diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java new file mode 100644 index 000000000..f8996f75b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/Knife4jOpenApiCustomizer.java @@ -0,0 +1,146 @@ +package cn.iocoder.yudao.framework.swagger.config; + +import com.github.xiaoymin.knife4j.annotations.ApiSupport; +import com.github.xiaoymin.knife4j.core.conf.ExtensionsConstants; +import com.github.xiaoymin.knife4j.core.conf.GlobalConstants; +import com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties; +import com.github.xiaoymin.knife4j.spring.configuration.Knife4jSetting; +import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.models.OpenAPI; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.springdoc.core.customizers.GlobalOpenApiCustomizer; +import org.springdoc.core.properties.SpringDocConfigProperties; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.util.CollectionUtils; +import org.springframework.web.bind.annotation.RestController; + +import java.lang.annotation.Annotation; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 增强扩展属性支持 + * + * 参考 Spring Boot 3.4 以上版本 /v3/api-docs 解决接口报错,依赖修复 + * + * @since 4.1.0 + * @author xiaoymin@foxmail.com + * 2022/12/11 22:40 + */ +@Primary +@Configuration +@Slf4j +public class Knife4jOpenApiCustomizer extends com.github.xiaoymin.knife4j.spring.extension.Knife4jOpenApiCustomizer + implements GlobalOpenApiCustomizer { + + final Knife4jProperties knife4jProperties; + final SpringDocConfigProperties properties; + + public Knife4jOpenApiCustomizer(Knife4jProperties knife4jProperties, SpringDocConfigProperties properties) { + super(knife4jProperties,properties); + this.knife4jProperties = knife4jProperties; + this.properties = properties; + } + + @Override + public void customise(OpenAPI openApi) { + if (knife4jProperties.isEnable()) { + Knife4jSetting setting = knife4jProperties.getSetting(); + OpenApiExtensionResolver openApiExtensionResolver = new OpenApiExtensionResolver(setting, knife4jProperties.getDocuments()); + // 解析初始化 + openApiExtensionResolver.start(); + Map objectMap = new HashMap<>(); + objectMap.put(GlobalConstants.EXTENSION_OPEN_SETTING_NAME, setting); + objectMap.put(GlobalConstants.EXTENSION_OPEN_MARKDOWN_NAME, openApiExtensionResolver.getMarkdownFiles()); + openApi.addExtension(GlobalConstants.EXTENSION_OPEN_API_NAME, objectMap); + addOrderExtension(openApi); + } + } + + /** + * 往 OpenAPI 内 tags 字段添加 x-order 属性 + * + * @param openApi openApi + */ + private void addOrderExtension(OpenAPI openApi) { + if (CollectionUtils.isEmpty(properties.getGroupConfigs())) { + return; + } + // 获取包扫描路径 + Set packagesToScan = + properties.getGroupConfigs().stream() + .map(SpringDocConfigProperties.GroupConfig::getPackagesToScan) + .filter(toScan -> !CollectionUtils.isEmpty(toScan)) + .flatMap(List::stream) + .collect(Collectors.toSet()); + if (CollectionUtils.isEmpty(packagesToScan)) { + return; + } + // 扫描包下被 ApiSupport 注解的 RestController Class + Set> classes = packagesToScan.stream() + .map(packageToScan -> scanPackageByAnnotation(packageToScan, RestController.class)) + .flatMap(Set::stream) + .filter(clazz -> clazz.isAnnotationPresent(ApiSupport.class)) + .collect(Collectors.toSet()); + if (!CollectionUtils.isEmpty(classes)) { + // ApiSupport oder 值存入 tagSortMap + Map tagOrderMap = new HashMap<>(); + classes.forEach(clazz -> { + Tag tag = getTag(clazz); + if (Objects.nonNull(tag)) { + ApiSupport apiSupport = clazz.getAnnotation(ApiSupport.class); + tagOrderMap.putIfAbsent(tag.name(), apiSupport.order()); + } + }); + // 往 openApi tags 字段添加 x-order 增强属性 + if (openApi.getTags() != null) { + openApi.getTags().forEach(tag -> { + if (tagOrderMap.containsKey(tag.getName())) { + tag.addExtension(ExtensionsConstants.EXTENSION_ORDER, tagOrderMap.get(tag.getName())); + } + }); + } + } + } + + private Tag getTag(Class clazz) { + // 从类上获取 + Tag tag = clazz.getAnnotation(Tag.class); + if (Objects.isNull(tag)) { + // 从接口上获取 + Class[] interfaces = clazz.getInterfaces(); + if (ArrayUtils.isNotEmpty(interfaces)) { + for (Class interfaceClazz : interfaces) { + Tag anno = interfaceClazz.getAnnotation(Tag.class); + if (Objects.nonNull(anno)) { + tag = anno; + break; + } + } + } + } + return tag; + } + + private Set> scanPackageByAnnotation(String packageName, final Class annotationClass) { + ClassPathScanningCandidateComponentProvider scanner = + new ClassPathScanningCandidateComponentProvider(false); + scanner.addIncludeFilter(new AnnotationTypeFilter(annotationClass)); + Set> classes = new HashSet<>(); + for (BeanDefinition beanDefinition : scanner.findCandidateComponents(packageName)) { + try { + Class clazz = Class.forName(beanDefinition.getBeanClassName()); + classes.add(clazz); + } catch (ClassNotFoundException ignore) { + } + } + return classes; + } + +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java index 7957983c4..dffa4743d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/swagger/config/YudaoSwaggerAutoConfiguration.java @@ -19,6 +19,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 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.Import; import org.springframework.context.annotation.Primary; import org.springframework.http.HttpHeaders; @@ -42,6 +43,7 @@ import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_ @ConditionalOnClass({OpenAPI.class}) @EnableConfigurationProperties(SwaggerProperties.class) @ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用 +@Import(Knife4jOpenApiCustomizer.class) public class YudaoSwaggerAutoConfiguration { // ========== 全局 OpenAPI 配置 ========== diff --git a/yudao-module-ai/yudao-module-ai-server/src/main/resources/application.yaml b/yudao-module-ai/yudao-module-ai-server/src/main/resources/application.yaml index fa1cc81a3..157a6c047 100644 --- a/yudao-module-ai/yudao-module-ai-server/src/main/resources/application.yaml +++ b/yudao-module-ai/yudao-module-ai-server/src/main/resources/application.yaml @@ -59,7 +59,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-bpm/yudao-module-bpm-server/src/main/resources/application.yaml b/yudao-module-bpm/yudao-module-bpm-server/src/main/resources/application.yaml index cc991899c..048cd7136 100644 --- a/yudao-module-bpm/yudao-module-bpm-server/src/main/resources/application.yaml +++ b/yudao-module-bpm/yudao-module-bpm-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-crm/yudao-module-crm-server/src/main/resources/application.yaml b/yudao-module-crm/yudao-module-crm-server/src/main/resources/application.yaml index 1d90156c3..0be7c718f 100644 --- a/yudao-module-crm/yudao-module-crm-server/src/main/resources/application.yaml +++ b/yudao-module-crm/yudao-module-crm-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-erp/yudao-module-erp-server/src/main/resources/application.yaml b/yudao-module-erp/yudao-module-erp-server/src/main/resources/application.yaml index 49588f5b4..cb7cf1332 100644 --- a/yudao-module-erp/yudao-module-erp-server/src/main/resources/application.yaml +++ b/yudao-module-erp/yudao-module-erp-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-infra/yudao-module-infra-server/src/main/resources/application.yaml b/yudao-module-infra/yudao-module-infra-server/src/main/resources/application.yaml index ccc089240..0fcd48a64 100644 --- a/yudao-module-infra/yudao-module-infra-server/src/main/resources/application.yaml +++ b/yudao-module-infra/yudao-module-infra-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/application.yaml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/application.yaml index 90ec6cdeb..a3666cf12 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/application.yaml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-mall/yudao-module-product-server/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-product-server/src/main/resources/application.yaml index f26baff6a..53556bad5 100644 --- a/yudao-module-mall/yudao-module-product-server/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-product-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-mall/yudao-module-promotion-server/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-promotion-server/src/main/resources/application.yaml index bab359246..429ab9ec4 100644 --- a/yudao-module-mall/yudao-module-promotion-server/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-promotion-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-mall/yudao-module-statistics-server/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-statistics-server/src/main/resources/application.yaml index 72b1d1ea4..40fd663fb 100644 --- a/yudao-module-mall/yudao-module-statistics-server/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-statistics-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-mall/yudao-module-trade-server/src/main/resources/application.yaml b/yudao-module-mall/yudao-module-trade-server/src/main/resources/application.yaml index b5eacc4c8..291586cdf 100644 --- a/yudao-module-mall/yudao-module-trade-server/src/main/resources/application.yaml +++ b/yudao-module-mall/yudao-module-trade-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-member/yudao-module-member-server/src/main/resources/application.yaml b/yudao-module-member/yudao-module-member-server/src/main/resources/application.yaml index 11ef4b74f..d96acfca6 100644 --- a/yudao-module-member/yudao-module-member-server/src/main/resources/application.yaml +++ b/yudao-module-member/yudao-module-member-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-mp/yudao-module-mp-server/src/main/resources/application.yaml b/yudao-module-mp/yudao-module-mp-server/src/main/resources/application.yaml index cf6c3e2ed..fe0dad385 100644 --- a/yudao-module-mp/yudao-module-mp-server/src/main/resources/application.yaml +++ b/yudao-module-mp/yudao-module-mp-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-pay/yudao-module-pay-server/src/main/resources/application.yaml b/yudao-module-pay/yudao-module-pay-server/src/main/resources/application.yaml index 7f597ab74..08e604694 100644 --- a/yudao-module-pay/yudao-module-pay-server/src/main/resources/application.yaml +++ b/yudao-module-pay/yudao-module-pay-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-report/yudao-module-report-server/src/main/resources/application.yaml b/yudao-module-report/yudao-module-report-server/src/main/resources/application.yaml index 7fa9f240f..90b417921 100644 --- a/yudao-module-report/yudao-module-report-server/src/main/resources/application.yaml +++ b/yudao-module-report/yudao-module-report-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml b/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml index 3f48e4a33..1c1e27d2e 100644 --- a/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml +++ b/yudao-module-system/yudao-module-system-server/src/main/resources/application.yaml @@ -54,7 +54,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 21d210422..fd68a9ab5 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -63,7 +63,7 @@ springdoc: default-flat-param-object: true # 参见 https://doc.xiaominfo.com/docs/faq/v4/knife4j-parameterobject-flat-param 文档 knife4j: - enable: false # TODO 芋艿:需要关闭增强,具体原因见:https://github.com/xiaoymin/knife4j/issues/874 + enable: true setting: language: zh_cn