add 新增 ruoyi-common-doc 整合 springdoc 基于 javadoc 实现无注解零入侵生成接口文档
parent
9256e938c6
commit
bbec3b5d8d
|
|
@ -63,10 +63,6 @@ dubbo:
|
||||||
log-level: info
|
log-level: info
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
mvc:
|
|
||||||
pathmatch:
|
|
||||||
# 适配 boot 2.6 路由与 springfox 兼容
|
|
||||||
matching-strategy: ANT_PATH_MATCHER
|
|
||||||
# 资源信息
|
# 资源信息
|
||||||
messages:
|
messages:
|
||||||
# 国际化资源文件路径
|
# 国际化资源文件路径
|
||||||
|
|
@ -242,17 +238,25 @@ mybatis-plus:
|
||||||
swagger:
|
swagger:
|
||||||
# 是否开启swagger
|
# 是否开启swagger
|
||||||
enabled: true
|
enabled: true
|
||||||
# 标题
|
info:
|
||||||
title: '标题:RuoYi-Cloud-Plus微服务权限管理系统_接口文档'
|
# 标题
|
||||||
# 描述
|
title: '标题:RuoYi-Cloud-Plus微服务权限管理系统_接口文档'
|
||||||
description: '描述:微服务权限管理系统, 具体包括XXX,XXX模块...'
|
# 描述
|
||||||
# 版本
|
description: '描述:微服务权限管理系统, 具体包括XXX,XXX模块...'
|
||||||
version: '版本号:系统版本...'
|
# 版本
|
||||||
# 作者信息
|
version: '版本号:系统版本...'
|
||||||
contact:
|
# 作者信息
|
||||||
name: Lion Li
|
contact:
|
||||||
email: crazylionli@163.com
|
name: Lion Li
|
||||||
url: https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus
|
email: crazylionli@163.com
|
||||||
|
url: https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus
|
||||||
|
components:
|
||||||
|
# 鉴权方式配置
|
||||||
|
security-schemes:
|
||||||
|
apiKey:
|
||||||
|
type: APIKEY
|
||||||
|
in: HEADER
|
||||||
|
name: ${sa-token.token-name}
|
||||||
|
|
||||||
# seata配置
|
# seata配置
|
||||||
seata:
|
seata:
|
||||||
|
|
|
||||||
44
pom.xml
44
pom.xml
|
|
@ -28,6 +28,8 @@
|
||||||
<dynamic-ds.version>3.5.1</dynamic-ds.version>
|
<dynamic-ds.version>3.5.1</dynamic-ds.version>
|
||||||
<velocity.version>2.3</velocity.version>
|
<velocity.version>2.3</velocity.version>
|
||||||
<fastjson.version>1.2.83</fastjson.version>
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
|
<swagger.core.version>2.2.0</swagger.core.version>
|
||||||
|
<springdoc.version>1.6.9</springdoc.version>
|
||||||
<poi.version>5.2.2</poi.version>
|
<poi.version>5.2.2</poi.version>
|
||||||
<easyexcel.version>3.1.1</easyexcel.version>
|
<easyexcel.version>3.1.1</easyexcel.version>
|
||||||
<hutool.version>5.8.4</hutool.version>
|
<hutool.version>5.8.4</hutool.version>
|
||||||
|
|
@ -35,6 +37,7 @@
|
||||||
<lock4j.version>2.2.2</lock4j.version>
|
<lock4j.version>2.2.2</lock4j.version>
|
||||||
<xxl-job.version>2.3.1</xxl-job.version>
|
<xxl-job.version>2.3.1</xxl-job.version>
|
||||||
<satoken.version>1.30.0</satoken.version>
|
<satoken.version>1.30.0</satoken.version>
|
||||||
|
<lombok.version>1.18.24</lombok.version>
|
||||||
<logstash.version>7.1.1</logstash.version>
|
<logstash.version>7.1.1</logstash.version>
|
||||||
|
|
||||||
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
|
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
|
||||||
|
|
@ -178,6 +181,30 @@
|
||||||
<version>${p6spy.version}</version>
|
<version>${p6spy.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger.core.v3</groupId>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
<version>${swagger.core.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-webmvc-core</artifactId>
|
||||||
|
<version>${springdoc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-javadoc</artifactId>
|
||||||
|
<version>${springdoc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.poi</groupId>
|
||||||
<artifactId>poi</artifactId>
|
<artifactId>poi</artifactId>
|
||||||
|
|
@ -300,6 +327,23 @@
|
||||||
<source>${java.version}</source>
|
<source>${java.version}</source>
|
||||||
<target>${java.version}</target>
|
<target>${java.version}</target>
|
||||||
<encoding>${project.build.sourceEncoding}</encoding>
|
<encoding>${project.build.sourceEncoding}</encoding>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>com.github.therapi</groupId>
|
||||||
|
<artifactId>therapi-runtime-javadoc-scribe</artifactId>
|
||||||
|
<version>0.13.0</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,11 @@
|
||||||
<artifactId>ruoyi-common-security</artifactId>
|
<artifactId>ruoyi-common-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common-web</artifactId>
|
<artifactId>ruoyi-common-web</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
<module>ruoyi-common-excel</module>
|
<module>ruoyi-common-excel</module>
|
||||||
<module>ruoyi-common-core</module>
|
<module>ruoyi-common-core</module>
|
||||||
<module>ruoyi-common-redis</module>
|
<module>ruoyi-common-redis</module>
|
||||||
|
<module>ruoyi-common-doc</module>
|
||||||
<module>ruoyi-common-security</module>
|
<module>ruoyi-common-security</module>
|
||||||
<module>ruoyi-common-satoken</module>
|
<module>ruoyi-common-satoken</module>
|
||||||
<module>ruoyi-common-web</module>
|
<module>ruoyi-common-web</module>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,13 @@
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 接口模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 安全模块 -->
|
<!-- 安全模块 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,11 @@
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger.core.v3</groupId>
|
||||||
|
<artifactId>swagger-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<artifactId>ruoyi-common-swagger</artifactId>
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
|
||||||
<description>
|
<description>
|
||||||
ruoyi-common-swagger系统接口
|
ruoyi-common-swagger系统接口
|
||||||
|
|
@ -23,15 +23,14 @@
|
||||||
<artifactId>ruoyi-common-core</artifactId>
|
<artifactId>ruoyi-common-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- SpringBoot Web -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>ruoyi-common-web</artifactId>
|
<artifactId>springdoc-openapi-webmvc-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.dev33</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>sa-token-core</artifactId>
|
<artifactId>springdoc-openapi-javadoc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
package com.ruoyi.common.doc.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.doc.handler.OpenApiHandler;
|
||||||
|
import com.ruoyi.common.doc.config.properties.SwaggerProperties;
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springdoc.core.*;
|
||||||
|
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
||||||
|
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
||||||
|
import org.springdoc.core.providers.JavadocProvider;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swagger 文档配置
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@AutoConfiguration(before = SpringDocConfiguration.class)
|
||||||
|
@EnableConfigurationProperties(SwaggerProperties.class)
|
||||||
|
@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
public class SwaggerAutoConfiguration {
|
||||||
|
|
||||||
|
private final SwaggerProperties swaggerProperties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(OpenAPI.class)
|
||||||
|
public OpenAPI openApi() {
|
||||||
|
OpenAPI openApi = new OpenAPI();
|
||||||
|
// 文档基本信息
|
||||||
|
SwaggerProperties.InfoProperties infoProperties = swaggerProperties.getInfo();
|
||||||
|
Info info = convertInfo(infoProperties);
|
||||||
|
openApi.info(info);
|
||||||
|
// 扩展文档信息
|
||||||
|
openApi.externalDocs(swaggerProperties.getExternalDocs());
|
||||||
|
openApi.tags(swaggerProperties.getTags());
|
||||||
|
openApi.paths(swaggerProperties.getPaths());
|
||||||
|
openApi.components(swaggerProperties.getComponents());
|
||||||
|
List<SecurityRequirement> list = new ArrayList<>();
|
||||||
|
list.add(new SecurityRequirement().addList("apikey"));
|
||||||
|
openApi.security(list);
|
||||||
|
|
||||||
|
return openApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Info convertInfo(SwaggerProperties.InfoProperties infoProperties) {
|
||||||
|
Info info = new Info();
|
||||||
|
info.setTitle(infoProperties.getTitle());
|
||||||
|
info.setDescription(infoProperties.getDescription());
|
||||||
|
info.setContact(infoProperties.getContact());
|
||||||
|
info.setLicense(infoProperties.getLicense());
|
||||||
|
info.setVersion(infoProperties.getVersion());
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 openapi 处理器
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
|
||||||
|
SecurityService securityParser,
|
||||||
|
SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
|
||||||
|
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers,
|
||||||
|
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider) {
|
||||||
|
return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
package com.ruoyi.common.doc.config.properties;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.Components;
|
||||||
|
import io.swagger.v3.oas.models.ExternalDocumentation;
|
||||||
|
import io.swagger.v3.oas.models.Paths;
|
||||||
|
import io.swagger.v3.oas.models.info.Contact;
|
||||||
|
import io.swagger.v3.oas.models.info.License;
|
||||||
|
import io.swagger.v3.oas.models.tags.Tag;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.NestedConfigurationProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* swagger 配置属性
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties(prefix = "swagger")
|
||||||
|
public class SwaggerProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启 openApi 文档
|
||||||
|
*/
|
||||||
|
private Boolean enabled = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档基本信息
|
||||||
|
*/
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private InfoProperties info = new InfoProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展文档地址
|
||||||
|
*/
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private ExternalDocumentation externalDocs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标签
|
||||||
|
*/
|
||||||
|
private List<Tag> tags = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 路径
|
||||||
|
*/
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private Paths paths = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件
|
||||||
|
*/
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private Components components = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 文档的基础属性信息
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see io.swagger.v3.oas.models.info.Info
|
||||||
|
*
|
||||||
|
* 为了 springboot 自动生产配置提示信息,所以这里复制一个类出来
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class InfoProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
|
private String title = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 描述
|
||||||
|
*/
|
||||||
|
private String description = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系人信息
|
||||||
|
*/
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private Contact contact = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 许可证
|
||||||
|
*/
|
||||||
|
@NestedConfigurationProperty
|
||||||
|
private License license = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本
|
||||||
|
*/
|
||||||
|
private String version = null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,272 @@
|
||||||
|
package com.ruoyi.common.doc.handler;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
|
import io.swagger.v3.core.jackson.TypeNameResolver;
|
||||||
|
import io.swagger.v3.core.util.AnnotationsUtils;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tags;
|
||||||
|
import io.swagger.v3.oas.models.Components;
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.Operation;
|
||||||
|
import io.swagger.v3.oas.models.Paths;
|
||||||
|
import io.swagger.v3.oas.models.tags.Tag;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springdoc.core.OpenAPIService;
|
||||||
|
import org.springdoc.core.PropertyResolverUtils;
|
||||||
|
import org.springdoc.core.SecurityService;
|
||||||
|
import org.springdoc.core.SpringDocConfigProperties;
|
||||||
|
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
||||||
|
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
||||||
|
import org.springdoc.core.providers.JavadocProvider;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义 openapi 处理器
|
||||||
|
* 对源码功能进行修改 增强使用
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public class OpenApiHandler extends OpenAPIService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constant LOGGER.
|
||||||
|
*/
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIService.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Context.
|
||||||
|
*/
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Security parser.
|
||||||
|
*/
|
||||||
|
private final SecurityService securityParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Mappings map.
|
||||||
|
*/
|
||||||
|
private final Map<String, Object> mappingsMap = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Springdoc tags.
|
||||||
|
*/
|
||||||
|
private final Map<HandlerMethod, Tag> springdocTags = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Open api builder customisers.
|
||||||
|
*/
|
||||||
|
private final Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server base URL customisers.
|
||||||
|
*/
|
||||||
|
private final Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Spring doc config properties.
|
||||||
|
*/
|
||||||
|
private final SpringDocConfigProperties springDocConfigProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Open api.
|
||||||
|
*/
|
||||||
|
private OpenAPI openAPI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Cached open api map.
|
||||||
|
*/
|
||||||
|
private final Map<String, OpenAPI> cachedOpenAPI = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Is servers present.
|
||||||
|
*/
|
||||||
|
private boolean isServersPresent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Server base url.
|
||||||
|
*/
|
||||||
|
private String serverBaseUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Property resolver utils.
|
||||||
|
*/
|
||||||
|
private final PropertyResolverUtils propertyResolverUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The javadoc provider.
|
||||||
|
*/
|
||||||
|
private final Optional<JavadocProvider> javadocProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Basic error controller.
|
||||||
|
*/
|
||||||
|
private static Class<?> basicErrorController;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
//spring-boot 2
|
||||||
|
basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
//spring-boot 1
|
||||||
|
try {
|
||||||
|
basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.BasicErrorController");
|
||||||
|
} catch (ClassNotFoundException classNotFoundException) {
|
||||||
|
//Basic error controller class not found
|
||||||
|
LOGGER.trace(classNotFoundException.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Open api builder.
|
||||||
|
*
|
||||||
|
* @param openAPI the open api
|
||||||
|
* @param securityParser the security parser
|
||||||
|
* @param springDocConfigProperties the spring doc config properties
|
||||||
|
* @param propertyResolverUtils the property resolver utils
|
||||||
|
* @param openApiBuilderCustomizers the open api builder customisers
|
||||||
|
* @param serverBaseUrlCustomizers the server base url customizers
|
||||||
|
* @param javadocProvider the javadoc provider
|
||||||
|
*/
|
||||||
|
public OpenApiHandler(Optional<OpenAPI> openAPI, SecurityService securityParser,
|
||||||
|
SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
|
||||||
|
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
|
||||||
|
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
|
||||||
|
Optional<JavadocProvider> javadocProvider) {
|
||||||
|
super(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);
|
||||||
|
if (openAPI.isPresent()) {
|
||||||
|
this.openAPI = openAPI.get();
|
||||||
|
if (this.openAPI.getComponents() == null)
|
||||||
|
this.openAPI.setComponents(new Components());
|
||||||
|
if (this.openAPI.getPaths() == null)
|
||||||
|
this.openAPI.setPaths(new Paths());
|
||||||
|
if (!CollectionUtils.isEmpty(this.openAPI.getServers()))
|
||||||
|
this.isServersPresent = true;
|
||||||
|
}
|
||||||
|
this.propertyResolverUtils = propertyResolverUtils;
|
||||||
|
this.securityParser = securityParser;
|
||||||
|
this.springDocConfigProperties = springDocConfigProperties;
|
||||||
|
this.openApiBuilderCustomisers = openApiBuilderCustomizers;
|
||||||
|
this.serverBaseUrlCustomizers = serverBaseUrlCustomizers;
|
||||||
|
this.javadocProvider = javadocProvider;
|
||||||
|
if (springDocConfigProperties.isUseFqn())
|
||||||
|
TypeNameResolver.std.setUseFqn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) {
|
||||||
|
|
||||||
|
Set<Tag> tags = new HashSet<>();
|
||||||
|
Set<String> tagsStr = new HashSet<>();
|
||||||
|
|
||||||
|
buildTagsFromMethod(handlerMethod.getMethod(), tags, tagsStr, locale);
|
||||||
|
buildTagsFromClass(handlerMethod.getBeanType(), tags, tagsStr, locale);
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(tagsStr))
|
||||||
|
tagsStr = tagsStr.stream()
|
||||||
|
.map(str -> propertyResolverUtils.resolve(str, locale))
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
if (springdocTags.containsKey(handlerMethod)) {
|
||||||
|
Tag tag = springdocTags.get(handlerMethod);
|
||||||
|
tagsStr.add(tag.getName());
|
||||||
|
if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
|
||||||
|
openAPI.addTagsItem(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(tagsStr)) {
|
||||||
|
if (CollectionUtils.isEmpty(operation.getTags()))
|
||||||
|
operation.setTags(new ArrayList<>(tagsStr));
|
||||||
|
else {
|
||||||
|
Set<String> operationTagsSet = new HashSet<>(operation.getTags());
|
||||||
|
operationTagsSet.addAll(tagsStr);
|
||||||
|
operation.getTags().clear();
|
||||||
|
operation.getTags().addAll(operationTagsSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAutoTagClasses(operation)) {
|
||||||
|
|
||||||
|
|
||||||
|
if (javadocProvider.isPresent()) {
|
||||||
|
String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType());
|
||||||
|
if (StringUtils.isNotBlank(description)) {
|
||||||
|
Tag tag = new Tag();
|
||||||
|
|
||||||
|
// 自定义部分 修改使用java注释当tag名
|
||||||
|
List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>());
|
||||||
|
// tag.setName(tagAutoName);
|
||||||
|
tag.setName(list.get(0));
|
||||||
|
operation.addTagsItem(list.get(0));
|
||||||
|
|
||||||
|
tag.setDescription(description);
|
||||||
|
if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
|
||||||
|
openAPI.addTagsItem(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String tagAutoName = splitCamelCase(handlerMethod.getBeanType().getSimpleName());
|
||||||
|
operation.addTagsItem(tagAutoName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(tags)) {
|
||||||
|
// Existing tags
|
||||||
|
List<Tag> openApiTags = openAPI.getTags();
|
||||||
|
if (!CollectionUtils.isEmpty(openApiTags))
|
||||||
|
tags.addAll(openApiTags);
|
||||||
|
openAPI.setTags(new ArrayList<>(tags));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle SecurityRequirement at operation level
|
||||||
|
io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser
|
||||||
|
.getSecurityRequirements(handlerMethod);
|
||||||
|
if (securityRequirements != null) {
|
||||||
|
if (securityRequirements.length == 0)
|
||||||
|
operation.setSecurity(Collections.emptyList());
|
||||||
|
else
|
||||||
|
securityParser.buildSecurityRequirement(securityRequirements, operation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buildTagsFromMethod(Method method, Set<Tag> tags, Set<String> tagsStr, Locale locale) {
|
||||||
|
// method tags
|
||||||
|
Set<Tags> tagsSet = AnnotatedElementUtils
|
||||||
|
.findAllMergedAnnotations(method, Tags.class);
|
||||||
|
Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream()
|
||||||
|
.flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet());
|
||||||
|
methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class));
|
||||||
|
if (!CollectionUtils.isEmpty(methodTags)) {
|
||||||
|
tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet()));
|
||||||
|
List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags);
|
||||||
|
addTags(allTags, tags, locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<Tag> tags, Locale locale) {
|
||||||
|
Optional<Set<Tag>> optionalTagSet = AnnotationsUtils
|
||||||
|
.getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true);
|
||||||
|
optionalTagSet.ifPresent(tagsSet -> {
|
||||||
|
tagsSet.forEach(tag -> {
|
||||||
|
tag.name(propertyResolverUtils.resolve(tag.getName(), locale));
|
||||||
|
tag.description(propertyResolverUtils.resolve(tag.getDescription(), locale));
|
||||||
|
if (tags.stream().noneMatch(t -> t.getName().equals(tag.getName())))
|
||||||
|
tags.add(tag);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
com.ruoyi.common.doc.config.SwaggerAutoConfiguration
|
||||||
|
|
@ -1,133 +0,0 @@
|
||||||
package com.ruoyi.common.swagger.config;
|
|
||||||
|
|
||||||
import cn.dev33.satoken.config.SaTokenConfig;
|
|
||||||
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
|
|
||||||
import com.ruoyi.common.core.utils.StringUtils;
|
|
||||||
import com.ruoyi.common.swagger.config.properties.SwaggerProperties;
|
|
||||||
import io.swagger.models.auth.In;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import springfox.documentation.builders.ApiInfoBuilder;
|
|
||||||
import springfox.documentation.builders.PathSelectors;
|
|
||||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
|
||||||
import springfox.documentation.service.*;
|
|
||||||
import springfox.documentation.spi.DocumentationType;
|
|
||||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
|
||||||
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
|
|
||||||
import springfox.documentation.spring.web.plugins.Docket;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Swagger 文档配置
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@AutoConfiguration
|
|
||||||
@EnableKnife4j
|
|
||||||
@EnableConfigurationProperties(SwaggerProperties.class)
|
|
||||||
@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
|
|
||||||
public class SwaggerAutoConfiguration {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private SaTokenConfig saTokenConfig;
|
|
||||||
|
|
||||||
@Value("${spring.application.name}")
|
|
||||||
private String appName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 默认的排除路径,排除Spring Boot默认的错误处理路径和端点
|
|
||||||
*/
|
|
||||||
private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**");
|
|
||||||
|
|
||||||
private static final String BASE_PATH = "/**";
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public Docket api(SwaggerProperties swaggerProperties) {
|
|
||||||
// base-path处理
|
|
||||||
if (swaggerProperties.getBasePath().isEmpty()) {
|
|
||||||
swaggerProperties.getBasePath().add(BASE_PATH);
|
|
||||||
}
|
|
||||||
// noinspection unchecked
|
|
||||||
List<Predicate<String>> basePath = new ArrayList<>();
|
|
||||||
swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path)));
|
|
||||||
|
|
||||||
// exclude-path处理
|
|
||||||
if (swaggerProperties.getExcludePath().isEmpty()) {
|
|
||||||
swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Predicate<String>> excludePath = new ArrayList<>();
|
|
||||||
swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path)));
|
|
||||||
|
|
||||||
ApiSelectorBuilder builder = new Docket(DocumentationType.OAS_30)
|
|
||||||
.enable(swaggerProperties.getEnabled())
|
|
||||||
.host(swaggerProperties.getHost())
|
|
||||||
.apiInfo(apiInfo(swaggerProperties))
|
|
||||||
.select()
|
|
||||||
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()));
|
|
||||||
|
|
||||||
swaggerProperties.getBasePath().forEach(p -> builder.paths(PathSelectors.ant(p)));
|
|
||||||
swaggerProperties.getExcludePath().forEach(p -> builder.paths(PathSelectors.ant(p).negate()));
|
|
||||||
|
|
||||||
return builder.build()
|
|
||||||
.securitySchemes(securitySchemes())
|
|
||||||
.securityContexts(securityContexts())
|
|
||||||
.pathMapping(StringUtils.substring(appName, appName.indexOf("-") + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 安全模式,这里指定token通过Authorization头请求头传递
|
|
||||||
*/
|
|
||||||
private List<SecurityScheme> securitySchemes() {
|
|
||||||
List<SecurityScheme> apiKeyList = new ArrayList<>();
|
|
||||||
String header = saTokenConfig.getTokenName();
|
|
||||||
apiKeyList.add(new ApiKey(header, header, In.HEADER.toValue()));
|
|
||||||
return apiKeyList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 安全上下文
|
|
||||||
*/
|
|
||||||
private List<SecurityContext> securityContexts() {
|
|
||||||
List<SecurityContext> securityContexts = new ArrayList<>();
|
|
||||||
securityContexts.add(
|
|
||||||
SecurityContext.builder()
|
|
||||||
.securityReferences(defaultAuth())
|
|
||||||
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
|
|
||||||
.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(saTokenConfig.getTokenName(), authorizationScopes));
|
|
||||||
return securityReferences;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
|
|
||||||
return new ApiInfoBuilder()
|
|
||||||
.title(swaggerProperties.getTitle())
|
|
||||||
.description(swaggerProperties.getDescription())
|
|
||||||
.license(swaggerProperties.getLicense())
|
|
||||||
.licenseUrl(swaggerProperties.getLicenseUrl())
|
|
||||||
.termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
|
|
||||||
.contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
|
|
||||||
.version(swaggerProperties.getVersion())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package com.ruoyi.common.swagger.config;
|
|
||||||
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
|
|
||||||
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
|
|
||||||
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* swagger 在 springboot 2.6.x 不兼容问题的处理
|
|
||||||
*
|
|
||||||
* @author ruoyi
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public class SwaggerBeanPostProcessor 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) {
|
|
||||||
mappings.removeIf(mapping -> mapping.getPatternParser() != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
package com.ruoyi.common.swagger.config.properties;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* swagger 配置属性
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@ConfigurationProperties("swagger")
|
|
||||||
public class SwaggerProperties {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启swagger
|
|
||||||
*/
|
|
||||||
private Boolean enabled;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* swagger会解析的包路径
|
|
||||||
**/
|
|
||||||
private String basePackage = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* swagger会解析的url规则
|
|
||||||
**/
|
|
||||||
private List<String> basePath = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在basePath基础上需要排除的url规则
|
|
||||||
**/
|
|
||||||
private List<String> excludePath = new ArrayList<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标题
|
|
||||||
**/
|
|
||||||
private String title = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 描述
|
|
||||||
**/
|
|
||||||
private String description = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 版本
|
|
||||||
**/
|
|
||||||
private String version = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 许可证
|
|
||||||
**/
|
|
||||||
private String license = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 许可证URL
|
|
||||||
**/
|
|
||||||
private String licenseUrl = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 服务条款URL
|
|
||||||
**/
|
|
||||||
private String termsOfServiceUrl = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* host信息
|
|
||||||
**/
|
|
||||||
private String host = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 联系人信息
|
|
||||||
*/
|
|
||||||
private Contact contact = new Contact();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 全局统一鉴权配置
|
|
||||||
**/
|
|
||||||
private Authorization authorization = new Authorization();
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public static class Contact {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 联系人
|
|
||||||
**/
|
|
||||||
private String name = "";
|
|
||||||
/**
|
|
||||||
* 联系人url
|
|
||||||
**/
|
|
||||||
private String url = "";
|
|
||||||
/**
|
|
||||||
* 联系人email
|
|
||||||
**/
|
|
||||||
private String email = "";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public static class Authorization {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 鉴权策略ID,需要和SecurityReferences ID保持一致
|
|
||||||
*/
|
|
||||||
private String name = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 需要开启鉴权URL的正则
|
|
||||||
*/
|
|
||||||
private String authRegex = "^.*$";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 鉴权作用域列表
|
|
||||||
*/
|
|
||||||
private List<AuthorizationScope> authorizationScopeList = new ArrayList<>();
|
|
||||||
|
|
||||||
private List<String> tokenUrlList = new ArrayList<>();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public static class AuthorizationScope {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 作用域名称
|
|
||||||
*/
|
|
||||||
private String scope = "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 作用域描述
|
|
||||||
*/
|
|
||||||
private String description = "";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
com.ruoyi.common.swagger.config.SwaggerAutoConfiguration
|
|
||||||
com.ruoyi.common.swagger.config.SwaggerBeanPostProcessor
|
|
||||||
|
|
@ -52,6 +52,11 @@
|
||||||
<artifactId>ruoyi-common-log</artifactId>
|
<artifactId>ruoyi-common-log</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common-web</artifactId>
|
<artifactId>ruoyi-common-web</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,11 @@
|
||||||
<artifactId>ruoyi-common-security</artifactId>
|
<artifactId>ruoyi-common-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common-web</artifactId>
|
<artifactId>ruoyi-common-web</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
package com.ruoyi.gateway.handler;
|
package com.ruoyi.gateway.handler;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
import com.ruoyi.gateway.utils.WebFluxUtils;
|
import com.ruoyi.gateway.utils.WebFluxUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||||
import org.springframework.cloud.gateway.support.NotFoundException;
|
import org.springframework.cloud.gateway.support.NotFoundException;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.annotation.Order;
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.server.RequestPath;
|
||||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
import org.springframework.web.server.ServerWebExchange;
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
|
@ -21,6 +23,8 @@ import reactor.core.publisher.Mono;
|
||||||
@Configuration
|
@Configuration
|
||||||
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
|
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
|
||||||
|
|
||||||
|
private static final String[] IGNORE_PATH = new String[]{"/favicon.ico"};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
|
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
|
||||||
ServerHttpResponse response = exchange.getResponse();
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
|
|
@ -40,7 +44,10 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
|
||||||
msg = "内部服务器错误";
|
msg = "内部服务器错误";
|
||||||
}
|
}
|
||||||
|
|
||||||
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
|
RequestPath path = exchange.getRequest().getPath();
|
||||||
|
if (!StringUtils.equalsAny(path.toString(), IGNORE_PATH)) {
|
||||||
|
log.error("[网关异常处理]请求路径:{},异常信息:{}", path, ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
return WebFluxUtils.webFluxResponseWriter(response, msg);
|
return WebFluxUtils.webFluxResponseWriter(response, msg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,11 @@
|
||||||
<artifactId>ruoyi-common-log</artifactId>
|
<artifactId>ruoyi-common-log</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common-web</artifactId>
|
<artifactId>ruoyi-common-web</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,11 @@
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common-dubbo</artifactId>
|
<artifactId>ruoyi-common-dubbo</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,11 @@
|
||||||
<artifactId>ruoyi-common-dict</artifactId>
|
<artifactId>ruoyi-common-dict</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-doc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-common-web</artifactId>
|
<artifactId>ruoyi-common-web</artifactId>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue