mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2026-06-08 14:56:09 +00:00
update 优化 springdoc 自定义逻辑行为实现
This commit is contained in:
@@ -6,18 +6,14 @@ import io.swagger.v3.oas.models.info.Info;
|
||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.doc.core.customizer.ClassTagOperationCustomizer;
|
||||
import org.dromara.common.doc.core.customizer.JavadocOperationCustomizer;
|
||||
import org.dromara.common.doc.config.properties.SpringDocProperties;
|
||||
import org.dromara.common.doc.core.resolver.JavadocResolver;
|
||||
import org.dromara.common.doc.core.resolver.SaTokenAnnotationMetadataJavadocResolver;
|
||||
import org.dromara.common.doc.handler.OpenApiHandler;
|
||||
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;
|
||||
@@ -91,16 +87,21 @@ public class SpringDocConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 openapi 处理器
|
||||
* Controller 类级标签增强
|
||||
*/
|
||||
@Bean
|
||||
public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
|
||||
SecurityService securityParser,
|
||||
SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
|
||||
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers,
|
||||
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider,
|
||||
List<JavadocResolver> javadocResolvers) {
|
||||
return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider, javadocResolvers);
|
||||
public ClassTagOperationCustomizer classTagOperationCustomizer(Optional<JavadocProvider> javadocProvider,
|
||||
PropertyResolverUtils propertyResolverUtils) {
|
||||
return new ClassTagOperationCustomizer(javadocProvider, propertyResolverUtils);
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法 JavaDoc 与权限描述增强
|
||||
*/
|
||||
@Bean
|
||||
public JavadocOperationCustomizer javadocOperationCustomizer(Optional<JavadocProvider> javadocProvider,
|
||||
List<JavadocResolver> javadocResolvers) {
|
||||
return new JavadocOperationCustomizer(javadocProvider, javadocResolvers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
package org.dromara.common.doc.core.customizer;
|
||||
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import io.swagger.v3.core.util.AnnotationsUtils;
|
||||
import io.swagger.v3.oas.annotations.tags.Tags;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import io.swagger.v3.oas.models.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springdoc.core.customizers.OpenApiCustomizer;
|
||||
import org.springdoc.core.customizers.OperationCustomizer;
|
||||
import org.springdoc.core.providers.JavadocProvider;
|
||||
import org.springdoc.core.service.OpenAPIService;
|
||||
import org.springdoc.core.utils.PropertyResolverUtils;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Controller 类级标签增强。
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class ClassTagOperationCustomizer implements OperationCustomizer, OpenApiCustomizer {
|
||||
|
||||
private final Optional<JavadocProvider> javadocProvider;
|
||||
|
||||
private final PropertyResolverUtils propertyResolverUtils;
|
||||
|
||||
private final Map<String, Tag> tags = new ConcurrentHashMap<>();
|
||||
|
||||
private final Set<String> replacedAutoTagNames = ConcurrentHashMap.newKeySet();
|
||||
|
||||
@Override
|
||||
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
|
||||
Class<?> beanType = handlerMethod.getBeanType();
|
||||
List<io.swagger.v3.oas.annotations.tags.Tag> classTags = getClassTags(beanType);
|
||||
if (!CollectionUtils.isEmpty(classTags)) {
|
||||
// 优先使用 Controller 类上的 @Tag / @Tags,保持 Swagger 原生注解语义
|
||||
addAnnotationTags(operation, classTags);
|
||||
return operation;
|
||||
}
|
||||
|
||||
String tagName = getClassJavadocTagName(beanType);
|
||||
if (StringUtils.isBlank(tagName)) {
|
||||
return operation;
|
||||
}
|
||||
|
||||
String autoTagName = OpenAPIService.splitCamelCase(beanType.getSimpleName());
|
||||
if (!shouldUseClassJavadocTag(operation, autoTagName)) {
|
||||
return operation;
|
||||
}
|
||||
|
||||
// 无显式 @Tag 时,将 springdoc 自动生成的类名 tag 替换为类 JavaDoc 第一行
|
||||
removeOperationTag(operation, autoTagName);
|
||||
addOperationTag(operation, tagName);
|
||||
replacedAutoTagNames.add(autoTagName);
|
||||
tags.putIfAbsent(tagName, new Tag().name(tagName).description(javadocProvider.get().getClassJavadoc(beanType)));
|
||||
return operation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customise(OpenAPI openApi) {
|
||||
if (!CollectionUtils.isEmpty(openApi.getTags()) && !CollectionUtils.isEmpty(replacedAutoTagNames)) {
|
||||
// 移除已被 JavaDoc tag 替换的默认类名 tag,避免 Swagger UI 出现空分组
|
||||
openApi.getTags().removeIf(tag -> replacedAutoTagNames.contains(tag.getName()));
|
||||
}
|
||||
// 将类级 @Tag 描述或 JavaDoc 描述补充到 OpenAPI 顶层 tags
|
||||
tags.values().forEach(tag -> {
|
||||
if (openApi.getTags() == null || openApi.getTags().stream().noneMatch(item -> Objects.equals(item.getName(), tag.getName()))) {
|
||||
openApi.addTagsItem(tag);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<io.swagger.v3.oas.annotations.tags.Tag> getClassTags(Class<?> beanType) {
|
||||
Set<Tags> tagsSet = AnnotatedElementUtils.findAllMergedAnnotations(beanType, Tags.class);
|
||||
Set<io.swagger.v3.oas.annotations.tags.Tag> mergedTags = tagsSet.stream()
|
||||
.flatMap(item -> Stream.of(item.value()))
|
||||
.collect(Collectors.toSet());
|
||||
mergedTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(beanType, io.swagger.v3.oas.annotations.tags.Tag.class));
|
||||
return new ArrayList<>(mergedTags);
|
||||
}
|
||||
|
||||
private void addAnnotationTags(Operation operation, List<io.swagger.v3.oas.annotations.tags.Tag> classTags) {
|
||||
classTags.stream()
|
||||
.map(io.swagger.v3.oas.annotations.tags.Tag::name)
|
||||
.map(name -> propertyResolverUtils.resolve(name, Locale.getDefault()))
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.forEach(name -> addOperationTag(operation, name));
|
||||
|
||||
AnnotationsUtils.getTags(classTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true)
|
||||
.ifPresent(items -> items.forEach(tag -> {
|
||||
tag.name(propertyResolverUtils.resolve(tag.getName(), Locale.getDefault()));
|
||||
tag.description(propertyResolverUtils.resolve(tag.getDescription(), Locale.getDefault()));
|
||||
if (StringUtils.isNotBlank(tag.getName())) {
|
||||
tags.putIfAbsent(tag.getName(), tag);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private String getClassJavadocTagName(Class<?> beanType) {
|
||||
if (javadocProvider.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String description = javadocProvider.get().getClassJavadoc(beanType);
|
||||
if (StringUtils.isBlank(description)) {
|
||||
return null;
|
||||
}
|
||||
// 与原 OpenApiHandler 保持一致:类 JavaDoc 第一行作为 tag 名,完整 JavaDoc 作为 tag 描述
|
||||
List<String> lines = IoUtil.readLines(new StringReader(description), new ArrayList<>());
|
||||
return lines.stream().filter(StringUtils::isNotBlank).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private boolean shouldUseClassJavadocTag(Operation operation, String autoTagName) {
|
||||
return CollectionUtils.isEmpty(operation.getTags()) || operation.getTags().contains(autoTagName);
|
||||
}
|
||||
|
||||
private void addOperationTag(Operation operation, String tagName) {
|
||||
if (operation.getTags() == null) {
|
||||
operation.setTags(new ArrayList<>());
|
||||
}
|
||||
if (!operation.getTags().contains(tagName)) {
|
||||
operation.addTagsItem(tagName);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeOperationTag(Operation operation, String tagName) {
|
||||
if (!CollectionUtils.isEmpty(operation.getTags())) {
|
||||
operation.getTags().removeIf(item -> Objects.equals(item, tagName));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.dromara.common.doc.core.customizer;
|
||||
|
||||
import io.swagger.v3.oas.models.Operation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.common.doc.core.resolver.JavadocResolver;
|
||||
import org.springdoc.core.customizers.OperationCustomizer;
|
||||
import org.springdoc.core.providers.JavadocProvider;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 方法 JavaDoc 与扩展描述增强。
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class JavadocOperationCustomizer implements OperationCustomizer {
|
||||
|
||||
private final Optional<JavadocProvider> javadocProvider;
|
||||
|
||||
private final List<JavadocResolver> javadocResolvers;
|
||||
|
||||
@Override
|
||||
public Operation customize(Operation operation, HandlerMethod handlerMethod) {
|
||||
javadocProvider.ifPresent(provider -> {
|
||||
String description = provider.getMethodJavadocDescription(handlerMethod.getMethod());
|
||||
if (StringUtils.isNotBlank(description)) {
|
||||
// 使用方法 JavaDoc 首句作为接口摘要,完整 JavaDoc 作为接口描述
|
||||
operation.setSummary(provider.getFirstSentence(description));
|
||||
operation.setDescription(description);
|
||||
}
|
||||
});
|
||||
|
||||
if (CollectionUtils.isEmpty(javadocResolvers)) {
|
||||
return operation;
|
||||
}
|
||||
|
||||
StringBuilder description = new StringBuilder(Optional.ofNullable(operation.getDescription()).orElse(""));
|
||||
List<String> resolvedDescriptions = javadocResolvers.stream()
|
||||
.sorted()
|
||||
// 只执行支持当前 HandlerMethod 的扩展解析器,避免无注解接口被追加权限说明
|
||||
.filter(resolver -> resolver.supports(handlerMethod))
|
||||
.map(resolver -> resolver.resolve(handlerMethod, operation))
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.toList();
|
||||
if (!resolvedDescriptions.isEmpty()) {
|
||||
// 在原方法 JavaDoc 后追加权限等扩展描述,保持现有 resolver 扩展点
|
||||
resolvedDescriptions.forEach(description::append);
|
||||
operation.setDescription(description.toString());
|
||||
}
|
||||
return operation;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,302 +0,0 @@
|
||||
package org.dromara.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 lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.doc.core.resolver.JavadocResolver;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Javadoc解析器接口
|
||||
*/
|
||||
private final List<JavadocResolver> javadocResolvers;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param javadocResolvers Javadoc 解析器列表
|
||||
*/
|
||||
public OpenApiHandler(Optional<OpenAPI> openAPI, SecurityService securityParser,
|
||||
SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
|
||||
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
|
||||
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
|
||||
Optional<JavadocProvider> javadocProvider,
|
||||
List<JavadocResolver> javadocResolvers) {
|
||||
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;
|
||||
this.javadocResolvers = javadocResolvers == null ? new ArrayList<>() : javadocResolvers;
|
||||
if (springDocConfigProperties.isUseFqn())
|
||||
TypeNameResolver.std.setUseFqn(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建接口标签、权限描述与方法摘要。
|
||||
*
|
||||
* @param handlerMethod Handler 方法
|
||||
* @param operation OpenAPI 操作对象
|
||||
* @param openAPI OpenAPI 文档对象
|
||||
* @param locale 当前语言环境
|
||||
* @return 处理后的操作对象
|
||||
*/
|
||||
@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)) {
|
||||
io.swagger.v3.oas.models.tags.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)) {
|
||||
io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.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<io.swagger.v3.oas.models.tags.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);
|
||||
}
|
||||
|
||||
if (javadocProvider.isPresent()) {
|
||||
String description = javadocProvider.get().getMethodJavadocDescription(handlerMethod.getMethod());
|
||||
String summary = javadocProvider.get().getFirstSentence(description);
|
||||
if (StringUtils.isNotBlank(description)){
|
||||
operation.setSummary(summary);
|
||||
}
|
||||
// 调用解析器提取JavaDoc中的权限信息
|
||||
if (javadocResolvers != null && !javadocResolvers.isEmpty()) {
|
||||
for (JavadocResolver resolver : javadocResolvers) {
|
||||
String desc = resolver.resolve(handlerMethod, operation);
|
||||
description = description + desc;
|
||||
}
|
||||
operation.setDescription(description);
|
||||
}
|
||||
}
|
||||
|
||||
return operation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从方法注解中提取标签信息。
|
||||
*
|
||||
* @param method 方法对象
|
||||
* @param tags 标签集合
|
||||
* @param tagsStr 标签名称集合
|
||||
* @param locale 当前语言环境
|
||||
*/
|
||||
private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.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(StreamUtils.toSet(methodTags, tag -> propertyResolverUtils.resolve(tag.name(), locale)));
|
||||
List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags);
|
||||
addTags(allTags, tags, locale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将注解标签转换并合并到 OpenAPI 标签集合。
|
||||
*
|
||||
* @param sourceTags 注解标签列表
|
||||
* @param tags OpenAPI 标签集合
|
||||
* @param 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<io.swagger.v3.oas.models.tags.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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user