From 9ebc3c49ec439cd273dc6301ceb123bc8195579c Mon Sep 17 00:00:00 2001 From: EightMonth Date: Thu, 3 Apr 2025 17:46:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96swagger=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E6=9E=B6=E6=9E=84=E6=94=B9=E9=80=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/jeecg/config/Swagger3Config.java | 14 +- .../src/main/resources/application-dev.yml | 5 +- .../src/main/resources/application-dm8.yml | 4 + .../main/resources/application-kingbase8.yml | 4 + .../src/main/resources/application-prod.yml | 4 + .../src/main/resources/application-test.yml | 4 + .../jeecg-cloud-gateway/pom.xml | 2 +- .../swagger/MySwaggerResourceProvider.java | 320 +++++++++--------- .../swagger/SwaggerResourceController.java | 93 +++-- .../src/main/resources/application-mysql.yml | 2 +- 10 files changed, 226 insertions(+), 226 deletions(-) diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java index 32d97cd5f..647986571 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger3Config.java @@ -3,7 +3,6 @@ package org.jeecg.config; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Paths; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; @@ -13,6 +12,7 @@ import lombok.extern.slf4j.Slf4j; import org.jeecg.common.constant.CommonConstant; import org.springdoc.core.GroupedOpenApi; import org.springdoc.core.customizers.GlobalOpenApiCustomizer; +import org.springdoc.core.filters.GlobalOpenApiMethodFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; @@ -55,16 +55,8 @@ public class Swagger3Config implements WebMvcConfigurer { } @Bean - public GroupedOpenApi swaggerOpenApi() { - return GroupedOpenApi.builder() - .group("default") - .packagesToScan("org.jeecg") - // 剔除以下几个包路径的接口生成文档 - .packagesToExclude("org.jeecg.modules.drag", "org.jeecg.modules.online", "org.jeecg.modules.jmreport") - // 加了Operation注解的方法,才生成接口文档 - .addOpenApiMethodFilter(method -> method.isAnnotationPresent(Operation.class)) - .addOpenApiCustomiser(globalOpenApiCustomizer()) - .build(); + public GlobalOpenApiMethodFilter globalOpenApiMethodFilter() { + return method -> method.isAnnotationPresent(Operation.class); } @Bean diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml index 99bc91498..dc0a62b8a 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml @@ -281,7 +281,10 @@ logging: level: org.flywaydb: debug org.jeecg.modules.system.mapper: info -#swagger +# springdoc-openapi项目配置 +springdoc: + auto-tag-classes: false + packages-to-scan: org.jeecg knife4j: #开启增强配置 enable: true diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dm8.yml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dm8.yml index 83adf884e..5b9473541 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dm8.yml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-dm8.yml @@ -143,6 +143,10 @@ spring: host: 127.0.0.1 port: 6379 password: '' +# springdoc-openapi项目配置 +springdoc: + auto-tag-classes: false + packages-to-scan: org.jeecg #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-kingbase8.yml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-kingbase8.yml index 4939915d5..e13806871 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-kingbase8.yml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-kingbase8.yml @@ -157,6 +157,10 @@ spring: host: 127.0.0.1 port: 6379 password: '' +# springdoc-openapi项目配置 +springdoc: + auto-tag-classes: false + packages-to-scan: org.jeecg #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml index b59f05e19..b6d768159 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-prod.yml @@ -161,6 +161,10 @@ spring: host: 127.0.0.1 port: 6379 password: '' +# springdoc-openapi项目配置 +springdoc: + auto-tag-classes: false + packages-to-scan: org.jeecg #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml index ef1b818df..b1921f819 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml +++ b/jeecg-boot/jeecg-module-system/jeecg-system-start/src/main/resources/application-test.yml @@ -161,6 +161,10 @@ spring: host: 192.168.1.188 port: 6379 password: '' +# springdoc-openapi项目配置 +springdoc: + auto-tag-classes: false + packages-to-scan: org.jeecg #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:org/jeecg/**/xml/*Mapper.xml diff --git a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/pom.xml b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/pom.xml index 117ad135e..8fae6e58d 100644 --- a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/pom.xml +++ b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/pom.xml @@ -73,7 +73,7 @@ com.github.xiaoymin - knife4j-gateway-spring-boot-starter + knife4j-openapi2-spring-boot-starter ${knife4j-spring-boot-starter.version} diff --git a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/MySwaggerResourceProvider.java b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/MySwaggerResourceProvider.java index 37937f40f..438a07224 100644 --- a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/MySwaggerResourceProvider.java +++ b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/MySwaggerResourceProvider.java @@ -1,160 +1,160 @@ -//package org.jeecg.handler.swagger; -// -//import cn.hutool.core.util.ArrayUtil; -//import cn.hutool.core.util.ObjectUtil; -//import com.alibaba.nacos.api.naming.NamingFactory; -//import com.alibaba.nacos.api.naming.NamingService; -//import com.alibaba.nacos.api.naming.pojo.Instance; -//import lombok.extern.slf4j.Slf4j; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.beans.factory.annotation.Value; -//import org.springframework.cloud.gateway.route.RouteLocator; -//import org.springframework.context.annotation.Primary; -//import org.springframework.stereotype.Component; -// -//import springfox.documentation.swagger.web.SwaggerResource; -//import springfox.documentation.swagger.web.SwaggerResourcesProvider; -// -//import java.util.*; -// -///** -// * 聚合各个服务的swagger接口 -// * @author zyf -// * @date: 2022/4/21 10:55 -// */ -//@Component -//@Slf4j -//@Primary -//public class MySwaggerResourceProvider implements SwaggerResourcesProvider { -// /** -// * swagger2默认的url后缀 -// */ -// private static final String SWAGGER2URL = "/v2/api-docs"; -// -// /** -// * 网关路由 -// */ -// private final RouteLocator routeLocator; -// /** -// * Nacos名字服务 -// */ -// private NamingService naming; -// -// /** -// * nacos服务地址 -// */ -// @Value("${spring.cloud.nacos.discovery.server-addr}") -// private String serverAddr; -// /** -// * nacos namespace -// */ -// @Value("${spring.cloud.nacos.discovery.namespace:#{null}}") -// private String namespace; -// -// /** -// * nacos groupName -// */ -// @Value("${spring.cloud.nacos.config.group:DEFAULT_GROUP:#{null}}") -// private String group; -// -// /** -// * nacos username -// */ -// @Value("${spring.cloud.nacos.discovery.username:#{null}}") -// private String username; -// /** -// * nacos password -// */ -// @Value("${spring.cloud.nacos.discovery.password:#{null}}") -// private String password; -// -// /** -// * Swagger中需要排除的服务 -// */ -// private String[] excludeServiceIds=new String[]{"jeecg-cloud-monitor"}; -// -// -// /** -// * 网关应用名称 -// */ -// @Value("${spring.application.name}") -// private String self; -// -// @Autowired -// public MySwaggerResourceProvider(RouteLocator routeLocator) { -// this.routeLocator = routeLocator; -// } -// -// @Override -// public List get() { -// List resources = new ArrayList<>(); -// List routeHosts = new ArrayList<>(); -// // 获取所有可用的host:serviceId -// routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null) -// .filter(route -> !self.equals(route.getUri().getHost())) -// .subscribe(route ->{ -// //update-begin---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开 -// boolean hasRoute=checkRoute(route.getId()); -// if(hasRoute){ -// routeHosts.add(route.getUri().getHost()); -// } -// //update-end---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开 -// }); -// -// // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上 -// Set dealed = new HashSet<>(); -// routeHosts.forEach(instance -> { -// // 拼接url -// String url = "/" + instance.toLowerCase() + SWAGGER2URL; -// if (!dealed.contains(url)) { -// dealed.add(url); -// log.info(" Gateway add SwaggerResource: {}",url); -// SwaggerResource swaggerResource = new SwaggerResource(); -// swaggerResource.setUrl(url); -// swaggerResource.setSwaggerVersion("2.0"); -// swaggerResource.setName(instance); -// //Swagger排除不展示的服务 -// if(!ArrayUtil.contains(excludeServiceIds,instance)){ -// resources.add(swaggerResource); -// } -// } -// }); -// return resources; -// } -// -// /** -// * 检测nacos中是否有健康实例 -// * @param routeId -// * @return -// */ -// private Boolean checkRoute(String routeId) { -// Boolean hasRoute = false; -// try { -// //修复使用带命名空间启动网关swagger看不到接口文档的问题 -// Properties properties=new Properties(); -// properties.setProperty("serverAddr",serverAddr); -// if(namespace!=null && !"".equals(namespace)){ -// log.info("nacos.discovery.namespace = {}", namespace); -// properties.setProperty("namespace",namespace); -// } -// if(username!=null && !"".equals(username)){ -// properties.setProperty("username",username); -// } -// if(password!=null && !"".equals(password)){ -// properties.setProperty("password",password); -// } -// //【issues/5115】因swagger文档导致gateway内存溢出 -// if (this.naming == null) { -// this.naming = NamingFactory.createNamingService(properties); -// } -// log.info(" config.group : {}", group); -// List list = this.naming.selectInstances(routeId, group , true); -// if (ObjectUtil.isNotEmpty(list)) { -// hasRoute = true; -// } -// } catch (Exception e) { -// e.printStackTrace(); -// } -// return hasRoute; -// } -//} \ No newline at end of file +package org.jeecg.handler.swagger; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.nacos.api.naming.NamingFactory; +import com.alibaba.nacos.api.naming.NamingService; +import com.alibaba.nacos.api.naming.pojo.Instance; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cloud.gateway.route.RouteLocator; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +import springfox.documentation.swagger.web.SwaggerResource; +import springfox.documentation.swagger.web.SwaggerResourcesProvider; + +import java.util.*; + +/** 已使用knife4j-gateway支持该功能 + * 聚合各个服务的swagger接口 + * @author zyf + * @date: 2022/4/21 10:55 + */ +@Component +@Slf4j +@Primary +public class MySwaggerResourceProvider implements SwaggerResourcesProvider { + /** + * swagger2默认的url后缀 + */ + private static final String SWAGGER2URL = "/v3/api-docs"; + + /** + * 网关路由 + */ + private final RouteLocator routeLocator; + /** + * Nacos名字服务 + */ + private NamingService naming; + + /** + * nacos服务地址 + */ + @Value("${spring.cloud.nacos.discovery.server-addr}") + private String serverAddr; + /** + * nacos namespace + */ + @Value("${spring.cloud.nacos.discovery.namespace:#{null}}") + private String namespace; + + /** + * nacos groupName + */ + @Value("${spring.cloud.nacos.config.group:DEFAULT_GROUP:#{null}}") + private String group; + + /** + * nacos username + */ + @Value("${spring.cloud.nacos.discovery.username:#{null}}") + private String username; + /** + * nacos password + */ + @Value("${spring.cloud.nacos.discovery.password:#{null}}") + private String password; + + /** + * Swagger中需要排除的服务 + */ + private String[] excludeServiceIds=new String[]{"jeecg-cloud-monitor"}; + + + /** + * 网关应用名称 + */ + @Value("${spring.application.name}") + private String self; + + @Autowired + public MySwaggerResourceProvider(RouteLocator routeLocator) { + this.routeLocator = routeLocator; + } + + @Override + public List get() { + List resources = new ArrayList<>(); + List routeHosts = new ArrayList<>(); + // 获取所有可用的host:serviceId + routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null) + .filter(route -> !self.equals(route.getUri().getHost())) + .subscribe(route ->{ + //update-begin---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开 + boolean hasRoute=checkRoute(route.getId()); + if(hasRoute){ + routeHosts.add(route.getUri().getHost()); + } + //update-end---author:zyf ---date:20220413 for:过滤掉无效路由,避免接口文档报错无法打开 + }); + + // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上 + Set dealed = new HashSet<>(); + routeHosts.forEach(instance -> { + // 拼接url + String url = "/" + instance.toLowerCase() + SWAGGER2URL; + if (!dealed.contains(url)) { + dealed.add(url); + log.info(" Gateway add SwaggerResource: {}",url); + SwaggerResource swaggerResource = new SwaggerResource(); + swaggerResource.setUrl(url); + swaggerResource.setSwaggerVersion("2.0"); + swaggerResource.setName(instance); + //Swagger排除不展示的服务 + if(!ArrayUtil.contains(excludeServiceIds,instance)){ + resources.add(swaggerResource); + } + } + }); + return resources; + } + + /** + * 检测nacos中是否有健康实例 + * @param routeId + * @return + */ + private Boolean checkRoute(String routeId) { + Boolean hasRoute = false; + try { + //修复使用带命名空间启动网关swagger看不到接口文档的问题 + Properties properties=new Properties(); + properties.setProperty("serverAddr",serverAddr); + if(namespace!=null && !"".equals(namespace)){ + log.info("nacos.discovery.namespace = {}", namespace); + properties.setProperty("namespace",namespace); + } + if(username!=null && !"".equals(username)){ + properties.setProperty("username",username); + } + if(password!=null && !"".equals(password)){ + properties.setProperty("password",password); + } + //【issues/5115】因swagger文档导致gateway内存溢出 + if (this.naming == null) { + this.naming = NamingFactory.createNamingService(properties); + } + log.info(" config.group : {}", group); + List list = this.naming.selectInstances(routeId, group , true); + if (ObjectUtil.isNotEmpty(list)) { + hasRoute = true; + } + } catch (Exception e) { + e.printStackTrace(); + } + return hasRoute; + } +} \ No newline at end of file diff --git a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/SwaggerResourceController.java b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/SwaggerResourceController.java index 1268d7200..6a6391101 100644 --- a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/SwaggerResourceController.java +++ b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-gateway/src/main/java/org/jeecg/handler/swagger/SwaggerResourceController.java @@ -1,52 +1,41 @@ -//package org.jeecg.handler.swagger; -// -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.beans.factory.annotation.Value; -//import org.springframework.http.HttpStatus; -//import org.springframework.http.ResponseEntity; -//import org.springframework.web.bind.annotation.RequestMapping; -//import org.springframework.web.bind.annotation.RestController; -//import springfox.documentation.swagger.web.*; -// -//import java.util.ArrayList; -//import java.util.List; -// -///** -// * swagger聚合接口,三个接口都是 doc.html需要访问的接口 -// * @author zyf -// * @date: 2022/4/21 10:55 -// */ -//@RestController -//@RequestMapping("/swagger-resources") -//public class SwaggerResourceController { -// private MySwaggerResourceProvider swaggerResourceProvider; -// /** -// * 生产环境,关闭swagger文档 -// */ -// @Value("${knife4j.production:#{null}}") -// private Boolean production; -// -// @Autowired -// public SwaggerResourceController(MySwaggerResourceProvider swaggerResourceProvider) { -// this.swaggerResourceProvider = swaggerResourceProvider; -// } -// -// @RequestMapping(value = "/configuration/security") -// public ResponseEntity securityConfiguration() { -// return new ResponseEntity<>(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK); -// } -// -// @RequestMapping(value = "/configuration/ui") -// public ResponseEntity uiConfiguration() { -// return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK); -// } -// -// @RequestMapping -// public ResponseEntity> swaggerResources() { -// // 是否开启生产环境屏蔽swagger -// if (production != null && production) { -// return new ResponseEntity<>(new ArrayList<>(), HttpStatus.OK); -// } -// return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK); -// } -//} \ No newline at end of file +package org.jeecg.handler.swagger; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import springfox.documentation.swagger.web.*; + +import java.util.List; + +/** 已使用knife4j-gateway支持该功能 + * swagger聚合接口,三个接口都是 doc.html需要访问的接口 + * @author zyf + * @date: 2022/4/21 10:55 + */ +@RestController +@RequestMapping("/swagger-resources") +public class SwaggerResourceController { + private MySwaggerResourceProvider swaggerResourceProvider; + + @Autowired + public SwaggerResourceController(MySwaggerResourceProvider swaggerResourceProvider) { + this.swaggerResourceProvider = swaggerResourceProvider; + } + + @RequestMapping(value = "/configuration/security") + public ResponseEntity securityConfiguration() { + return new ResponseEntity<>(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK); + } + + @RequestMapping(value = "/configuration/ui") + public ResponseEntity uiConfiguration() { + return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK); + } + + @RequestMapping + public ResponseEntity> swaggerResources() { + return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK); + } +} \ No newline at end of file diff --git a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos/src/main/resources/application-mysql.yml b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos/src/main/resources/application-mysql.yml index 89fe5563a..f21be8f19 100644 --- a/jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos/src/main/resources/application-mysql.yml +++ b/jeecg-boot/jeecg-server-cloud/jeecg-cloud-nacos/src/main/resources/application-mysql.yml @@ -13,7 +13,7 @@ spring: db: num: 1 password: - '0': ${MYSQL-PWD:root} + '0': ${MYSQL-PWD:root@2023} url: '0': jdbc:mysql://${MYSQL-HOST:jeecg-boot-mysql}:${MYSQL-PORT:3306}/${MYSQL-DB:nacos}?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true user: