From 3b9d4ccc8283d44b9eea0a44479b4c928f644e1e Mon Sep 17 00:00:00 2001 From: maven <2163098428@qq.com> Date: 星期五, 22 八月 2025 09:22:38 +0800 Subject: [PATCH] yys 增加接口文档 --- ruoyi-admin/pom.xml | 7 + ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerProperties.java | 63 ++++++++++++ ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java | 1 ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java | 181 +++++++++++++++++++++++++++-------- ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java | 2 5 files changed, 208 insertions(+), 46 deletions(-) diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 622c28a..905a605 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -16,7 +16,12 @@ </description> <dependencies> - + <!-- ruoyi-springboot2 / swagger knife4j 閰嶇疆 --> + <dependency> + <groupId>com.github.xiaoymin</groupId> + <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> + <version>4.4.0</version> + </dependency> <!-- spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java index 9ab7c24..89f250a 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java @@ -1,64 +1,157 @@ package com.ruoyi.web.core.config; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import com.ruoyi.common.config.RuoYiConfig; 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.media.StringSchema; +import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.security.SecurityScheme.In; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.springdoc.core.customizers.OpenApiBuilderCustomizer; +import org.springdoc.core.customizers.ServerBaseUrlCustomizer; +import org.springdoc.core.models.GroupedOpenApi; +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.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.Configuration; +import org.springframework.http.HttpHeaders; /** - * Swagger2鐨勬帴鍙i厤缃� - * - * @author ruoyi + * Swagger 鑷姩閰嶇疆绫伙紝鍩轰簬 OpenAPI + Springdoc 瀹炵幇銆� + * + * 鍙嬫儏鎻愮ず锛� + * 1. Springdoc 鏂囨。鍦板潃锛�<a href="https://github.com/springdoc/springdoc-openapi">浠撳簱</a> + * 2. Swagger 瑙勮寖锛屼簬 2015 鏇村悕涓� OpenAPI 瑙勮寖锛屾湰璐ㄦ槸涓�涓笢瑗� + * */ +// @AutoConfiguration @Configuration +@ConditionalOnClass({OpenAPI.class}) +@EnableConfigurationProperties(SwaggerProperties.class) +@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 璁剧疆涓� false 鏃讹紝绂佺敤 public class SwaggerConfig { - /** 绯荤粺鍩虹閰嶇疆 */ - @Autowired - private RuoYiConfig ruoyiConfig; - - /** - * 鑷畾涔夌殑 OpenAPI 瀵硅薄 - */ + + public static final String HEADER_TENANT_ID = "tenant-id"; + + + // ========== 鍏ㄥ眬 OpenAPI 閰嶇疆 ========== + @Bean - public OpenAPI customOpenApi() - { - return new OpenAPI().components(new Components() - // 璁剧疆璁よ瘉鐨勮姹傚ご - .addSecuritySchemes("apikey", securityScheme())) - .addSecurityItem(new SecurityRequirement().addList("apikey")) - .info(getApiInfo()); + public OpenAPI createApi(SwaggerProperties properties) { + Map<String, SecurityScheme> securitySchemas = buildSecuritySchemes(); + OpenAPI openAPI = new OpenAPI() + // 鎺ュ彛淇℃伅 + .info(buildInfo(properties)) + // 鎺ュ彛瀹夊叏閰嶇疆 + .components(new Components().securitySchemes(securitySchemas)) + .addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION)); + securitySchemas.keySet().forEach(key -> openAPI.addSecurityItem(new SecurityRequirement().addList(key))); + return openAPI; } - - @Bean - public SecurityScheme securityScheme() - { - return new SecurityScheme() - .type(SecurityScheme.Type.APIKEY) - .name("Authorization") - .in(SecurityScheme.In.HEADER) - .scheme("Bearer"); - } - + /** - * 娣诲姞鎽樿淇℃伅 + * API 鎽樿淇℃伅 */ - public Info getApiInfo() - { + private Info buildInfo(SwaggerProperties properties) { return new Info() - // 璁剧疆鏍囬 - .title("鏍囬锛氳嫢渚濈鐞嗙郴缁焈鎺ュ彛鏂囨。") - // 鎻忚堪 - .description("鎻忚堪锛氱敤浜庣鐞嗛泦鍥㈡棗涓嬪叕鍙哥殑浜哄憳淇℃伅,鍏蜂綋鍖呮嫭XXX,XXX妯″潡...") - // 浣滆�呬俊鎭� - .contact(new Contact().name(ruoyiConfig.getName())) - // 鐗堟湰 - .version("鐗堟湰鍙�:" + ruoyiConfig.getVersion()); + .title(properties.getTitle()) + .description(properties.getDescription()) + .version(properties.getVersion()) + .contact(new Contact().name(properties.getAuthor()).url(properties.getUrl()).email(properties.getEmail())) + .license(new License().name(properties.getLicense()).url(properties.getLicenseUrl())); } -} + + /** + * 瀹夊叏妯″紡锛岃繖閲岄厤缃�氳繃璇锋眰澶� Authorization 浼犻�� token 鍙傛暟 + */ + private Map<String, SecurityScheme> buildSecuritySchemes() { + Map<String, SecurityScheme> securitySchemes = new HashMap<>(); + SecurityScheme securityScheme = new SecurityScheme() + .type(SecurityScheme.Type.APIKEY) // 绫诲瀷 + .name(HttpHeaders.AUTHORIZATION) // 璇锋眰澶寸殑 name + .in(SecurityScheme.In.HEADER); // token 鎵�鍦ㄤ綅缃� + securitySchemes.put(HttpHeaders.AUTHORIZATION, securityScheme); + return securitySchemes; + } + + /** + * 鑷畾涔� OpenAPI 澶勭悊鍣� + */ + @Bean + public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI, + SecurityService securityParser, + SpringDocConfigProperties springDocConfigProperties, + PropertyResolverUtils propertyResolverUtils, + Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers, + Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers, + Optional<JavadocProvider> javadocProvider) { + + return new OpenAPIService(openAPI, securityParser, springDocConfigProperties, + propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider); + } + + // ========== 鍒嗙粍 OpenAPI 閰嶇疆 ========== + + /** + * 鎵�鏈夋ā鍧楃殑 API 鍒嗙粍 + */ + @Bean + public GroupedOpenApi allGroupedOpenApi() { + return buildGroupedOpenApi("all", ""); + } + + public static GroupedOpenApi buildGroupedOpenApi(String group) { + return buildGroupedOpenApi(group, group); + } + + public static GroupedOpenApi buildGroupedOpenApi(String group, String path) { + return GroupedOpenApi.builder() + .group(group) + .pathsToMatch("/admin-api/" + path + "/**", "/app-api/" + path + "/**", "/**") + .addOperationCustomizer((operation, handlerMethod) -> operation + // .addParametersItem(buildTenantHeaderParameter()) + .addParametersItem(buildSecurityHeaderParameter())) + .build(); + } + + /** + * 鏋勫缓 Authorization 璁よ瘉璇锋眰澶村弬鏁� + * + * 瑙e喅 Knife4j <a href="https://gitee.com/xiaoym/knife4j/issues/I69QBU">Authorize 鏈敓鏁堬紝璇锋眰header閲屾湭鍖呭惈鍙傛暟</a> + * + * @return 璁よ瘉鍙傛暟 + */ + private static Parameter buildSecurityHeaderParameter() { + return new Parameter() + .name(HttpHeaders.AUTHORIZATION) // header 鍚� + .description("璁よ瘉 Token") // 鎻忚堪 + .in(String.valueOf(SecurityScheme.In.HEADER)) // 璇锋眰 header + .schema(new StringSchema()._default("Bearer test1").name(HEADER_TENANT_ID).description("璁よ瘉 Token")); // 榛樿锛氫娇鐢ㄧ敤鎴风紪鍙蜂负 1 + } + + /** + * 鏋勫缓 Tenant 绉熸埛缂栧彿璇锋眰澶村弬鏁� + * @return 澶氱鎴峰弬鏁� + */ +/* private static Parameter buildTenantHeaderParameter() { + return new Parameter() + .name(HEADER_TENANT_ID) // header 鍚� + .description("绉熸埛缂栧彿") // 鎻忚堪 + .in(String.valueOf(SecurityScheme.In.HEADER)) // 璇锋眰 header + .schema(new IntegerSchema()._default(1L).name(HEADER_TENANT_ID).description("绉熸埛缂栧彿")); // 榛樿锛氫娇鐢ㄧ鎴风紪鍙蜂负 1 + } */ +} \ No newline at end of file diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerProperties.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerProperties.java new file mode 100644 index 0000000..3cb9cbc --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerProperties.java @@ -0,0 +1,63 @@ +package com.ruoyi.web.core.config; + + +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +/** + * @author :yys + * @date : 2025/8/22 9:16 + */ + + + +/** + * Swagger 閰嶇疆灞炴��*/ +@ConfigurationProperties("aixin.swagger") +@Data +public class SwaggerProperties { + + /** + * 鏍囬 + */ + @NotEmpty(message = "鏍囬涓嶈兘涓虹┖") + private String title; + /** + * 鎻忚堪 + */ + @NotEmpty(message = "鎻忚堪涓嶈兘涓虹┖") + private String description; + /** + * 浣滆�� + */ + @NotEmpty(message = "浣滆�呬笉鑳戒负绌�") + private String author; + /** + * 鐗堟湰 + */ + @NotEmpty(message = "鐗堟湰涓嶈兘涓虹┖") + private String version; + /** + * url + */ + @NotEmpty(message = "鎵弿鐨� package 涓嶈兘涓虹┖") + private String url; + /** + * email + */ + @NotEmpty(message = "鎵弿鐨� email 涓嶈兘涓虹┖") + private String email; + + /** + * license + */ + @NotEmpty(message = "鎵弿鐨� license 涓嶈兘涓虹┖") + private String license; + + /** + * license-url + */ + @NotEmpty(message = "鎵弿鐨� license-url 涓嶈兘涓虹┖") + private String licenseUrl; + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java index 0f48b11..3900552 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java @@ -55,6 +55,7 @@ public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); // 璁剧疆璁块棶婧愬湴鍧� config.addAllowedOriginPattern("*"); // 璁剧疆璁块棶婧愯姹傚ご diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index 330039f..2bece06 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -114,7 +114,7 @@ requests.requestMatchers("/login", "/register", "/captchaImage").permitAll() // 闈欐�佽祫婧愶紝鍙尶鍚嶈闂� .requestMatchers(HttpMethod.GET, "/", "/*.html", "/**.html", "/**.css", "/**.js", "/profile/**").permitAll() - .requestMatchers("/swagger-ui.html", "/v3/api-docs/**", "/swagger-ui/**", "/druid/**").permitAll() + .requestMatchers("/swagger-ui.html", "/v3/api-docs/**", "/swagger-ui/**","/swagger-resources", "/druid/**","/swagger-resources","/webjars/**", "/favicon.ico", "/doc.html").permitAll() // 闄や笂闈㈠鐨勬墍鏈夎姹傚叏閮ㄩ渶瑕侀壌鏉冭璇� .anyRequest().authenticated(); }) -- Gitblit v1.9.3