From 2ca07a12aa156ca44dea67a1413f7a47b1e80f6a Mon Sep 17 00:00:00 2001 From: 75681 <756810279@qq.com> Date: Tue, 12 Aug 2025 20:34:57 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=BA=86YAML=E4=B8=AD?= =?UTF-8?q?=E7=9A=84=E9=87=8D=E5=A4=8D=E7=BB=84=E9=85=8D=E7=BD=AE=EF=BC=8C?= =?UTF-8?q?=E4=BF=9D=E6=8C=81Java=20Bean=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- pom.xml | 126 +++++++++++++++++- .../youfool/devops/DevOpsApplication.java | 19 ++- .../devops/config/SpringDocOpenApiConfig.java | 114 ++++++++++++++++ .../youfool/devops/config/SwaggerKnife4j.java | 123 ----------------- src/main/resources/application-dev.yml | 18 +++ src/main/resources/application-prod.yml | 7 + 7 files changed, 278 insertions(+), 133 deletions(-) create mode 100644 src/main/java/com/chinaweal/youfool/devops/config/SpringDocOpenApiConfig.java delete mode 100644 src/main/java/com/chinaweal/youfool/devops/config/SwaggerKnife4j.java diff --git a/.gitignore b/.gitignore index 6ff364a..9d9e6d5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,6 @@ /PowerShell启动说明.md /DEPLOYMENT.md /ERROR_CAPTURE_GUIDE.md -/*.sql \ No newline at end of file +/*.sql +/JDK21_UPGRADE_NOTES.md +/start-jdk21.sh \ No newline at end of file diff --git a/pom.xml b/pom.xml index 973930c..c74d1fc 100644 --- a/pom.xml +++ b/pom.xml @@ -14,17 +14,25 @@ org.springframework.boot spring-boot-starter-parent - 2.2.6.RELEASE + 2.7.18 - 1.8 - 1.8 - 1.8 + 21 + 21 + 21 + 21 true 2.17.1 1.2.9 1.12.0 + + 1.18.34 + 3.5.16 + 1.2.23 + 3.5.7 + + 1.8.0 @@ -50,19 +58,36 @@ org.apache.shiro shiro-spring + + + com.github.xiaoymin + knife4j-spring-boot-starter + + + io.springfox + springfox-swagger2 + + + io.springfox + springfox-swagger-ui + + + io.springfox + springfox-boot-starter + com.alibaba druid-spring-boot-starter - 1.1.21 + ${druid.version} org.projectlombok lombok - 1.18.30 + ${lombok.version} provided @@ -137,7 +162,7 @@ org.mybatis mybatis - 3.5.6 + ${mybatis.version} @@ -145,6 +170,37 @@ shiro-spring ${shiro.version} + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springdoc + springdoc-openapi-ui + ${springdoc.version} + + + + org.springdoc + springdoc-openapi-webmvc-core + ${springdoc.version} + + + + io.springfox + springfox-swagger2 + 2.9.2 + compile + + + + com.github.xiaoymin + knife4j-annotations + 2.0.9 + compile + devops-api-gd @@ -152,6 +208,62 @@ org.springframework.boot spring-boot-maven-plugin + + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang.reflect=ALL-UNNAMED + --add-opens java.base/java.time=ALL-UNNAMED + --add-opens java.desktop/java.beans=ALL-UNNAMED + + + + org.projectlombok + lombok + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.12.1 + + 21 + 21 + 21 + + + org.projectlombok + lombok + ${lombok.version} + + + + --add-opens + java.base/java.util=ALL-UNNAMED + --add-opens + java.base/java.lang=ALL-UNNAMED + --add-opens + java.base/java.lang.reflect=ALL-UNNAMED + -Xlint:deprecation + -Xlint:unchecked + -Xlint:-options + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + --add-opens java.base/java.util=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang.reflect=ALL-UNNAMED + --add-opens java.base/java.time=ALL-UNNAMED + + diff --git a/src/main/java/com/chinaweal/youfool/devops/DevOpsApplication.java b/src/main/java/com/chinaweal/youfool/devops/DevOpsApplication.java index 534883e..2ad01ba 100644 --- a/src/main/java/com/chinaweal/youfool/devops/DevOpsApplication.java +++ b/src/main/java/com/chinaweal/youfool/devops/DevOpsApplication.java @@ -54,6 +54,7 @@ public class DevOpsApplication extends SpringBootServletInitializer implements A log.info("====== 程 序:{} !", applicationName); log.info("====== 版本号:{} ", version); log.info("====== 描 述:{} ", description); + log.info("====== Java环境:{}", getJavaVersionInfo()); log.info("====== 接口文档路径:/doc.html,账号:admin、密码:123456。注:如果乱码请指定VM -Dfile.encoding=UTF-8"); log.info("====== Druid Monitor路径:/druid,账号:admin、密码:123456"); @@ -173,7 +174,7 @@ public class DevOpsApplication extends SpringBootServletInitializer implements A private static boolean isJava9OrHigher() { try { String version = System.getProperty("java.version"); - // Java 8: 1.8.x, Java 9+: 9.x, 10.x, 11.x, etc. + // Java 8: 1.8.x, Java 9+: 9.x, 10.x, 11.x, 21.x, etc. if (version.startsWith("1.8")) { return false; } @@ -186,7 +187,21 @@ public class DevOpsApplication extends SpringBootServletInitializer implements A } catch (Exception e) { log.warn("解析Java版本失败: " + System.getProperty("java.version"), e); } - return false; // 默认认为是Java 8 + return true; // JDK 21环境下默认为true + } + + /** + * 获取当前Java版本信息 + */ + private static String getJavaVersionInfo() { + try { + String version = System.getProperty("java.version"); + String vendor = System.getProperty("java.vendor"); + String vmName = System.getProperty("java.vm.name"); + return String.format("Java %s (%s - %s)", version, vendor, vmName); + } catch (Exception e) { + return "Java version unknown"; + } } /** diff --git a/src/main/java/com/chinaweal/youfool/devops/config/SpringDocOpenApiConfig.java b/src/main/java/com/chinaweal/youfool/devops/config/SpringDocOpenApiConfig.java new file mode 100644 index 0000000..4274e53 --- /dev/null +++ b/src/main/java/com/chinaweal/youfool/devops/config/SpringDocOpenApiConfig.java @@ -0,0 +1,114 @@ +package com.chinaweal.youfool.devops.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springdoc.core.GroupedOpenApi; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * SpringDoc OpenAPI 配置类 (替换SpringFox) + * @author itluck + */ +@Configuration +@ConditionalOnProperty(value = "swagger.enable", havingValue = "true") +public class SpringDocOpenApiConfig { + + @Value("${applicationName}") + private String applicationName; + + @Value("${version:1.0.0}") + private String version; + + @Value("${description:DevOps运维管理系统}") + private String description; + + @Value("${license:Apache 2.0}") + private String license; + + /** + * 配置OpenAPI基本信息 + */ + @Bean + public OpenAPI customOpenAPI() { + return new OpenAPI() + .info(new Info() + .title(applicationName) + .description(description) + .version(version) + .contact(new Contact() + .name("chinaweal") + .url("https://www.chinaweal.com.cn") + .email("")) + .license(new License() + .name(license) + .url("https://www.chinaweal.com.cn"))) + .components(new Components() + .addSecuritySchemes("token", new SecurityScheme() + .type(SecurityScheme.Type.APIKEY) + .in(SecurityScheme.In.HEADER) + .name("token") + .description("令牌"))); + } + + /** + * 组织架构模块API分组 + */ + @Bean + public GroupedOpenApi orgApi() { + return GroupedOpenApi.builder() + .group("组织架构") + .packagesToScan("com.chinaweal.youfool.devops.org") + .build(); + } + + /** + * 运维报障模块API分组 + */ + @Bean + public GroupedOpenApi devopsApi() { + return GroupedOpenApi.builder() + .group("运维报障") + .packagesToScan("com.chinaweal.youfool.devops.repair") + .build(); + } + + /** + * 基础环境模块API分组 + */ + @Bean + public GroupedOpenApi basisApi() { + return GroupedOpenApi.builder() + .group("基础环境") + .packagesToScan("com.chinaweal.youfool.devops.base") + .build(); + } + + /** + * WebSocket测试环境API分组 + */ + @Bean + public GroupedOpenApi websocketApi() { + return GroupedOpenApi.builder() + .group("WebSocket测试环境") + .packagesToScan("com.chinaweal.youfool.devops.websocket") + .build(); + } + + /** + * 领导分配模块API分组 + */ + @Bean + public GroupedOpenApi leaderAssignApi() { + return GroupedOpenApi.builder() + .group("领导分配") + .packagesToScan("com.chinaweal.youfool.devops.leaderassign") + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/chinaweal/youfool/devops/config/SwaggerKnife4j.java b/src/main/java/com/chinaweal/youfool/devops/config/SwaggerKnife4j.java deleted file mode 100644 index ccb6a35..0000000 --- a/src/main/java/com/chinaweal/youfool/devops/config/SwaggerKnife4j.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.chinaweal.youfool.devops.config; - -import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.ParameterBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.schema.ModelRef; -import springfox.documentation.service.ApiInfo; -import springfox.documentation.service.Contact; -import springfox.documentation.service.Parameter; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author itluck - */ -@Configuration -@EnableSwagger2 -@EnableKnife4j -@ConditionalOnProperty(value = "swagger.enable", havingValue = "true") -public class SwaggerKnife4j { - @Value("${applicationName}") - private String applicationName; - @Value("${version}") - private String version; - @Value("${description}") - private String description; - @Value("${license}") - private String license; - - @Bean("orgApi") - public Docket orgApi() { - ParameterBuilder tokenPar = new ParameterBuilder(); - List headers = new ArrayList<>(); - tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); - headers.add(tokenPar.build()); - return new Docket(DocumentationType.SWAGGER_2) - .enable(true) - .apiInfo(apiInfo()) - .groupName("组织架构") - .select() - .apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.org")) - .paths(PathSelectors.any()) - .build() - .globalOperationParameters(headers); - } - - @Bean("devopsApi") - public Docket devopsApi() { - //添加head参数start - ParameterBuilder tokenPar = new ParameterBuilder(); - List headers = new ArrayList<>(); - tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); - headers.add(tokenPar.build()); - return new Docket(DocumentationType.SWAGGER_2) - .enable(true) - .apiInfo(apiInfo()) - .groupName("运维报障") - .select() - .apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.repair")) - .paths(PathSelectors.any()) - .build() - .globalOperationParameters(headers); - } - - @Bean("basisApi") - public Docket basisApi() { - //添加head参数start - ParameterBuilder tokenPar = new ParameterBuilder(); - List headers = new ArrayList<>(); - tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); - headers.add(tokenPar.build()); - return new Docket(DocumentationType.SWAGGER_2) - .enable(true) - .apiInfo(apiInfo()) - .groupName("基础环境") - .select() - .apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.base")) - .paths(PathSelectors.any()) - .build() - .globalOperationParameters(headers); - } - - @Bean("websocketApi") - public Docket websocketApi() { - //添加head参数start - ParameterBuilder tokenPar = new ParameterBuilder(); - List headers = new ArrayList<>(); - tokenPar.name("token").description("令牌").modelRef(new ModelRef("string")).parameterType("header").required(false).build(); - headers.add(tokenPar.build()); - return new Docket(DocumentationType.SWAGGER_2) - .enable(true) - .apiInfo(apiInfo()) - .groupName("WebSocket测试环境") - .select() - .apis(RequestHandlerSelectors.basePackage("com.chinaweal.youfool.devops.websocket")) - .paths(PathSelectors.any()) - .build() - .globalOperationParameters(headers); - } - - - private ApiInfo apiInfo() { - return new ApiInfoBuilder() - .title(applicationName) - .description(description) - .termsOfServiceUrl("https://www.chinaweal.com.cn") - .version(version) - .contact(new Contact("chinaweal", "https://www.chinaweal.com.cn", "")) - .license(license) - .licenseUrl("https://www.chinaweal.com.cn") - .build(); - } -} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 2183f1a..19f9d8c 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -14,6 +14,9 @@ spring: url: jdbc:postgresql://172.22.80.157:5432/devops_gd username: devops_gd password: ChinaWeal@2024 + main: + # Spring Boot 2.7+新增:允许循环依赖(临时修复,后续需重构代码消除循环依赖) + allow-circular-references: true file: devopsDir: D:\chinaweal\gitea-code\youfool-project\youfool-devops\upload @@ -32,6 +35,21 @@ applicationName: devOps swagger: enable: true + +# SpringDoc OpenAPI 配置 (替换SpringFox) +springdoc: + api-docs: + enabled: true + path: /v3/api-docs + swagger-ui: + enabled: true + path: /swagger-ui.html + operations-sorter: alpha + tags-sorter: alpha + +version: "1.0.0" +description: "DevOps运维管理系统API文档" +license: "Apache 2.0" # 错误日志配置 error-log: # 是否启用错误日志文件写入功能 diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 5489ceb..fd78042 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -32,3 +32,10 @@ dbWebhookKeys: 45d1bda2-c0b9-45c3-b640-be77f7a0726d,2eacc126-74d2-4360-a88e-369c swagger: enable: false + +# SpringDoc OpenAPI 配置 (生产环境禁用) +springdoc: + api-docs: + enabled: false + swagger-ui: + enabled: false