This commit is contained in:
clay
2024-03-06 17:44:09 +08:00
commit adaec0eadd
1493 changed files with 219939 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>common</artifactId>
<groupId>cn.fateverse</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>common-swagger</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<optional>true</optional>
</dependency>
<!--swagger 相关依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
</exclusion>
<exclusion>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>cn.fateverse</groupId>
<artifactId>common-core</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -0,0 +1 @@
cn.fateverse.common.swagger.SwaggerAutoConfiguration