mirror of
https://gitee.com/hhyykk/ipms-sjy.git
synced 2025-07-12 18:15:07 +08:00
refactor: springdoc 替换 springfox
This commit is contained in:
@ -1,119 +1,60 @@
|
||||
package cn.iocoder.yudao.framework.swagger.config;
|
||||
|
||||
import cn.iocoder.yudao.framework.swagger.core.SpringFoxHandlerProviderBeanPostProcessor;
|
||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
||||
import io.swagger.v3.oas.models.Components;
|
||||
import io.swagger.v3.oas.models.ExternalDocumentation;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.info.License;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ExampleBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestParameterBuilder;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||
import static springfox.documentation.builders.RequestHandlerSelectors.basePackage;
|
||||
|
||||
/**
|
||||
* Swagger2 自动配置类
|
||||
* Swagger3 自动配置类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableSwagger2
|
||||
@EnableKnife4j
|
||||
@ConditionalOnClass({Docket.class, ApiInfoBuilder.class})
|
||||
@ConditionalOnClass({OpenAPI.class})
|
||||
// 允许使用 swagger.enable=false 禁用 Swagger
|
||||
@ConditionalOnProperty(prefix = "yudao.swagger", value = "enable", matchIfMissing = true)
|
||||
@EnableConfigurationProperties(SwaggerProperties.class)
|
||||
public class YudaoSwaggerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public SpringFoxHandlerProviderBeanPostProcessor springFoxHandlerProviderBeanPostProcessor() {
|
||||
return new SpringFoxHandlerProviderBeanPostProcessor();
|
||||
public OpenAPI createRestApi(SwaggerProperties properties) {
|
||||
return new OpenAPI()
|
||||
.info(new Info().title(properties.getTitle())
|
||||
.description(properties.getDescription())
|
||||
.version(properties.getVersion())
|
||||
.license(new License().name("MIT").url("https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSE")))
|
||||
.externalDocs(new ExternalDocumentation()
|
||||
.description(properties.getDescription())
|
||||
.url("https://gitee.com/zhijiantianya/ruoyi-vue-pro"));
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi(SwaggerProperties properties) {
|
||||
// 创建 Docket 对象
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
// ① 用来创建该 API 的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||
.apiInfo(apiInfo(properties))
|
||||
// ② 设置扫描指定 package 包下的
|
||||
.select()
|
||||
.apis(basePackage(properties.getBasePackage()))
|
||||
// .apis(basePackage("cn.iocoder.yudao.module.system")) // 可用于 swagger 无法展示时使用
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
// ③ 安全上下文(认证)
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts())
|
||||
// ④ 全局参数(多租户 header)
|
||||
.globalRequestParameters(globalRequestParameters());
|
||||
}
|
||||
|
||||
// ========== apiInfo ==========
|
||||
|
||||
/**
|
||||
* API 摘要信息
|
||||
*/
|
||||
private static ApiInfo apiInfo(SwaggerProperties properties) {
|
||||
return new ApiInfoBuilder()
|
||||
.title(properties.getTitle())
|
||||
.description(properties.getDescription())
|
||||
.contact(new Contact(properties.getAuthor(), null, null))
|
||||
.version(properties.getVersion())
|
||||
public GroupedOpenApi publicApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("app")
|
||||
.pathsToMatch("/app/**")
|
||||
.build();
|
||||
}
|
||||
|
||||
// ========== securitySchemes ==========
|
||||
|
||||
/**
|
||||
* 安全模式,这里配置通过请求头 Authorization 传递 token 参数
|
||||
*/
|
||||
private static List<SecurityScheme> securitySchemes() {
|
||||
return Collections.singletonList(new ApiKey(HttpHeaders.AUTHORIZATION, "Authorization", "header"));
|
||||
@Bean
|
||||
public GroupedOpenApi adminApi() {
|
||||
return GroupedOpenApi.builder()
|
||||
.group("admin")
|
||||
.pathsToMatch("/admin/**")
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全上下文
|
||||
*
|
||||
* @see #securitySchemes()
|
||||
* @see #authorizationScopes()
|
||||
*/
|
||||
private static List<SecurityContext> securityContexts() {
|
||||
return Collections.singletonList(SecurityContext.builder()
|
||||
.securityReferences(securityReferences())
|
||||
// 通过 PathSelectors.regex("^(?!auth).*$"),排除包含 "auth" 的接口不需要使用securitySchemes
|
||||
.operationSelector(o -> o.requestMappingPattern().matches("^(?!auth).*$"))
|
||||
.build());
|
||||
}
|
||||
|
||||
private static List<SecurityReference> securityReferences() {
|
||||
return Collections.singletonList(new SecurityReference(HttpHeaders.AUTHORIZATION, authorizationScopes()));
|
||||
}
|
||||
|
||||
private static AuthorizationScope[] authorizationScopes() {
|
||||
return new AuthorizationScope[]{new AuthorizationScope("global", "accessEverything")};
|
||||
}
|
||||
|
||||
// ========== globalRequestParameters ==========
|
||||
|
||||
private static List<RequestParameter> globalRequestParameters() {
|
||||
RequestParameterBuilder tenantParameter = new RequestParameterBuilder()
|
||||
.name(HEADER_TENANT_ID).description("租户编号")
|
||||
.in(ParameterType.HEADER).example(new ExampleBuilder().value(1L).build());
|
||||
return Collections.singletonList(tenantParameter.build());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,43 +1,43 @@
|
||||
package cn.iocoder.yudao.framework.swagger.core;
|
||||
|
||||
import cn.hutool.core.util.ReflectUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
|
||||
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
|
||||
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题
|
||||
* 该问题对应的 issue 为 https://github.com/springfox/springfox/issues/3462
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public class SpringFoxHandlerProviderBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
|
||||
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
|
||||
// 移除,只保留 patternParser
|
||||
List<T> copy = CollectionUtils.filterList(mappings, mapping -> mapping.getPatternParser() == null);
|
||||
// 添加到 mappings 中
|
||||
mappings.clear();
|
||||
mappings.addAll(copy);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
|
||||
return (List<RequestMappingInfoHandlerMapping>)
|
||||
ReflectUtil.getFieldValue(bean, "handlerMappings");
|
||||
}
|
||||
|
||||
}
|
||||
//package cn.iocoder.yudao.framework.swagger.core;
|
||||
//
|
||||
//import cn.hutool.core.util.ReflectUtil;
|
||||
//import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
//import org.springframework.beans.BeansException;
|
||||
//import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
//import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
|
||||
//import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
|
||||
//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * 解决 SpringFox 与 SpringBoot 2.6.x 不兼容的问题
|
||||
// * 该问题对应的 issue 为 https://github.com/springfox/springfox/issues/3462
|
||||
// *
|
||||
// * @author 芋道源码
|
||||
// */
|
||||
//public class SpringFoxHandlerProviderBeanPostProcessor implements BeanPostProcessor {
|
||||
//
|
||||
// @Override
|
||||
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
// if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
|
||||
// customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
|
||||
// }
|
||||
// return bean;
|
||||
// }
|
||||
//
|
||||
// private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
|
||||
// // 移除,只保留 patternParser
|
||||
// List<T> copy = CollectionUtils.filterList(mappings, mapping -> mapping.getPatternParser() == null);
|
||||
// // 添加到 mappings 中
|
||||
// mappings.clear();
|
||||
// mappings.addAll(copy);
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
|
||||
// return (List<RequestMappingInfoHandlerMapping>)
|
||||
// ReflectUtil.getFieldValue(bean, "handlerMappings");
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
Reference in New Issue
Block a user