diff --git a/config/dev/application-common.yml b/config/dev/application-common.yml
index 69b04b59..2882c5ff 100644
--- a/config/dev/application-common.yml
+++ b/config/dev/application-common.yml
@@ -63,10 +63,6 @@ dubbo:
log-level: info
spring:
- mvc:
- pathmatch:
- # 适配 boot 2.6 路由与 springfox 兼容
- matching-strategy: ANT_PATH_MATCHER
# 资源信息
messages:
# 国际化资源文件路径
@@ -242,17 +238,25 @@ mybatis-plus:
swagger:
# 是否开启swagger
enabled: true
- # 标题
- title: '标题:RuoYi-Cloud-Plus微服务权限管理系统_接口文档'
- # 描述
- description: '描述:微服务权限管理系统, 具体包括XXX,XXX模块...'
- # 版本
- version: '版本号:系统版本...'
- # 作者信息
- contact:
- name: Lion Li
- email: crazylionli@163.com
- url: https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus
+ info:
+ # 标题
+ title: '标题:RuoYi-Cloud-Plus微服务权限管理系统_接口文档'
+ # 描述
+ description: '描述:微服务权限管理系统, 具体包括XXX,XXX模块...'
+ # 版本
+ version: '版本号:系统版本...'
+ # 作者信息
+ contact:
+ name: Lion Li
+ email: crazylionli@163.com
+ url: https://gitee.com/JavaLionLi/RuoYi-Cloud-Plus
+ components:
+ # 鉴权方式配置
+ security-schemes:
+ apiKey:
+ type: APIKEY
+ in: HEADER
+ name: ${sa-token.token-name}
# seata配置
seata:
diff --git a/pom.xml b/pom.xml
index b13f58f5..74a2e35f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,6 +28,8 @@
3.5.1
2.3
1.2.83
+ 2.2.0
+ 1.6.9
5.2.2
3.1.1
5.8.4
@@ -35,6 +37,7 @@
2.2.2
2.3.1
1.30.0
+ 1.18.24
7.1.1
@@ -178,6 +181,30 @@
${p6spy.version}
+
+ io.swagger.core.v3
+ swagger-annotations
+ ${swagger.core.version}
+
+
+
+ org.springdoc
+ springdoc-openapi-webmvc-core
+ ${springdoc.version}
+
+
+
+ org.springdoc
+ springdoc-openapi-javadoc
+ ${springdoc.version}
+
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
org.apache.poi
poi
@@ -300,6 +327,23 @@
${java.version}
${java.version}
${project.build.sourceEncoding}
+
+
+ com.github.therapi
+ therapi-runtime-javadoc-scribe
+ 0.13.0
+
+
+ org.projectlombok
+ lombok
+ ${lombok.version}
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ ${spring-boot.version}
+
+
diff --git a/ruoyi-auth/pom.xml b/ruoyi-auth/pom.xml
index dd9eeb4d..e29d8556 100644
--- a/ruoyi-auth/pom.xml
+++ b/ruoyi-auth/pom.xml
@@ -46,6 +46,11 @@
ruoyi-common-security
+
+ com.ruoyi
+ ruoyi-common-doc
+
+
com.ruoyi
ruoyi-common-web
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 2c40aeeb..13f4039e 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -16,6 +16,7 @@
ruoyi-common-excel
ruoyi-common-core
ruoyi-common-redis
+ ruoyi-common-doc
ruoyi-common-security
ruoyi-common-satoken
ruoyi-common-web
diff --git a/ruoyi-common/ruoyi-common-bom/pom.xml b/ruoyi-common/ruoyi-common-bom/pom.xml
index 3567b8f6..57654bbe 100644
--- a/ruoyi-common/ruoyi-common-bom/pom.xml
+++ b/ruoyi-common/ruoyi-common-bom/pom.xml
@@ -22,6 +22,13 @@
${project.version}
+
+
+ com.ruoyi
+ ruoyi-common-doc
+ ${project.version}
+
+
com.ruoyi
diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml
index ef2d3dba..12fc1537 100644
--- a/ruoyi-common/ruoyi-common-core/pom.xml
+++ b/ruoyi-common/ruoyi-common-core/pom.xml
@@ -73,6 +73,11 @@
javax.servlet-api
+
+ io.swagger.core.v3
+ swagger-annotations
+
+
org.projectlombok
lombok
diff --git a/ruoyi-common/ruoyi-common-swagger/pom.xml b/ruoyi-common/ruoyi-common-doc/pom.xml
similarity index 75%
rename from ruoyi-common/ruoyi-common-swagger/pom.xml
rename to ruoyi-common/ruoyi-common-doc/pom.xml
index 4de434d2..d1455329 100644
--- a/ruoyi-common/ruoyi-common-swagger/pom.xml
+++ b/ruoyi-common/ruoyi-common-doc/pom.xml
@@ -9,7 +9,7 @@
4.0.0
- ruoyi-common-swagger
+ ruoyi-common-doc
ruoyi-common-swagger系统接口
@@ -23,15 +23,14 @@
ruoyi-common-core
-
- com.ruoyi
- ruoyi-common-web
+ org.springdoc
+ springdoc-openapi-webmvc-core
- cn.dev33
- sa-token-core
+ org.springdoc
+ springdoc-openapi-javadoc
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerAutoConfiguration.java b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerAutoConfiguration.java
new file mode 100644
index 00000000..14aa3564
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/SwaggerAutoConfiguration.java
@@ -0,0 +1,78 @@
+package com.ruoyi.common.doc.config;
+
+import com.ruoyi.common.doc.handler.OpenApiHandler;
+import com.ruoyi.common.doc.config.properties.SwaggerProperties;
+import io.swagger.v3.oas.models.OpenAPI;
+import io.swagger.v3.oas.models.info.Info;
+import io.swagger.v3.oas.models.security.SecurityRequirement;
+import lombok.RequiredArgsConstructor;
+import org.springdoc.core.*;
+import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
+import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
+import org.springdoc.core.providers.JavadocProvider;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Swagger 文档配置
+ *
+ * @author Lion Li
+ */
+@RequiredArgsConstructor
+@AutoConfiguration(before = SpringDocConfiguration.class)
+@EnableConfigurationProperties(SwaggerProperties.class)
+@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true", matchIfMissing = true)
+public class SwaggerAutoConfiguration {
+
+ private final SwaggerProperties swaggerProperties;
+
+ @Bean
+ @ConditionalOnMissingBean(OpenAPI.class)
+ public OpenAPI openApi() {
+ OpenAPI openApi = new OpenAPI();
+ // 文档基本信息
+ SwaggerProperties.InfoProperties infoProperties = swaggerProperties.getInfo();
+ Info info = convertInfo(infoProperties);
+ openApi.info(info);
+ // 扩展文档信息
+ openApi.externalDocs(swaggerProperties.getExternalDocs());
+ openApi.tags(swaggerProperties.getTags());
+ openApi.paths(swaggerProperties.getPaths());
+ openApi.components(swaggerProperties.getComponents());
+ List list = new ArrayList<>();
+ list.add(new SecurityRequirement().addList("apikey"));
+ openApi.security(list);
+
+ return openApi;
+ }
+
+ private Info convertInfo(SwaggerProperties.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,
+ SecurityService securityParser,
+ SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
+ Optional> openApiBuilderCustomisers,
+ Optional> serverBaseUrlCustomisers, Optional javadocProvider) {
+ return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider);
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java
new file mode 100644
index 00000000..7e157c1f
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/config/properties/SwaggerProperties.java
@@ -0,0 +1,99 @@
+package com.ruoyi.common.doc.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 = "swagger")
+public class SwaggerProperties {
+
+ /**
+ * 是否开启 openApi 文档
+ */
+ private Boolean enabled = true;
+
+ /**
+ * 文档基本信息
+ */
+ @NestedConfigurationProperty
+ private InfoProperties info = new InfoProperties();
+
+ /**
+ * 扩展文档地址
+ */
+ @NestedConfigurationProperty
+ private ExternalDocumentation externalDocs;
+
+ /**
+ * 标签
+ */
+ private List tags = null;
+
+ /**
+ * 路径
+ */
+ @NestedConfigurationProperty
+ private Paths paths = null;
+
+ /**
+ * 组件
+ */
+ @NestedConfigurationProperty
+ private Components components = null;
+
+ /**
+ *
+ * 文档的基础属性信息
+ *
+ *
+ * @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;
+
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java
new file mode 100644
index 00000000..4e0dbd49
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/java/com/ruoyi/common/doc/handler/OpenApiHandler.java
@@ -0,0 +1,272 @@
+package com.ruoyi.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 org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springdoc.core.OpenAPIService;
+import org.springdoc.core.PropertyResolverUtils;
+import org.springdoc.core.SecurityService;
+import org.springdoc.core.SpringDocConfigProperties;
+import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
+import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
+import org.springdoc.core.providers.JavadocProvider;
+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 处理器
+ * 对源码功能进行修改 增强使用
+ */
+@SuppressWarnings("all")
+public class OpenApiHandler extends OpenAPIService {
+
+ /**
+ * The constant LOGGER.
+ */
+ private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIService.class);
+
+ /**
+ * The Context.
+ */
+ private ApplicationContext context;
+
+ /**
+ * The Security parser.
+ */
+ private final SecurityService securityParser;
+
+ /**
+ * The Mappings map.
+ */
+ private final Map mappingsMap = new HashMap<>();
+
+ /**
+ * The Springdoc tags.
+ */
+ private final Map springdocTags = new HashMap<>();
+
+ /**
+ * The Open api builder customisers.
+ */
+ private final Optional> openApiBuilderCustomisers;
+
+ /**
+ * The server base URL customisers.
+ */
+ private final Optional> serverBaseUrlCustomizers;
+
+ /**
+ * The Spring doc config properties.
+ */
+ private final SpringDocConfigProperties springDocConfigProperties;
+
+ /**
+ * The Open api.
+ */
+ private OpenAPI openAPI;
+
+ /**
+ * The Cached open api map.
+ */
+ private final Map cachedOpenAPI = new HashMap<>();
+
+ /**
+ * The Is servers present.
+ */
+ private boolean isServersPresent;
+
+ /**
+ * The Server base url.
+ */
+ private String serverBaseUrl;
+
+ /**
+ * The Property resolver utils.
+ */
+ private final PropertyResolverUtils propertyResolverUtils;
+
+ /**
+ * The javadoc provider.
+ */
+ private final Optional javadocProvider;
+
+ /**
+ * The Basic error controller.
+ */
+ private static Class> basicErrorController;
+
+ static {
+ try {
+ //spring-boot 2
+ basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController");
+ } catch (ClassNotFoundException e) {
+ //spring-boot 1
+ try {
+ basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.BasicErrorController");
+ } catch (ClassNotFoundException classNotFoundException) {
+ //Basic error controller class not found
+ LOGGER.trace(classNotFoundException.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 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, SecurityService securityParser,
+ SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
+ Optional> openApiBuilderCustomizers,
+ Optional> serverBaseUrlCustomizers,
+ Optional 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 tags = new HashSet<>();
+ Set 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 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 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 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 tags, Set tagsStr, Locale locale) {
+ // method tags
+ Set tagsSet = AnnotatedElementUtils
+ .findAllMergedAnnotations(method, Tags.class);
+ Set 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 allTags = new ArrayList<>(methodTags);
+ addTags(allTags, tags, locale);
+ }
+ }
+
+ private void addTags(List sourceTags, Set tags, Locale locale) {
+ Optional> 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);
+ });
+ });
+ }
+
+}
diff --git a/ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..e3302e60
--- /dev/null
+++ b/ruoyi-common/ruoyi-common-doc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+com.ruoyi.common.doc.config.SwaggerAutoConfiguration
diff --git a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java b/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java
deleted file mode 100644
index 58df8cff..00000000
--- a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerAutoConfiguration.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.ruoyi.common.swagger.config;
-
-import cn.dev33.satoken.config.SaTokenConfig;
-import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
-import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.swagger.config.properties.SwaggerProperties;
-import io.swagger.models.auth.In;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.autoconfigure.AutoConfiguration;
-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.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.*;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spi.service.contexts.SecurityContext;
-import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
-import springfox.documentation.spring.web.plugins.Docket;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Predicate;
-
-/**
- * Swagger 文档配置
- *
- * @author Lion Li
- */
-@AutoConfiguration
-@EnableKnife4j
-@EnableConfigurationProperties(SwaggerProperties.class)
-@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
-public class SwaggerAutoConfiguration {
-
- @Autowired
- private SaTokenConfig saTokenConfig;
-
- @Value("${spring.application.name}")
- private String appName;
-
- /**
- * 默认的排除路径,排除Spring Boot默认的错误处理路径和端点
- */
- private static final List DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**");
-
- private static final String BASE_PATH = "/**";
-
- @Bean
- public Docket api(SwaggerProperties swaggerProperties) {
- // base-path处理
- if (swaggerProperties.getBasePath().isEmpty()) {
- swaggerProperties.getBasePath().add(BASE_PATH);
- }
- // noinspection unchecked
- List> basePath = new ArrayList<>();
- swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path)));
-
- // exclude-path处理
- if (swaggerProperties.getExcludePath().isEmpty()) {
- swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH);
- }
-
- List> excludePath = new ArrayList<>();
- swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path)));
-
- ApiSelectorBuilder builder = new Docket(DocumentationType.OAS_30)
- .enable(swaggerProperties.getEnabled())
- .host(swaggerProperties.getHost())
- .apiInfo(apiInfo(swaggerProperties))
- .select()
- .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage()));
-
- swaggerProperties.getBasePath().forEach(p -> builder.paths(PathSelectors.ant(p)));
- swaggerProperties.getExcludePath().forEach(p -> builder.paths(PathSelectors.ant(p).negate()));
-
- return builder.build()
- .securitySchemes(securitySchemes())
- .securityContexts(securityContexts())
- .pathMapping(StringUtils.substring(appName, appName.indexOf("-") + 1));
- }
-
- /**
- * 安全模式,这里指定token通过Authorization头请求头传递
- */
- private List securitySchemes() {
- List apiKeyList = new ArrayList<>();
- String header = saTokenConfig.getTokenName();
- apiKeyList.add(new ApiKey(header, header, In.HEADER.toValue()));
- return apiKeyList;
- }
-
- /**
- * 安全上下文
- */
- private List securityContexts() {
- List securityContexts = new ArrayList<>();
- securityContexts.add(
- SecurityContext.builder()
- .securityReferences(defaultAuth())
- .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
- .build());
- return securityContexts;
- }
-
- /**
- * 默认的全局鉴权策略
- */
- private List defaultAuth() {
- AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
- AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
- authorizationScopes[0] = authorizationScope;
- List securityReferences = new ArrayList<>();
- securityReferences.add(new SecurityReference(saTokenConfig.getTokenName(), authorizationScopes));
- return securityReferences;
- }
-
- private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
- return new ApiInfoBuilder()
- .title(swaggerProperties.getTitle())
- .description(swaggerProperties.getDescription())
- .license(swaggerProperties.getLicense())
- .licenseUrl(swaggerProperties.getLicenseUrl())
- .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
- .contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
- .version(swaggerProperties.getVersion())
- .build();
- }
-}
diff --git a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerBeanPostProcessor.java b/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerBeanPostProcessor.java
deleted file mode 100644
index 2436a550..00000000
--- a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/SwaggerBeanPostProcessor.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.ruoyi.common.swagger.config;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-import org.springframework.util.ReflectionUtils;
-import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
-import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
-import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
-
-import java.lang.reflect.Field;
-import java.util.List;
-
-/**
- * swagger 在 springboot 2.6.x 不兼容问题的处理
- *
- * @author ruoyi
- */
-@SuppressWarnings("all")
-public class SwaggerBeanPostProcessor implements BeanPostProcessor {
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
- customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
- }
- return bean;
- }
-
- private void customizeSpringfoxHandlerMappings(List mappings) {
- mappings.removeIf(mapping -> mapping.getPatternParser() != null);
- }
-
- private List getHandlerMappings(Object bean) {
- try {
- Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
- field.setAccessible(true);
- return (List) field.get(bean);
- } catch (IllegalArgumentException | IllegalAccessException e) {
- throw new IllegalStateException(e);
- }
- }
-}
diff --git a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/properties/SwaggerProperties.java b/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/properties/SwaggerProperties.java
deleted file mode 100644
index 12cf880c..00000000
--- a/ruoyi-common/ruoyi-common-swagger/src/main/java/com/ruoyi/common/swagger/config/properties/SwaggerProperties.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.ruoyi.common.swagger.config.properties;
-
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import lombok.experimental.Accessors;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * swagger 配置属性
- *
- * @author Lion Li
- */
-@Data
-@ConfigurationProperties("swagger")
-public class SwaggerProperties {
-
- /**
- * 是否开启swagger
- */
- private Boolean enabled;
-
- /**
- * swagger会解析的包路径
- **/
- private String basePackage = "";
-
- /**
- * swagger会解析的url规则
- **/
- private List basePath = new ArrayList<>();
-
- /**
- * 在basePath基础上需要排除的url规则
- **/
- private List excludePath = new ArrayList<>();
-
- /**
- * 标题
- **/
- private String title = "";
-
- /**
- * 描述
- **/
- private String description = "";
-
- /**
- * 版本
- **/
- private String version = "";
-
- /**
- * 许可证
- **/
- private String license = "";
-
- /**
- * 许可证URL
- **/
- private String licenseUrl = "";
-
- /**
- * 服务条款URL
- **/
- private String termsOfServiceUrl = "";
-
- /**
- * host信息
- **/
- private String host = "";
-
- /**
- * 联系人信息
- */
- private Contact contact = new Contact();
-
- /**
- * 全局统一鉴权配置
- **/
- private Authorization authorization = new Authorization();
-
- @Data
- @NoArgsConstructor
- public static class Contact {
-
- /**
- * 联系人
- **/
- private String name = "";
- /**
- * 联系人url
- **/
- private String url = "";
- /**
- * 联系人email
- **/
- private String email = "";
-
- }
-
- @Data
- @NoArgsConstructor
- public static class Authorization {
-
- /**
- * 鉴权策略ID,需要和SecurityReferences ID保持一致
- */
- private String name = "";
-
- /**
- * 需要开启鉴权URL的正则
- */
- private String authRegex = "^.*$";
-
- /**
- * 鉴权作用域列表
- */
- private List authorizationScopeList = new ArrayList<>();
-
- private List tokenUrlList = new ArrayList<>();
-
- }
-
- @Data
- @NoArgsConstructor
- public static class AuthorizationScope {
-
- /**
- * 作用域名称
- */
- private String scope = "";
-
- /**
- * 作用域描述
- */
- private String description = "";
-
- }
-
-}
diff --git a/ruoyi-common/ruoyi-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
deleted file mode 100644
index bab0482f..00000000
--- a/ruoyi-common/ruoyi-common-swagger/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ /dev/null
@@ -1,2 +0,0 @@
-com.ruoyi.common.swagger.config.SwaggerAutoConfiguration
-com.ruoyi.common.swagger.config.SwaggerBeanPostProcessor
diff --git a/ruoyi-example/ruoyi-demo/pom.xml b/ruoyi-example/ruoyi-demo/pom.xml
index 27e496af..d8c74b3d 100644
--- a/ruoyi-example/ruoyi-demo/pom.xml
+++ b/ruoyi-example/ruoyi-demo/pom.xml
@@ -52,6 +52,11 @@
ruoyi-common-log
+
+ com.ruoyi
+ ruoyi-common-doc
+
+
com.ruoyi
ruoyi-common-web
diff --git a/ruoyi-example/ruoyi-stream-mq/pom.xml b/ruoyi-example/ruoyi-stream-mq/pom.xml
index c31ab311..d9bed52b 100644
--- a/ruoyi-example/ruoyi-stream-mq/pom.xml
+++ b/ruoyi-example/ruoyi-stream-mq/pom.xml
@@ -61,6 +61,11 @@
ruoyi-common-security
+
+ com.ruoyi
+ ruoyi-common-doc
+
+
com.ruoyi
ruoyi-common-web
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java
index 3a05cdd7..b0d99b5b 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java
@@ -1,47 +1,54 @@
-package com.ruoyi.gateway.handler;
-
-import com.ruoyi.gateway.utils.WebFluxUtils;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
-import org.springframework.cloud.gateway.support.NotFoundException;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.annotation.Order;
-import org.springframework.http.server.reactive.ServerHttpResponse;
-import org.springframework.web.server.ResponseStatusException;
-import org.springframework.web.server.ServerWebExchange;
-import reactor.core.publisher.Mono;
-
-/**
- * 网关统一异常处理
- *
- * @author ruoyi
- */
-@Slf4j
-@Order(-1)
-@Configuration
-public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
-
- @Override
- public Mono handle(ServerWebExchange exchange, Throwable ex) {
- ServerHttpResponse response = exchange.getResponse();
-
- if (exchange.getResponse().isCommitted()) {
- return Mono.error(ex);
- }
-
- String msg;
-
- if (ex instanceof NotFoundException) {
- msg = "服务未找到";
- } else if (ex instanceof ResponseStatusException) {
- ResponseStatusException responseStatusException = (ResponseStatusException) ex;
- msg = responseStatusException.getMessage();
- } else {
- msg = "内部服务器错误";
- }
-
- log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
-
- return WebFluxUtils.webFluxResponseWriter(response, msg);
- }
-}
\ No newline at end of file
+package com.ruoyi.gateway.handler;
+
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.gateway.utils.WebFluxUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+import org.springframework.cloud.gateway.support.NotFoundException;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.server.RequestPath;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * 网关统一异常处理
+ *
+ * @author ruoyi
+ */
+@Slf4j
+@Order(-1)
+@Configuration
+public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
+
+ private static final String[] IGNORE_PATH = new String[]{"/favicon.ico"};
+
+ @Override
+ public Mono handle(ServerWebExchange exchange, Throwable ex) {
+ ServerHttpResponse response = exchange.getResponse();
+
+ if (exchange.getResponse().isCommitted()) {
+ return Mono.error(ex);
+ }
+
+ String msg;
+
+ if (ex instanceof NotFoundException) {
+ msg = "服务未找到";
+ } else if (ex instanceof ResponseStatusException) {
+ ResponseStatusException responseStatusException = (ResponseStatusException) ex;
+ msg = responseStatusException.getMessage();
+ } else {
+ msg = "内部服务器错误";
+ }
+
+ RequestPath path = exchange.getRequest().getPath();
+ if (!StringUtils.equalsAny(path.toString(), IGNORE_PATH)) {
+ log.error("[网关异常处理]请求路径:{},异常信息:{}", path, ex.getMessage());
+ }
+
+ return WebFluxUtils.webFluxResponseWriter(response, msg);
+ }
+}
diff --git a/ruoyi-modules/ruoyi-gen/pom.xml b/ruoyi-modules/ruoyi-gen/pom.xml
index 5b636428..e381cc68 100644
--- a/ruoyi-modules/ruoyi-gen/pom.xml
+++ b/ruoyi-modules/ruoyi-gen/pom.xml
@@ -59,6 +59,11 @@
ruoyi-common-log
+
+ com.ruoyi
+ ruoyi-common-doc
+
+
com.ruoyi
ruoyi-common-web
diff --git a/ruoyi-modules/ruoyi-resource/pom.xml b/ruoyi-modules/ruoyi-resource/pom.xml
index ffdd0376..11806ca6 100644
--- a/ruoyi-modules/ruoyi-resource/pom.xml
+++ b/ruoyi-modules/ruoyi-resource/pom.xml
@@ -47,6 +47,11 @@
spring-boot-starter-actuator
+
+ com.ruoyi
+ ruoyi-common-doc
+
+
com.ruoyi
ruoyi-common-dubbo
diff --git a/ruoyi-modules/ruoyi-system/pom.xml b/ruoyi-modules/ruoyi-system/pom.xml
index 59602495..639aa3b1 100644
--- a/ruoyi-modules/ruoyi-system/pom.xml
+++ b/ruoyi-modules/ruoyi-system/pom.xml
@@ -58,6 +58,11 @@
ruoyi-common-dict
+
+ com.ruoyi
+ ruoyi-common-doc
+
+
com.ruoyi
ruoyi-common-web