knife4j
1.介绍
knife4j 集成 微服务模板工程 pom 可直接使用 高内聚低耦合
2.项目结构
framework-knife4J
└─src
└─main
├─java
│ └─com
│ └─yan
│ ├─abstractinterface
│ │ └─swagger
│ ├─config
│ ├─constants
│ └─scan
└─resources
3.pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yan</groupId>
<artifactId>framework-knife4j</artifactId>
<version>${project-module.version}</version>
<properties>
<java.version>8</java.version>
<project-module.version>0.0.1-SNAPSHOT</project-module.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<!--swagger 版本-->
<knife4j.version>4.1.0</knife4j.version>
<springdoc-openapi-ui.version>1.6.15</springdoc-openapi-ui.version>
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
<spring-core.version>5.3.27</spring-core.version>
</properties>
<!-- 网关引用需要排除
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</exclusion>
</exclusions>
-->
<dependencyManagement>
<dependencies>
<!--swagger-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>${springdoc-openapi-ui.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax.annotation-api.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring-core.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--适用于springboot3版本替换依赖-->
<!--
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-common</artifactId>
<version>1.6.9</version>
<scope>compile</scope>
</dependency>
-->
<!--swagger-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
4.com.yan.constants
4.1 SwaggerConstants
package com.yan.constants;
/**
* @author yan
* @date 2023/9/30 5:30
*/
public class SwaggerConstants {
public static final String swaggerScanPackage = "com.yan.config";
public static final String authorization = "${api.authorization:Authorization}";
public static final String version = "${api.common.version:1.0.0}";
public static final String title = "${api.common.title:标题}";
public static final String description = "${api.common.description:说明}";
public static final String termsOfService = "${api.common.termsOfService:}";
public static final String license = "${api.common.license:}";
public static final String licenseUrl = "${api.common.licenseUrl:}";
public static final String externalDocDesc = "${api.common.externalDocDesc:}";
public static final String externalDocUrl = "${api.common.externalDocUrl:}";
public static final String contactName = "${api.common.contact.name:}";
public static final String contactUrl = "${api.common.contact.url:}";
public static final String contactEmail = "${api.common.contact.email:}";
public static final String serverServletContextPath = "${server.servlet.context-path:}";
}
4.2 GroupExpressionConstants
package com.yan.constants;
/**
* @Author yan
* @Date 2024/11/12 上午12:40:02
* @Description
*/
public class GroupExpressionConstants {
public static final String defaultGroupEnableExpression = "${springdoc.open.default-group-configs.enable:false}";
public static final String defaultApiGroupExpression = "${springdoc.open.default-group-configs.api:true}";
public static final String defaultJwtGroupExpression = "${springdoc.open.default-group-configs.jwt:true}";
public static final String defaultOtherGroupExpression = "${springdoc.open.default-group-configs.other:true}";
}
5.com.yan.abstractinterface.swagger
5.1 AbstractSwagger
package com.yan.abstractinterface.swagger;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
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.media.Schema;
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 lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpHeaders;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @Author yan
* @Date 2024/7/26 0026 11:47:39
* @Description
*/
public interface AbstractSwagger {
String authorization = HttpHeaders.AUTHORIZATION;
String apiGroupName = "api";
String jwtGroupName = "jwt";
String otherGroupName = "other";
String GroupSuffix = "_Group";
default <T> T defaultIfEmpty(T object, T defaultValue) {
return ObjectUtil.isEmpty(object) ? defaultValue : object;
}
default <T> T defaultIfEmpty(T object) {
return defaultIfEmpty(object, null);
}
default List<String> getPrefixByAuthorization() {
Environment env = SpringUtil.getBean(Environment.class);
String property = env.getProperty("authorization.prefix");
List<String> list = CollUtil.newArrayList("/jwt/", "/test/");
if (StrUtil.isNotBlank(property)) {
list = Arrays.stream(property.split(",")).map(o -> {
String str = "/";
String strEnd = "**";
if (!o.startsWith(str)) {
o = new StringBuffer(str).append(o).toString();
}
if (o.contains(strEnd)) {
o = o.replace(strEnd, "");
}
if (!o.endsWith(str)) {
o = new StringBuffer(o).append(str).toString();
}
return o;
}).collect(Collectors.toList());
}
return list;
}
default String getAuthorization() {
return authorization;
}
/**
* 安全模式,这里配置通过请求头 Authorization 传递 token 参数
*/
default Map<String, SecurityScheme> buildSecuritySchemes() {
String authorization = getAuthorization();
Map<String, SecurityScheme> securitySchemes = new HashMap<>();
SecurityScheme securityScheme = new SecurityScheme()
.type(SecurityScheme.Type.APIKEY) // 类型
.name(authorization) // 请求头的 name
.in(SecurityScheme.In.HEADER); // token 所在位置
securitySchemes.put(authorization, securityScheme);
return securitySchemes;
}
/*####################################################################################################################################################################################################################################################*/
/**
* 配置api组
* 注意请和yaml中配置的组名不要重复(俩者配置同时生效)
*
* @return
*/
//@Lazy//懒加载
default GroupedOpenApi buildApiGroupedOpenApi() {
String path = new StringBuilder().append("/api/**").toString();
List<String> paths = CollUtil.newArrayList(path);
SwaggerParameter sign = new SwaggerParameter()
.setName("sign").setDescription("签名")
.setStringSchemaDefault("签名sign")
.setRequired(true);
SwaggerParameter timestamp = new SwaggerParameter()
.setName("timestamp").setDescription("时间戳")
.setStringSchemaDefault(String.valueOf(System.currentTimeMillis()+ 3000))
.setRequired(true);
List<SwaggerParameter> swaggerParameters = CollUtil.newArrayList(sign, timestamp);
//加入全局
List<Parameter> parameterList = swaggerParameters.stream().filter(ObjectUtil::isNotEmpty)
.map(this::buildHeaderParameter).collect(Collectors.toList());
//Parameter signParameter = buildHeaderParameter("sign", "验签",
// null, "验签1"
// , null, null).required(true);
//
//Parameter timestampParameter = buildHeaderParameter("timestamp", "时间戳",
// null, System.currentTimeMillis() + 3000 + ""
// , null, "时间戳1").required(true);
//
////加入全局
//List<Parameter> parameterList = CollUtil.newArrayList(signParameter, timestampParameter);
GroupSwagger groupSwagger = new GroupSwagger()
.setGroupName(apiGroupName)
.setPaths(paths)
.setParameterList(parameterList);
GroupedOpenApi groupedOpenApi = buildGroupedOpenApi(groupSwagger);
return groupedOpenApi;
}
/**
* 配置jwt组
* 注意请和yaml中配置的组名不要重复(俩者配置同时生效)
*
* @return
*/
//@Lazy//懒加载
default GroupedOpenApi buildJwtGroupedOpenApi() {
String path = new StringBuilder().append("/jwt/**").toString();
List<String> paths = CollUtil.newArrayList(path);
List<Parameter> parameterList = CollUtil.newArrayList(buildSecurityHeaderParameter(getAuthorization()));
GroupSwagger groupSwagger = new GroupSwagger()
.setGroupName(jwtGroupName)
.setPaths(paths)
.setParameterList(parameterList);
GroupedOpenApi groupedOpenApi = buildGroupedOpenApi(groupSwagger);
return groupedOpenApi;
}
/**
* 配置other组
* 注意请和yaml中配置的组名不要重复(俩者配置同时生效)
*
* @return
*/
//@Lazy//懒加载
default GroupedOpenApi buildOtherGroupedOpenApi() {
//无需验证,无组必传参数
String apiPath = new StringBuilder().append("/api/**").toString();
String jwtPath = new StringBuilder().append("/jwt/**").toString();
List<String> excludePaths = CollUtil.newArrayList(apiPath, jwtPath);
GroupSwagger groupSwagger = new GroupSwagger()
.setGroupName(otherGroupName)
.setExcludePaths(excludePaths);
GroupedOpenApi groupedOpenApi = buildGroupedOpenApi(groupSwagger);
return groupedOpenApi;
}
@Data @Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
class GroupSwagger {
/**
* 组名
*/
String groupName;
/**
* 路径
*/
List<String> paths;
/**
* 排除路径
*/
List<String> excludePaths;
/**
* 参数
*/
List<Parameter> parameterList;
}
default GroupedOpenApi buildGroupedOpenApi(@Valid @NotNull GroupSwagger groupSwagger){
String groupName = groupSwagger.getGroupName();
List<String> paths = groupSwagger.getPaths();
List<String> excludePaths = groupSwagger.getExcludePaths();
List<Parameter> parameterList = groupSwagger.getParameterList();
return buildGroupedOpenApi(groupName, paths, excludePaths, parameterList);
}
/**
* 配置 ,组|指定路径|全局 --必传参数
*
* @param groupName 该组名
* @param paths 该组路径
* @param excludePaths 该组排除路径
* @param parameterList 该组参数
* @return
*/
default GroupedOpenApi buildGroupedOpenApi(String groupName, List<String> paths, List<String> excludePaths, List<Parameter> parameterList) {
GroupedOpenApi.Builder builder = GroupedOpenApi.builder();
if (StrUtil.isNotBlank(groupName)) {
//加组配置
builder.group(groupName);
}
if (CollUtil.isNotEmpty(paths)) {
//组路径
String[] pathsToMatch = paths.toArray(new String[paths.size()]);
builder.pathsToMatch(pathsToMatch);
}
if (CollUtil.isNotEmpty(excludePaths)) {
//组排除路径
String[] pathsToExclude = excludePaths.toArray(new String[excludePaths.size()]);
builder.pathsToExclude(pathsToExclude);
}
if (CollUtil.isNotEmpty(parameterList)) {
builder.addOperationCustomizer(
//加全局变量
(operation, handlerMethod) -> {
Operation reOperation = new Operation();
for (Parameter parameter : parameterList) {
// parameter.setRequired(true);
//再原有方法参数基础上添加全局参数
reOperation = operation.addParametersItem(parameter);
}
//该方法会覆盖原有参数
//Operation parameters = operation.parameters(parameterList);
return reOperation;
}
);
}
return builder.build();
}
/*####################################################################################################################################################################################################################################################*/
/**
* 构建 Authorization 认证请求头参数
* <p>
* 解决 Knife4j <a href="https://gitee.com/xiaoym/knife4j/issues/I69QBU">Authorize 未生效,请求header里未包含参数</a>
*
* @return 认证参数
*/
default Parameter buildSecurityHeaderParameter(String authorization) {
//String authorization = getAuthorization();
Parameter parameter = new Parameter()
.name(authorization) // header 名
.description("认证 Token")// 描述
.in(String.valueOf(SecurityScheme.In.HEADER))// 请求 header
.schema(new StringSchema()
// ._default("Bearer ") // 最好关闭
.name(authorization).description("认证 Token"))//
.required(true);
return parameter;
}
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
class SwaggerParameter {
/**
* 名称
*/
String name = "SwaggerParameter名称";
/**
* 描述
*/
String description = "SwaggerParameter描述";
/**
* 请求参数位置
*/
SecurityScheme.In securitySchemeIn = SecurityScheme.In.HEADER;
/**
* schema默认值
*/
String stringSchemaDefault = null;
String schemaName = "schemaName";
/**
* schema描述
*/
String schemaDescription = "schema描述";
/**
* 是否必须
*/
Boolean required = false;
}
default Parameter buildHeaderParameter(@Valid @NotNull SwaggerParameter swaggerParameter) {
String name = swaggerParameter.getName();
String description = swaggerParameter.getDescription();
SecurityScheme.In securitySchemeIn = swaggerParameter.getSecuritySchemeIn();
String stringSchemaDefault = swaggerParameter.getStringSchemaDefault();
String schemaName = swaggerParameter.getSchemaName();
String schemaDescription = swaggerParameter.getSchemaDescription();
Boolean required = swaggerParameter.getRequired();
return buildHeaderParameter(name, description, String.valueOf(securitySchemeIn), stringSchemaDefault, schemaName, schemaDescription)
.required(required);
}
/**
* 自定义参数
*
* @param parameterName 名称
* @param parameterDescription 描述
* @param parameterIn 请求参数位置
* @param schemaDefault 默认值
* @param schemaName
* @param schemaDescription schema描述
* @return
*/
default Parameter buildHeaderParameter(@NotNull String parameterName,
@NotNull String parameterDescription,
String parameterIn,
String schemaDefault,
String schemaName,
String schemaDescription) {
// header 名
parameterName = defaultIfEmpty(parameterName, "header&" + System.currentTimeMillis());
// 描述
parameterDescription = defaultIfEmpty(parameterDescription, "认证 Token");
// 请求 header
parameterIn = defaultIfEmpty(parameterIn, String.valueOf(SecurityScheme.In.HEADER));
schemaDefault = defaultIfEmpty(schemaDefault, "StringSchema");
schemaDescription = defaultIfEmpty(schemaDescription, "schemaDescription");
StringSchema stringSchema = new StringSchema()
._default(schemaDefault);
Schema schema = stringSchema.name(schemaName)
.description(schemaDescription);
Parameter parameter = new Parameter()
.name(parameterName)
.description(parameterDescription)
.in(parameterIn)
.schema(schema);// 默认:使用用户编号为 1
return parameter;
}
default OpenAPI buildOpenAPI() {
String authorization = getAuthorization();
OpenAPI api = new OpenAPI()
.addSecurityItem(new SecurityRequirement().addList(authorization))
.components(new Components()
.addSecuritySchemes(authorization, new SecurityScheme().name(authorization)
.type(SecurityScheme.Type.HTTP)
.scheme("Bearer ")
.in(SecurityScheme.In.HEADER)
.description("鉴权token")));
return api;
}
default GlobalOpenApiCustomizer buildGlobalOpenApiCustomizer() {
//Logger log = LoggerFactory.getLogger(getClass());
//log.info("start");
return openApi -> {
if (ObjectUtil.isNotEmpty(openApi)) {
openApi.getPaths().forEach((path, pathItem) -> {
boolean pathBool = false;
//log.info("path:{};pathItem:{};", path, pathItem);
List<String> list = getPrefixByAuthorization();
if (CollUtil.isEmpty(list)) {
pathBool = true;
} else {
for (String prefix : list) {
if (path.startsWith(prefix)) {
pathBool = true;
break;
}
}
}
if (pathBool) {
pathItem.readOperations().forEach(operation ->
operation.addSecurityItem(new SecurityRequirement().addList(HttpHeaders.AUTHORIZATION))
);
}
});
}
};
}
default GlobalOpenApiCustomizer buildOpenApiCustomizer() {
GlobalOpenApiCustomizer customizer = buildGlobalOpenApiCustomizer();
return customizer;
}
}
6.com.yan.config
6.1 SwaggerConfiguration
package com.yan.config;
import com.yan.constants.SwaggerConstants;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
/**
* @Author yan
* @Date 2024/5/27 0027 13:19
* @Description
*/
@Configuration
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Slf4j
public class SwaggerConfiguration {
@Value(SwaggerConstants.authorization)
private String authorization;
@Value(SwaggerConstants.version)
private String version;
@Value(SwaggerConstants.title)
private String title;
@Value(SwaggerConstants.description)
private String description;
@Value(SwaggerConstants.termsOfService)
private String termsOfService;
@Value(SwaggerConstants.license)
private String license;
@Value(SwaggerConstants.licenseUrl)
private String licenseUrl;
@Value(SwaggerConstants.externalDocDesc)
private String externalDocDesc;
@Value(SwaggerConstants.externalDocUrl)
private String externalDocUrl;
@Value(SwaggerConstants.contactName)
private String contactName;
@Value(SwaggerConstants.contactUrl)
private String contactUrl;
@Value(SwaggerConstants.contactEmail)
private String contactEmail;
@Value(SwaggerConstants.serverServletContextPath)
private String serverServletContextPath;
}
6.2 SwaggerConfig
package com.yan.config;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.github.xiaoymin.knife4j.core.util.StrUtil;
import com.yan.abstractinterface.swagger.AbstractSwagger;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
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.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import javax.annotation.Resource;
import java.util.*;
/**
* @author yan
* @date 2023/9/30 4:24
*/
@Data
@NoArgsConstructor
@Configuration
@Slf4j
public class SwaggerConfig implements AbstractSwagger {
@Lazy
@Resource
private SwaggerConfiguration config;
@Override
public String getAuthorization() {
String result = config.getAuthorization();
return result;
}
// @Bean
public OpenAPI getOpenApiDocumentation() {
ExternalDocumentation externalDocs = new ExternalDocumentation()
.description(defaultIfEmpty(config.getExternalDocDesc()))
.description(defaultIfEmpty(config.getExternalDocUrl()));
Contact contact = new Contact()
.name(defaultIfEmpty(config.getContactName()))
.url(defaultIfEmpty(config.getContactUrl()))
.email(defaultIfEmpty(config.getContactEmail()));
License license = new License()
.name(defaultIfEmpty(config.getLicense()))
.url(defaultIfEmpty(config.getLicenseUrl()));
Info info = new Info()
.title(defaultIfEmpty(config.getTitle()))
.description(defaultIfEmpty(config.getDescription()))
.version(defaultIfEmpty(config.getVersion()))
.contact(contact)
.termsOfService(defaultIfEmpty(config.getTermsOfService()))
.license(license);
/**
* 全局参数
*/
// 设置 spring security jwt accessToken 认证的请求头 Authorization: Bearer xxx.xxx.xxx
String authorization = getAuthorization();
/*System.err.println(authorization);*/
Map<String, SecurityScheme> securitySchemas = buildSecuritySchemes();
Components components = new Components()
.securitySchemes(securitySchemas);
SecurityRequirement securityRequirement = new SecurityRequirement();
securityRequirement.addList(authorization);
OpenAPI openApi = new OpenAPI()
.info(info)
.components(components)
.addSecurityItem(securityRequirement)
.externalDocs(externalDocs);
securitySchemas.keySet().forEach(key -> openApi.addSecurityItem(new SecurityRequirement().addList(key)));
return openApi;
}
/**
* 配置api组
* 注意请和yaml中配置的组名不要重复(俩者配置同时生效)
*
* @return
*/
//@Lazy//懒加载
public static GroupedOpenApi beanBuildApiGroupedOpenApi() {
return SpringUtil.getBean(SwaggerConfig.class).buildApiGroupedOpenApi();
}
/**
* 配置jwt组
* 注意请和yaml中配置的组名不要重复(俩者配置同时生效)
*
* @return
*/
//@Lazy//懒加载
public static GroupedOpenApi beanBuildJwtGroupedOpenApi() {
return SpringUtil.getBean(SwaggerConfig.class).buildJwtGroupedOpenApi();
}
/**
* 配置other组
* 注意请和yaml中配置的组名不要重复(俩者配置同时生效)
*
* @return
*/
//@Lazy//懒加载
public static GroupedOpenApi beanBuildOtherGroupedOpenApi() {
return SpringUtil.getBean(SwaggerConfig.class).buildOtherGroupedOpenApi();
}
@Bean
public OpenAPI openAPI() {
return buildOpenAPI();
}
@Bean
public GlobalOpenApiCustomizer globalOpenApiCustomizer() {
return buildOpenApiCustomizer();
}
}
6.3 GroupedOpenApiBeanList
package com.yan.config;
import com.yan.constants.GroupExpressionConstants;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author yan
* @Date 2024/10/20 下午11:34:00
* @Description
*/
@Slf4j
@Configuration
//@ConditionalOnExpression("${springdoc.open.default-group-configs.enable:false}")
@ConditionalOnExpression(GroupExpressionConstants.defaultGroupEnableExpression)
public class GroupedOpenApiBeanList {
@Bean
@ConditionalOnExpression(GroupExpressionConstants.defaultApiGroupExpression)
public GroupedOpenApi api(){
log.info("GroupedOpenApi {} init...","api");
return SwaggerConfig.beanBuildApiGroupedOpenApi();
}
@Bean
@ConditionalOnExpression(GroupExpressionConstants.defaultJwtGroupExpression)
public GroupedOpenApi jwt(){
log.info("GroupedOpenApi {} init...","jwt");
return SwaggerConfig.beanBuildJwtGroupedOpenApi();
}
@Bean
@ConditionalOnExpression(GroupExpressionConstants.defaultOtherGroupExpression)
public GroupedOpenApi other(){
log.info("GroupedOpenApi {} init...","other");
return SwaggerConfig.beanBuildOtherGroupedOpenApi();
}
}
7. com.yan.scan
7.1 SwaggerScan
package com.yan.scan;
import com.yan.constants.SwaggerConstants;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
/**
* @author yan
* @date 2023/9/30 5:30
*/
@ComponentScan(basePackages = {SwaggerConstants.swaggerScanPackage}
, basePackageClasses = {RestController.class}
)
@Configuration
public class SwaggerScan {
}
8.yml
## 自定义open API公共描述信息
#api:
# authorization: token
# common:
# version: 3.0.0
# title: SecuityAPI
# description: SecuityAPI
# termsOfService:
# license: 未经许可不得转载
# licenseUrl: xxx.license.com
# externalDocDesc:
# externalDocUrl:
# contact:
# name: kirito-asuna
# url:
# email:
#
#springdoc:
# api-docs:
# path: /v3/api-docs
## 请注意使用group名时如果配置了GroupedOpenApi引用自动配置时组名不能重复
# open:
# default-group-configs: true
# group-configs:
# - group: "api"
# paths-to-match: "/api/**"
# - group: "jwt"
# paths-to-match: "/jwt/**"
# - group: "other"
# paths-to-exclude:
# - "/swagger-resources/**"
# - "/v2/api-docs"
# - "/v3/api-docs"
# - "/api/**"
# - "/jwt/**"
# swagger-ui:
# operations-sorter: alpha
# path: /swagger-ui.html
# tags-sorter: alpha
# Authorization 在knife4j中失效==>替代方案 使用knife4j中全局参数设置Authorization
#knife4j:
# cors: true
# enable: true
# setting:
# enable-dynamic-parameter: true
# #swagger
# basic:
# # enable: true
# username: root
# password: root
#cors: true - 开启跨域资源共享(CORS),允许不同域名的请求访问。
#enable: true - 启用knife4j。
#setting: enable-dynamic-parameter: true - 开启动态参数功能,允许在运行时动态修改API接口参数。
#basic: enable: true - 开启基本认证,使用用户名和密码进行认证。
#username: root - 用户名为root。
#password: root - 密码为root。
9.依赖
<!--swagger-->
<dependency>
<groupId>com.yan</groupId>
<artifactId>framework-knife4j</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>