From e9bfa1396ff47d171b3052a606e0931e6f93cc9c Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期四, 10 四月 2025 12:05:23 +0800 Subject: [PATCH] 还原framework代码 --- iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 157 insertions(+), 0 deletions(-) diff --git a/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java new file mode 100644 index 0000000..331e7f0 --- /dev/null +++ b/iailab-framework/iailab-common-web/src/main/java/com/iailab/framework/swagger/config/IailabSwaggerAutoConfiguration.java @@ -0,0 +1,157 @@ +package com.iailab.framework.swagger.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.media.IntegerSchema; +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 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.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.Primary; +import org.springframework.http.HttpHeaders; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.iailab.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; + +/** + * Swagger 自动配置类,基于 OpenAPI + Springdoc 实现。 + * + * 友情提示: + * 1. Springdoc 文档地址:<a href="https://github.com/springdoc/springdoc-openapi">仓库</a> + * 2. Swagger 规范,于 2015 更名为 OpenAPI 规范,本质是一个东西 + * + * @author iailab + */ +@AutoConfiguration +@ConditionalOnClass({OpenAPI.class}) +@EnableConfigurationProperties(SwaggerProperties.class) +@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true) // 设置为 false 时,禁用 +public class IailabSwaggerAutoConfiguration { + + // ========== 全局 OpenAPI 配置 ========== + + @Bean + 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; + } + + /** + * API 摘要信息 + */ + private Info buildInfo(SwaggerProperties properties) { + return new Info() + .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 + @Primary // 目的:以我们创建的 OpenAPIService 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(); + } + + /** + * 构建 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 + } + + /** + * 构建 Authorization 认证请求头参数 + * + * 解决 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 + } + +} + -- Gitblit v1.9.3