fix(接口文档): 修复接口文档/v3/api-docs无法正常访问

This commit is contained in:
ageer
2025-05-03 14:31:20 +08:00
parent 59104028b6
commit d22d2cb708
7 changed files with 46 additions and 46 deletions

View File

@@ -20,7 +20,7 @@
<java.version>17</java.version> <java.version>17</java.version>
<mysql.version>8.0.33</mysql.version> <mysql.version>8.0.33</mysql.version>
<mybatis.version>3.5.16</mybatis.version> <mybatis.version>3.5.16</mybatis.version>
<springdoc.version>2.1.0</springdoc.version> <springdoc.version>2.8.5</springdoc.version>
<therapi-javadoc.version>0.15.0</therapi-javadoc.version> <therapi-javadoc.version>0.15.0</therapi-javadoc.version>
<poi.version>5.2.3</poi.version> <poi.version>5.2.3</poi.version>
<easyexcel.version>3.2.1</easyexcel.version> <easyexcel.version>3.2.1</easyexcel.version>

View File

@@ -215,20 +215,25 @@ mybatis-encryptor:
publicKey: publicKey:
privateKey: privateKey:
# Swagger配置 springdoc:
swagger: api-docs:
# 是否开启接口文档
enabled: true
# swagger-ui:
# # 持久化认证数据
# persistAuthorization: true
info: info:
# 标题 # 标题
title: '标题:${ruoyi.name}多租户管理系统_接口文档' title: '标题:RuoYi-Vue-Plus多租户管理系统_接口文档'
# 描述 # 描述
description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...' description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'
# 版本 # 版本
version: '版本号: ${ruoyi.version}' version: '版本号: ${ruoyi.version}'
# 作者信息 # 作者信息
contact: contact:
name: ageerle name: Lion Li
email: ageerle@163.com email: crazylionli@163.com
url: https://gitee.com/ageerle/ruoyi-ai url: https://gitee.com/dromara/RuoYi-Vue-Plus
components: components:
# 鉴权方式配置 # 鉴权方式配置
security-schemes: security-schemes:
@@ -236,24 +241,18 @@ swagger:
type: APIKEY type: APIKEY
in: HEADER in: HEADER
name: ${sa-token.token-name} name: ${sa-token.token-name}
springdoc:
api-docs:
# 是否开启接口文档
enabled: true
swagger-ui:
# 持久化认证数据
persistAuthorization: true
#这里定义了两个分组,可定义多个,也可以不定义 #这里定义了两个分组,可定义多个,也可以不定义
group-configs: group-configs:
- group: 1.演示模块 - group: 1.演示模块
packages-to-scan: org.ruoyi.demo packages-to-scan: org.dromara.demo
- group: 2.通用模块 - group: 2.通用模块
packages-to-scan: org.ruoyi.web packages-to-scan: org.dromara.web
- group: 3.系统模块 - group: 3.系统模块
packages-to-scan: org.ruoyi.system packages-to-scan: org.dromara.system
- group: 4.代码生成模块 - group: 4.代码生成模块
packages-to-scan: org.ruoyi.generator packages-to-scan: org.dromara.generator
- group: 5.工作流模块
packages-to-scan: org.dromara.workflow
# 防止XSS攻击 # 防止XSS攻击
xss: xss:

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -6,7 +6,7 @@ import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityRequirement;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.ruoyi.common.core.utils.StringUtils; import org.ruoyi.common.core.utils.StringUtils;
import org.ruoyi.common.doc.config.properties.SwaggerProperties; import org.ruoyi.common.doc.config.properties.SpringDocProperties;
import org.ruoyi.common.doc.handler.OpenApiHandler; import org.ruoyi.common.doc.handler.OpenApiHandler;
import org.springdoc.core.configuration.SpringDocConfiguration; import org.springdoc.core.configuration.SpringDocConfiguration;
import org.springdoc.core.customizers.OpenApiBuilderCustomizer; import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
@@ -36,26 +36,26 @@ import java.util.Set;
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
@AutoConfiguration(before = SpringDocConfiguration.class) @AutoConfiguration(before = SpringDocConfiguration.class)
@EnableConfigurationProperties(SwaggerProperties.class) @EnableConfigurationProperties(SpringDocProperties.class)
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true)
public class SwaggerConfig { public class SpringDocConfig {
private final ServerProperties serverProperties; private final ServerProperties serverProperties;
@Bean @Bean
@ConditionalOnMissingBean(OpenAPI.class) @ConditionalOnMissingBean(OpenAPI.class)
public OpenAPI openApi(SwaggerProperties swaggerProperties) { public OpenAPI openApi(SpringDocProperties properties) {
OpenAPI openApi = new OpenAPI(); OpenAPI openApi = new OpenAPI();
// 文档基本信息 // 文档基本信息
SwaggerProperties.InfoProperties infoProperties = swaggerProperties.getInfo(); SpringDocProperties.InfoProperties infoProperties = properties.getInfo();
Info info = convertInfo(infoProperties); Info info = convertInfo(infoProperties);
openApi.info(info); openApi.info(info);
// 扩展文档信息 // 扩展文档信息
openApi.externalDocs(swaggerProperties.getExternalDocs()); openApi.externalDocs(properties.getExternalDocs());
openApi.tags(swaggerProperties.getTags()); openApi.tags(properties.getTags());
openApi.paths(swaggerProperties.getPaths()); openApi.paths(properties.getPaths());
openApi.components(swaggerProperties.getComponents()); openApi.components(properties.getComponents());
Set<String> keySet = swaggerProperties.getComponents().getSecuritySchemes().keySet(); Set<String> keySet = properties.getComponents().getSecuritySchemes().keySet();
List<SecurityRequirement> list = new ArrayList<>(); List<SecurityRequirement> list = new ArrayList<>();
SecurityRequirement securityRequirement = new SecurityRequirement(); SecurityRequirement securityRequirement = new SecurityRequirement();
keySet.forEach(securityRequirement::addList); keySet.forEach(securityRequirement::addList);
@@ -65,7 +65,7 @@ public class SwaggerConfig {
return openApi; return openApi;
} }
private Info convertInfo(SwaggerProperties.InfoProperties infoProperties) { private Info convertInfo(SpringDocProperties.InfoProperties infoProperties) {
Info info = new Info(); Info info = new Info();
info.setTitle(infoProperties.getTitle()); info.setTitle(infoProperties.getTitle());
info.setDescription(infoProperties.getDescription()); info.setDescription(infoProperties.getDescription());

View File

@@ -18,8 +18,8 @@ import java.util.List;
* @author Lion Li * @author Lion Li
*/ */
@Data @Data
@ConfigurationProperties(prefix = "swagger") @ConfigurationProperties(prefix = "springdoc")
public class SwaggerProperties { public class SpringDocProperties {
/** /**
* 文档基本信息 * 文档基本信息

View File

@@ -11,6 +11,7 @@ import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.tags.Tag; import io.swagger.v3.oas.models.tags.Tag;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.ruoyi.common.core.utils.StreamUtils;
import org.springdoc.core.customizers.OpenApiBuilderCustomizer; import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
import org.springdoc.core.customizers.ServerBaseUrlCustomizer; import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springdoc.core.properties.SpringDocConfigProperties; import org.springdoc.core.properties.SpringDocConfigProperties;
@@ -154,11 +155,11 @@ public class OpenApiHandler extends OpenAPIService {
if (!CollectionUtils.isEmpty(tagsStr)) if (!CollectionUtils.isEmpty(tagsStr))
tagsStr = tagsStr.stream() tagsStr = tagsStr.stream()
.map(str -> propertyResolverUtils.resolve(str, locale)) .map(str -> propertyResolverUtils.resolve(str, locale))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
if (springdocTags.containsKey(handlerMethod)) { if (springdocTags.containsKey(handlerMethod)) {
Tag tag = springdocTags.get(handlerMethod); io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod);
tagsStr.add(tag.getName()); tagsStr.add(tag.getName());
if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) { if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {
openAPI.addTagsItem(tag); openAPI.addTagsItem(tag);
@@ -182,7 +183,7 @@ public class OpenApiHandler extends OpenAPIService {
if (javadocProvider.isPresent()) { if (javadocProvider.isPresent()) {
String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType()); String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType());
if (StringUtils.isNotBlank(description)) { if (StringUtils.isNotBlank(description)) {
Tag tag = new Tag(); io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.Tag();
// 自定义部分 修改使用java注释当tag名 // 自定义部分 修改使用java注释当tag名
List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>()); List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>());
@@ -203,7 +204,7 @@ public class OpenApiHandler extends OpenAPIService {
if (!CollectionUtils.isEmpty(tags)) { if (!CollectionUtils.isEmpty(tags)) {
// Existing tags // Existing tags
List<Tag> openApiTags = openAPI.getTags(); List<io.swagger.v3.oas.models.tags.Tag> openApiTags = openAPI.getTags();
if (!CollectionUtils.isEmpty(openApiTags)) if (!CollectionUtils.isEmpty(openApiTags))
tags.addAll(openApiTags); tags.addAll(openApiTags);
openAPI.setTags(new ArrayList<>(tags)); openAPI.setTags(new ArrayList<>(tags));
@@ -211,7 +212,7 @@ public class OpenApiHandler extends OpenAPIService {
// Handle SecurityRequirement at operation level // Handle SecurityRequirement at operation level
io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser
.getSecurityRequirements(handlerMethod); .getSecurityRequirements(handlerMethod);
if (securityRequirements != null) { if (securityRequirements != null) {
if (securityRequirements.length == 0) if (securityRequirements.length == 0)
operation.setSecurity(Collections.emptyList()); operation.setSecurity(Collections.emptyList());
@@ -222,23 +223,23 @@ public class OpenApiHandler extends OpenAPIService {
return operation; return operation;
} }
private void buildTagsFromMethod(Method method, Set<Tag> tags, Set<String> tagsStr, Locale locale) { private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) {
// method tags // method tags
Set<Tags> tagsSet = AnnotatedElementUtils Set<Tags> tagsSet = AnnotatedElementUtils
.findAllMergedAnnotations(method, Tags.class); .findAllMergedAnnotations(method, Tags.class);
Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream() Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream()
.flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet());
methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class)); methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class));
if (!CollectionUtils.isEmpty(methodTags)) { if (!CollectionUtils.isEmpty(methodTags)) {
tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet())); tagsStr.addAll(StreamUtils.toSet(methodTags, tag -> propertyResolverUtils.resolve(tag.name(), locale)));
List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags); List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags);
addTags(allTags, tags, locale); addTags(allTags, tags, locale);
} }
} }
private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<Tag> tags, Locale locale) { private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag> tags, Locale locale) {
Optional<Set<Tag>> optionalTagSet = AnnotationsUtils Optional<Set<io.swagger.v3.oas.models.tags.Tag>> optionalTagSet = AnnotationsUtils
.getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true); .getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true);
optionalTagSet.ifPresent(tagsSet -> { optionalTagSet.ifPresent(tagsSet -> {
tagsSet.forEach(tag -> { tagsSet.forEach(tag -> {
tag.name(propertyResolverUtils.resolve(tag.getName(), locale)); tag.name(propertyResolverUtils.resolve(tag.getName(), locale));

View File

@@ -1 +1 @@
org.ruoyi.common.doc.config.SwaggerConfig org.ruoyi.common.doc.config.SpringDocConfig