mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-10-21 20:57:15 +08:00
refactor(api-doc): 将默认API文档UI从Knife4j替换为NextDoc4j
- 移除对Knife4j相关依赖和资源配置 - 新增NextDoc4j依赖及版本管理 - 重构BaseEnumParameterHandler以继承ModelResolver - 添加ObjectMapper注入支持枚举参数解析 - 调整资源处理器配置移除旧版静态资源配置 - 删除自定义OpenApiHandler及相关构建器配置 - 更新YAML配置文件启用NextDoc4j并移除Knife4j设置
This commit is contained in:
@@ -22,10 +22,11 @@
|
|||||||
<artifactId>continew-starter-core</artifactId>
|
<artifactId>continew-starter-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Knife4j(前身是 swagger-bootstrap-ui,集 Swagger2 和 OpenAPI3 为一体的增强解决方案) -->
|
<!--NextDoc4j (现代化 API 文档 UI 工具 全面替代 Swagger UI) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
<groupId>top.nextdoc4j</groupId>
|
||||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
<artifactId>nextdoc4j-springboot3-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
@@ -17,6 +17,7 @@
|
|||||||
package top.continew.starter.apidoc.autoconfigure;
|
package top.continew.starter.apidoc.autoconfigure;
|
||||||
|
|
||||||
import cn.hutool.core.map.MapUtil;
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import io.swagger.v3.oas.models.Components;
|
import io.swagger.v3.oas.models.Components;
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
import io.swagger.v3.oas.models.info.Contact;
|
import io.swagger.v3.oas.models.info.Contact;
|
||||||
@@ -29,32 +30,21 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springdoc.core.configuration.SpringDocConfiguration;
|
import org.springdoc.core.configuration.SpringDocConfiguration;
|
||||||
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
|
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
|
||||||
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.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
import org.springframework.http.CacheControl;
|
|
||||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
import top.continew.starter.apidoc.handler.BaseEnumParameterHandler;
|
import top.continew.starter.apidoc.handler.BaseEnumParameterHandler;
|
||||||
import top.continew.starter.apidoc.handler.OpenApiHandler;
|
|
||||||
import top.continew.starter.core.autoconfigure.application.ApplicationProperties;
|
import top.continew.starter.core.autoconfigure.application.ApplicationProperties;
|
||||||
import top.continew.starter.core.util.CollUtils;
|
import top.continew.starter.core.util.CollUtils;
|
||||||
import top.continew.starter.core.util.GeneralPropertySourceFactory;
|
import top.continew.starter.core.util.GeneralPropertySourceFactory;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 文档自动配置
|
* API 文档自动配置
|
||||||
@@ -73,10 +63,6 @@ public class SpringDocAutoConfiguration implements WebMvcConfigurer {
|
|||||||
@Override
|
@Override
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/");
|
registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/");
|
||||||
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
|
|
||||||
registry.addResourceHandler("/webjars/**")
|
|
||||||
.addResourceLocations("classpath:/META-INF/resources/webjars/")
|
|
||||||
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,20 +125,6 @@ public class SpringDocAutoConfiguration implements WebMvcConfigurer {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义 BaseEnum 枚举参数配置(针对实现了 BaseEnum 的枚举,优化其枚举值和描述展示)
|
* 自定义 BaseEnum 枚举参数配置(针对实现了 BaseEnum 的枚举,优化其枚举值和描述展示)
|
||||||
*
|
*
|
||||||
@@ -160,8 +132,8 @@ public class SpringDocAutoConfiguration implements WebMvcConfigurer {
|
|||||||
* @since 2.4.0
|
* @since 2.4.0
|
||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
public BaseEnumParameterHandler customParameterCustomizer() {
|
public BaseEnumParameterHandler customParameterCustomizer(ObjectMapper mapper) {
|
||||||
return new BaseEnumParameterHandler();
|
return new BaseEnumParameterHandler(mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
|
@@ -18,19 +18,23 @@ package top.continew.starter.apidoc.handler;
|
|||||||
|
|
||||||
import cn.hutool.core.text.CharSequenceUtil;
|
import cn.hutool.core.text.CharSequenceUtil;
|
||||||
import cn.hutool.core.util.ClassUtil;
|
import cn.hutool.core.util.ClassUtil;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.type.CollectionType;
|
import com.fasterxml.jackson.databind.type.CollectionType;
|
||||||
import com.fasterxml.jackson.databind.type.SimpleType;
|
import com.fasterxml.jackson.databind.type.SimpleType;
|
||||||
import io.swagger.v3.core.converter.AnnotatedType;
|
import io.swagger.v3.core.converter.AnnotatedType;
|
||||||
|
import io.swagger.v3.core.converter.ModelConverter;
|
||||||
|
import io.swagger.v3.core.converter.ModelConverterContext;
|
||||||
|
import io.swagger.v3.core.jackson.ModelResolver;
|
||||||
import io.swagger.v3.oas.models.media.Schema;
|
import io.swagger.v3.oas.models.media.Schema;
|
||||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||||
import org.springdoc.core.customizers.ParameterCustomizer;
|
import org.springdoc.core.customizers.ParameterCustomizer;
|
||||||
import org.springdoc.core.customizers.PropertyCustomizer;
|
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import top.continew.starter.apidoc.util.ApiDocUtils;
|
import top.continew.starter.apidoc.util.ApiDocUtils;
|
||||||
import top.continew.starter.core.enums.BaseEnum;
|
import top.continew.starter.core.enums.BaseEnum;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,7 +46,11 @@ import java.util.List;
|
|||||||
* @author echo
|
* @author echo
|
||||||
* @since 2.5.2
|
* @since 2.5.2
|
||||||
*/
|
*/
|
||||||
public class BaseEnumParameterHandler implements ParameterCustomizer, PropertyCustomizer {
|
public class BaseEnumParameterHandler extends ModelResolver implements ParameterCustomizer {
|
||||||
|
|
||||||
|
public BaseEnumParameterHandler(ObjectMapper mapper) {
|
||||||
|
super(mapper);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Parameter customize(Parameter parameterModel, MethodParameter methodParameter) {
|
public Parameter customize(Parameter parameterModel, MethodParameter methodParameter) {
|
||||||
@@ -62,16 +70,18 @@ public class BaseEnumParameterHandler implements ParameterCustomizer, PropertyCu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Schema customize(Schema schema, AnnotatedType type) {
|
public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
|
||||||
|
Schema resolve = super.resolve(type, context, chain);
|
||||||
Class<?> rawClass = resolveRawClass(type.getType());
|
Class<?> rawClass = resolveRawClass(type.getType());
|
||||||
// 判断是否为 BaseEnum 的子类型
|
// 判断是否为 BaseEnum 的子类型
|
||||||
if (!ClassUtil.isAssignable(BaseEnum.class, rawClass)) {
|
if (!ClassUtil.isAssignable(BaseEnum.class, rawClass)) {
|
||||||
return schema;
|
return resolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 自定义参数描述并封装参数配置
|
// 自定义参数描述并封装参数配置
|
||||||
configureSchema(schema, rawClass);
|
configureSchema(resolve, rawClass);
|
||||||
schema.setDescription(appendEnumDescription(schema.getDescription(), rawClass));
|
resolve.setDescription(appendEnumDescription(resolve.getDescription(), rawClass));
|
||||||
return schema;
|
return resolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,275 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
|
||||||
* <p>
|
|
||||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* <p>
|
|
||||||
* http://www.gnu.org/licenses/lgpl.html
|
|
||||||
* <p>
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package top.continew.starter.apidoc.handler;
|
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
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.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.web.method.HandlerMethod;
|
|
||||||
import top.continew.starter.core.util.CollUtils;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义 OpenApi 处理器(对源码功能进行修改,增强使用)
|
|
||||||
*
|
|
||||||
* @author echo
|
|
||||||
* @since 2.4.0
|
|
||||||
*/
|
|
||||||
@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 (CollUtil.isNotEmpty(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 (CollUtil.isNotEmpty(tagsStr)) {
|
|
||||||
tagsStr = CollUtils.mapToSet(tagsStr, str -> propertyResolverUtils.resolve(str, locale));
|
|
||||||
}
|
|
||||||
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 (CollUtil.isNotEmpty(tagsStr)) {
|
|
||||||
if (CollUtil.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 (CollUtil.isNotEmpty(tags)) {
|
|
||||||
// Existing tags
|
|
||||||
List<Tag> openApiTags = openAPI.getTags();
|
|
||||||
if (CollUtil.isNotEmpty(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 (CollUtil.isNotEmpty(methodTags)) {
|
|
||||||
tagsStr.addAll(CollUtils.mapToSet(methodTags, tag -> propertyResolverUtils.resolve(tag.name(), locale)));
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@@ -10,8 +10,5 @@ springdoc:
|
|||||||
enabled: ${springdoc.swagger-ui.enabled}
|
enabled: ${springdoc.swagger-ui.enabled}
|
||||||
path: /v3/api-docs
|
path: /v3/api-docs
|
||||||
## 接口文档增强配置
|
## 接口文档增强配置
|
||||||
knife4j:
|
nextdoc4j:
|
||||||
enable: true
|
enabled: true
|
||||||
setting:
|
|
||||||
language: zh_cn
|
|
||||||
swagger-model-name: 实体类列表
|
|
||||||
|
@@ -62,7 +62,8 @@
|
|||||||
<crane4j.version>2.9.0</crane4j.version>
|
<crane4j.version>2.9.0</crane4j.version>
|
||||||
|
|
||||||
<!-- API Documentation Versions -->
|
<!-- API Documentation Versions -->
|
||||||
<knife4j.version>4.5.0</knife4j.version>
|
<nextdoc4j.version>1.0.1</nextdoc4j.version>
|
||||||
|
<swagger-annotations.version>2.2.36</swagger-annotations.version>
|
||||||
|
|
||||||
<!-- Tracing and Logging Versions -->
|
<!-- Tracing and Logging Versions -->
|
||||||
<tlog.version>1.5.2</tlog.version>
|
<tlog.version>1.5.2</tlog.version>
|
||||||
@@ -325,11 +326,11 @@
|
|||||||
<version>${crane4j.version}</version>
|
<version>${crane4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Knife4j(前身是 swagger-bootstrap-ui,集 Swagger2 和 OpenAPI3 为一体的增强解决方案) -->
|
<!--NextDoc4j (现代化 API 文档 UI 工具 全面替代 Swagger UI) -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.xiaoymin</groupId>
|
<groupId>top.nextdoc4j</groupId>
|
||||||
<artifactId>knife4j-dependencies</artifactId>
|
<artifactId>nextdoc4j-bom</artifactId>
|
||||||
<version>${knife4j.version}</version>
|
<version>${nextdoc4j.version}</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
@@ -422,6 +423,13 @@
|
|||||||
<version>${commons-compress.version}</version>
|
<version>${commons-compress.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Swagger 注解 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.swagger.core.v3</groupId>
|
||||||
|
<artifactId>swagger-annotations-jakarta</artifactId>
|
||||||
|
<version>${swagger-annotations.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- ContiNew Starter 依赖 -->
|
<!-- ContiNew Starter 依赖 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>top.continew.starter</groupId>
|
<groupId>top.continew.starter</groupId>
|
||||||
|
Reference in New Issue
Block a user