SpringDoc与Sa-Token的集成
This commit is contained in:
parent
5ba051c16a
commit
71bf1f6645
18
.editorconfig
Normal file
18
.editorconfig
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# 空格替代Tab缩进在各种编辑工具下效果一致
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{json,yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
insert_final_newline = false
|
||||||
|
trim_trailing_whitespace = false
|
4
pom.xml
4
pom.xml
@ -28,8 +28,8 @@
|
|||||||
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
|
<pagehelper.boot.version>1.4.6</pagehelper.boot.version>
|
||||||
<pagehelper.version>5.3.3</pagehelper.version>
|
<pagehelper.version>5.3.3</pagehelper.version>
|
||||||
<fastjson.version>2.0.34</fastjson.version>
|
<fastjson.version>2.0.34</fastjson.version>
|
||||||
<oshi.version>6.4.3</oshi.version>
|
<oshi.version>6.4.4</oshi.version>
|
||||||
<commons.io.version>2.11.0</commons.io.version>
|
<commons.io.version>2.13.0</commons.io.version>
|
||||||
<commons.collections.version>3.2.2</commons.collections.version>
|
<commons.collections.version>3.2.2</commons.collections.version>
|
||||||
<poi.version>5.2.3</poi.version>
|
<poi.version>5.2.3</poi.version>
|
||||||
<easyexcel.version>3.3.2</easyexcel.version>
|
<easyexcel.version>3.3.2</easyexcel.version>
|
||||||
|
@ -70,11 +70,6 @@ public class CaptchaController
|
|||||||
}
|
}
|
||||||
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||||
|
|
||||||
// AjaxResult ajax = AjaxResult.success();
|
|
||||||
// ajax.put("uuid", uuid);
|
|
||||||
// ajax.put("img", captcha.getImageBase64());
|
|
||||||
// return ajax;
|
|
||||||
|
|
||||||
captchaVo.setUuid(uuid);
|
captchaVo.setUuid(uuid);
|
||||||
captchaVo.setImg(captcha.getImageBase64());
|
captchaVo.setImg(captcha.getImageBase64());
|
||||||
return AjaxResult.success(captchaVo);
|
return AjaxResult.success(captchaVo);
|
||||||
|
@ -118,7 +118,7 @@ pagehelper:
|
|||||||
# SpringDoc配置
|
# SpringDoc配置
|
||||||
springdoc:
|
springdoc:
|
||||||
#需要扫描的包,可以配置多个,使用逗号分割
|
#需要扫描的包,可以配置多个,使用逗号分割
|
||||||
packages-to-scan: com.ruoyi.demo
|
packages-to-scan: com.ruoyi
|
||||||
paths-to-exclude: #配置不包含在swagger文档中的api
|
paths-to-exclude: #配置不包含在swagger文档中的api
|
||||||
- /api/test/**
|
- /api/test/**
|
||||||
- /api/mockito/data
|
- /api/mockito/data
|
||||||
@ -145,13 +145,22 @@ springdoc:
|
|||||||
name: 数据小王子
|
name: 数据小王子
|
||||||
email: 738981257@qq.com
|
email: 738981257@qq.com
|
||||||
url: https://gitee.com/dataprince/ruoyi-flex
|
url: https://gitee.com/dataprince/ruoyi-flex
|
||||||
components:
|
components:
|
||||||
# 鉴权方式配置
|
# 鉴权方式配置
|
||||||
security-schemes:
|
security-schemes:
|
||||||
apiKey:
|
apiKey:
|
||||||
type: APIKEY
|
type: APIKEY
|
||||||
in: HEADER
|
in: HEADER
|
||||||
name: ${sa-token.token-name}
|
name: ${sa-token.token-name}
|
||||||
|
group-configs:
|
||||||
|
- group: 1.演示模块
|
||||||
|
packages-to-scan: com.ruoyi.demo
|
||||||
|
- group: 2.通用模块
|
||||||
|
packages-to-scan: com.ruoyi.common
|
||||||
|
- group: 3.系统模块
|
||||||
|
packages-to-scan: com.ruoyi.system
|
||||||
|
- group: 4.代码生成模块
|
||||||
|
packages-to-scan: com.ruoyi.generator
|
||||||
|
|
||||||
# 防止XSS攻击
|
# 防止XSS攻击
|
||||||
xss:
|
xss:
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package com.ruoyi.common.core.utils.poi;
|
package com.ruoyi.common.core.utils.poi;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
|
import org.apache.poi.ss.usermodel.Workbook;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Excel数据格式处理适配器
|
* Excel数据格式处理适配器
|
||||||
*
|
*
|
||||||
@ -12,8 +15,10 @@ public interface ExcelHandlerAdapter
|
|||||||
*
|
*
|
||||||
* @param value 单元格数据值
|
* @param value 单元格数据值
|
||||||
* @param args excel注解args参数组
|
* @param args excel注解args参数组
|
||||||
|
* @param cell 单元格对象
|
||||||
|
* @param wb 工作簿对象
|
||||||
*
|
*
|
||||||
* @return 处理后的值
|
* @return 处理后的值
|
||||||
*/
|
*/
|
||||||
Object format(Object value, String[] args);
|
Object format(Object value, String[] args, Cell cell, Workbook wb);
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,10 @@
|
|||||||
</description>
|
</description>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
<!-- springdoc -->
|
<!-- springdoc -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
package com.ruoyi.common.security;
|
|
||||||
|
|
||||||
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.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SpringDoc API文档相关配置
|
|
||||||
* @author 数据小王子 on 2023/07/24.
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class SpringDocConfig {
|
|
||||||
@Bean
|
|
||||||
public OpenAPI openAPI() {
|
|
||||||
SecurityRequirement securityRequirement = new SecurityRequirement().addList("Authorization"); // 名字和创建的SecuritySchemes一致
|
|
||||||
List<SecurityRequirement> list = new ArrayList<>();
|
|
||||||
list.add(securityRequirement);
|
|
||||||
return new OpenAPI()
|
|
||||||
.components(new Components().addSecuritySchemes("Authorization", // key值
|
|
||||||
new SecurityScheme()
|
|
||||||
.type(SecurityScheme.Type.APIKEY) //请求认证类型
|
|
||||||
.scheme("bearer").bearerFormat("JWT")
|
|
||||||
.name("Authorization") //API key参数名
|
|
||||||
.description("token令牌") //API key描述
|
|
||||||
.in(SecurityScheme.In.HEADER))) //设置API key的存放位置
|
|
||||||
.security(list)
|
|
||||||
.info(new Info().title("Ruoyi-Flex API Doc")
|
|
||||||
.description("Ruoyi-Flex SrpingDoc demo")
|
|
||||||
.version("v4.1.2")
|
|
||||||
.license(new License().name("MIT").url("https://opensource.org/licenses/MIT")))
|
|
||||||
.externalDocs(new ExternalDocumentation()
|
|
||||||
.description("Ruoyi-Flex Wiki Documentation")
|
|
||||||
.url("https://gitee.com/dataprince/ruoyi-flex"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,128 @@
|
|||||||
|
package com.ruoyi.common.springdoc.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.springdoc.handler.OpenApiHandler;
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.Paths;
|
||||||
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import com.ruoyi.common.springdoc.config.properties.SpringDocProperties;
|
||||||
|
import org.springdoc.core.configuration.SpringDocConfiguration;
|
||||||
|
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
||||||
|
import org.springdoc.core.customizers.OpenApiCustomizer;
|
||||||
|
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
||||||
|
import org.springdoc.core.properties.SpringDocConfigProperties;
|
||||||
|
import org.springdoc.core.providers.JavadocProvider;
|
||||||
|
import org.springdoc.core.service.OpenAPIService;
|
||||||
|
import org.springdoc.core.service.SecurityService;
|
||||||
|
import org.springdoc.core.utils.PropertyResolverUtils;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SpringDoc API文档相关配置
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@AutoConfiguration(before = SpringDocConfiguration.class)
|
||||||
|
@EnableConfigurationProperties(SpringDocProperties.class)
|
||||||
|
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
@Configuration
|
||||||
|
public class SpringDocConfig {
|
||||||
|
|
||||||
|
private final ServerProperties serverProperties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean(OpenAPI.class)
|
||||||
|
public OpenAPI openApi(SpringDocProperties properties) {
|
||||||
|
OpenAPI openApi = new OpenAPI();
|
||||||
|
// 文档基本信息
|
||||||
|
SpringDocProperties.InfoProperties infoProperties = properties.getInfo();
|
||||||
|
Info info = convertInfo(infoProperties);
|
||||||
|
openApi.info(info);
|
||||||
|
// 扩展文档信息
|
||||||
|
openApi.externalDocs(properties.getExternalDocs());
|
||||||
|
openApi.tags(properties.getTags());
|
||||||
|
openApi.paths(properties.getPaths());
|
||||||
|
openApi.components(properties.getComponents());
|
||||||
|
Set<String> keySet = properties.getComponents().getSecuritySchemes().keySet();
|
||||||
|
List<SecurityRequirement> list = new ArrayList<>();
|
||||||
|
SecurityRequirement securityRequirement = new SecurityRequirement();
|
||||||
|
keySet.forEach(securityRequirement::addList);
|
||||||
|
list.add(securityRequirement);
|
||||||
|
openApi.security(list);
|
||||||
|
|
||||||
|
return openApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Info convertInfo(SpringDocProperties.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对已经生成好的 OpenApi 进行自定义操作
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public OpenApiCustomizer openApiCustomizer() {
|
||||||
|
String contextPath = serverProperties.getServlet().getContextPath();
|
||||||
|
String finalContextPath;
|
||||||
|
if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) {
|
||||||
|
finalContextPath = "";
|
||||||
|
} else {
|
||||||
|
finalContextPath = contextPath;
|
||||||
|
}
|
||||||
|
// 对所有路径增加前置上下文路径
|
||||||
|
return openApi -> {
|
||||||
|
Paths oldPaths = openApi.getPaths();
|
||||||
|
if (oldPaths instanceof PlusPaths) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PlusPaths newPaths = new PlusPaths();
|
||||||
|
oldPaths.forEach((k, v) -> newPaths.addPathItem(finalContextPath + k, v));
|
||||||
|
openApi.setPaths(newPaths);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单独使用一个类便于判断 解决springdoc路径拼接重复问题
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
static class PlusPaths extends Paths {
|
||||||
|
|
||||||
|
public PlusPaths() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
package com.ruoyi.common.springdoc.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 = "springdoc")
|
||||||
|
public class SpringDocProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文档基本信息
|
||||||
|
*/
|
||||||
|
@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,252 @@
|
|||||||
|
package com.ruoyi.common.springdoc.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 lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
||||||
|
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
||||||
|
import org.springdoc.core.properties.SpringDocConfigProperties;
|
||||||
|
import org.springdoc.core.providers.JavadocProvider;
|
||||||
|
import org.springdoc.core.service.OpenAPIService;
|
||||||
|
import org.springdoc.core.service.SecurityService;
|
||||||
|
import org.springdoc.core.utils.PropertyResolverUtils;
|
||||||
|
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 处理器
|
||||||
|
* 对源码功能进行修改 增强使用
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public class OpenApiHandler extends OpenAPIService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Basic error controller.
|
||||||
|
*/
|
||||||
|
private static Class<?> basicErrorController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 Cached open api map.
|
||||||
|
*/
|
||||||
|
private final Map<String, OpenAPI> cachedOpenAPI = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Property resolver utils.
|
||||||
|
*/
|
||||||
|
private final PropertyResolverUtils propertyResolverUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The javadoc provider.
|
||||||
|
*/
|
||||||
|
private final Optional<JavadocProvider> javadocProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Context.
|
||||||
|
*/
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Open api.
|
||||||
|
*/
|
||||||
|
private OpenAPI openAPI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Is servers present.
|
||||||
|
*/
|
||||||
|
private boolean isServersPresent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Server base url.
|
||||||
|
*/
|
||||||
|
private String serverBaseUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.springdoc.config.SpringDocConfig
|
Loading…
Reference in New Issue
Block a user