init
This commit is contained in:
@@ -0,0 +1,157 @@
|
||||
package cn.fateverse.common.swagger;
|
||||
|
||||
import cn.fateverse.common.swagger.aspect.SwaggerAspect;
|
||||
import cn.fateverse.common.swagger.config.SwaggerProperties;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.oas.annotations.EnableOpenApi;
|
||||
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.spring.web.plugins.WebFluxRequestHandlerProvider;
|
||||
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2023-05-21
|
||||
*/
|
||||
@EnableOpenApi
|
||||
@EnableConfigurationProperties(SwaggerProperties.class)
|
||||
public class SwaggerAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public SwaggerAspect swaggerAspect() {
|
||||
return new SwaggerAspect();
|
||||
}
|
||||
|
||||
/**
|
||||
* doc https://developer.aliyun.com/article/950787
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
|
||||
return getBeanPostProcessor();
|
||||
}
|
||||
|
||||
public static BeanPostProcessor getBeanPostProcessor() {
|
||||
return new 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) {
|
||||
List<T> copy = mappings.stream()
|
||||
.filter(mapping -> mapping.getPatternParser() == null)
|
||||
.collect(Collectors.toList());
|
||||
mappings.clear();
|
||||
mappings.addAll(copy);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
|
||||
try {
|
||||
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
|
||||
field.setAccessible(true);
|
||||
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
|
||||
} catch (IllegalArgumentException | IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi(SwaggerProperties properties) {
|
||||
return new Docket(DocumentationType.OAS_30)
|
||||
// 是否启用Swagger
|
||||
.enable(properties.isEnabled())
|
||||
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
|
||||
.apiInfo(apiInfo(properties))
|
||||
.select()
|
||||
// 扫描所有有注解的api,用这种方式更灵活
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
//.apis(RequestHandlerSelectors.withMethodAnnotation(Operation.class))
|
||||
// 扫描指定包中的swagger注解
|
||||
// .apis(RequestHandlerSelectors.basePackage("cn.fateverse.**.controller"))
|
||||
// 扫描所有
|
||||
//.apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
// 设置安全模式,swagger可以设置访问token
|
||||
.securitySchemes(securitySchemes(properties))
|
||||
.securityContexts(securityContexts())
|
||||
//请求映射路径
|
||||
.pathMapping("/");
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo(SwaggerProperties properties) {
|
||||
return new ApiInfoBuilder()
|
||||
// 页面标题
|
||||
.title(properties.getTitle())
|
||||
// 版本号
|
||||
.version(properties.getVersion())
|
||||
// 描述
|
||||
.description(properties.getDescription())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全模式,这里指定token通过Authorization头请求头传递
|
||||
*/
|
||||
private List<SecurityScheme> securitySchemes(SwaggerProperties properties) {
|
||||
ApiKey apiKey = new ApiKey("Authorization", properties.getHeader(), "header");
|
||||
return Collections.singletonList(apiKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全上下文
|
||||
*/
|
||||
private List<SecurityContext> securityContexts() {
|
||||
List<SecurityContext> securityContexts = new ArrayList<>();
|
||||
securityContexts.add(
|
||||
SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
//已过时
|
||||
//.forPaths(PathSelectors.regex("^(?!auth).*$"))
|
||||
.operationSelector(os ->
|
||||
os.requestMappingPattern().matches("^(?!auth).*$"))
|
||||
.build());
|
||||
return securityContexts;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 默认的安全上引用
|
||||
*/
|
||||
private List<SecurityReference> defaultAuth() {
|
||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||
authorizationScopes[0] = authorizationScope;
|
||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
|
||||
return securityReferences;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package cn.fateverse.common.swagger.aspect;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.fateverse.common.core.utils.HttpServletUtils;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.util.UriComponents;
|
||||
import springfox.documentation.spring.web.json.Json;
|
||||
import springfox.documentation.swagger.common.HostNameProvider;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* @author Clay
|
||||
* @date 2023-05-07
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
public class SwaggerAspect {
|
||||
|
||||
|
||||
@SneakyThrows
|
||||
@Around("execution(* springfox.documentation.oas.web.OpenApiControllerWebMvc.getDocumentation(..))")
|
||||
public Object around(ProceedingJoinPoint point) {
|
||||
ResponseEntity<Json> proceed = (ResponseEntity<Json>) point.proceed();
|
||||
String value = proceed.getBody().value();
|
||||
JSONObject object = JSON.parseObject(value);
|
||||
HttpServletRequest request = HttpServletUtils.getRequest();
|
||||
JSONArray servers = object.getJSONArray("servers");
|
||||
String basePath = null;
|
||||
JSONObject server = servers.getJSONObject(0);
|
||||
String path = server.getString("url");
|
||||
UriComponents uriComponents = HostNameProvider.componentsFrom(request, path);
|
||||
basePath = StrUtil.isEmpty(uriComponents.getPath()) ? "/" : uriComponents.getPath();
|
||||
//server.put("url", path + basePath);
|
||||
object.put("basePath", basePath);
|
||||
return new ResponseEntity<>(object.toString(), HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package cn.fateverse.common.swagger.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
|
||||
/**
|
||||
* swagger
|
||||
*
|
||||
* @author Clay
|
||||
* @date 2022/10/31
|
||||
*/
|
||||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "swagger")
|
||||
public class SwaggerProperties {
|
||||
|
||||
@Value("${token.header}")
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* title
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 版本号
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 是否开启swagger
|
||||
*/
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* swagger文档描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
|
||||
public String getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(String header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
cn.fateverse.common.swagger.SwaggerAutoConfiguration
|
||||
Reference in New Issue
Block a user