SpringBoot集成Knife4j接口文档

界面展示

  • knife4j界面图

引入坐标文件

SpringBoot版本

<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.6.9</version>
<relativePath/>
</parent>

knife4j版本

<!-- springboot --> 
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

<!-- knifej4 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<!--在引用时请在maven中央仓库搜索3.X最新版本号-->
<version>3.0.3</version>
</dependency>

具体代码

注意:

如果引入的SpringBoot版本大于等于2.6,需要以下操作

在application.yml中加上以下配置

spring:
mvc:
pathmatch:
# 适配 boot 2.6 路由与 springfox 兼容
matching-strategy: ANT_PATH_MATCHER

application.yml中配置文件部分

# 以下配置文件,自定义properties获取
swagger:
enable: true
title: "xxx后台"
description: "xxx后台描述"
version: "1.0.0"
pathMapping: /api
# 作者信息
contact:
name: "xxx"
email: "xxxx@qq.com"
url: "https://xxxx.com"
# 接口文档分组
groups:
- name: 1.接口文档一
basePackage: com.xxxx.controller.apiA
- name: 2.接口文档二
basePackage: com.xxxx.controller.apiB

# 必须有,以下配置文件,knife4j插件自动获取
knife4j:
enable: true
production: false
# 接口文档是否需要密码
basic:
enable: false
username: username
password: password
setting:
# 默认语言
language: zh-CN
# 是否显示Footer
enableFooter: false
# 是否开启动态参数调试功能
enableDynamicParameter: true
# 是否在每个Debug调试栏后显示刷新变量按钮
enableReloadCacheParameter: true

SwaggerPropertise.java 用于获取application.yml中swagger一栏配置文件

@Data
@Component
@ConfigurationProperties(prefix = "swagger")
public class SwaggerProperties {

private Boolean enable;
private String title;
private String description;
private String pathMapping;
private String version;
private Contact contact;
private List<Groups> groups;

@Data
@NoArgsConstructor
public static class Contact {
private String contact;
private String name;
private String email;
private String url;
private String groups;
}

@Data
@NoArgsConstructor
public static class Groups {
private String name;
private String basePackage;

}
}

SwaggerConfig.java (Knife4j是实现,Swagger是规范)

// 实现BeanFactoryPostProcessor获取beanContext上下文,用于待会手动注册bean
// TODO 实现BeanFactoryPostProcessor后@PostConstruct无法使用
@Configuration
@EnableKnife4j
public class SwaggerConfig {


@Resource
private SwaggerProperties properties;
@Resource
private OpenApiExtensionResolver openApiExtensionResolver;

// private ConfigurableListableBeanFactory beanFactory;

@Bean
public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}

private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
// removeIf方法是否执行,removeIf中接口抽象类的自定义实现
mappings.removeIf(mapping -> mapping.getPatternParser() != null);
}

private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}


@PostConstruct
public void createRestApi() {
for (SwaggerProperties.Groups group : properties.getGroups()) {
String basePackage = group.getBasePackage();
// 文档类型
Docket docket = new Docket(DocumentationType.OAS_30)
// 是否开启
.enable(properties.getEnable())
// API文档基本信息
.apiInfo(getApiInfo())
// 设置哪些接口暴露给Swagger
.select()
// 扫描指定包中的swagger注解
.apis(RequestHandlerSelectors.basePackage(basePackage))
// 扫描所有.apis()
.paths(PathSelectors.any())
.build()
.groupName(group.getName())
.extensions(openApiExtensionResolver.buildExtensions(group.getName()))
.pathMapping(properties.getPathMapping())
// TODO 设置安全模式,swagger可以设置访问token
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());

String beanName = StringUtils.substringAfterLast(basePackage, ".") + "Docket";
// 手动注入bean对象
SpringUtil.setBean(beanName, docket);
// beanFactory.autowireBean(docket);
// 设置bean的生命周期为单例
// beanFactory.registerSingleton(beanName, docket);
}
}

/**
* 安全模式,这里指定token通过Authorization头请求头传递
*/
private List<SecurityScheme> securitySchemes() {
List<SecurityScheme> apiKeyList = new ArrayList<>();
// TODO Authorization指token名称
apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
return apiKeyList;
}

/**
* 安全上下文
*/
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContexts = new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.operationSelector(o -> o.requestMappingPattern().matches("/.*"))
.build());
return securityContexts;
}

/**
* 默认的安全上引用
*/
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
List<SecurityReference> securityReferences = new ArrayList<>();
securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
return securityReferences;
}


private ApiInfo getApiInfo() {
SwaggerProperties.Contact contact = properties.getContact();
return new ApiInfoBuilder()
.contact(new Contact(contact.getName(), contact.getUrl(), contact.getEmail()))
.description(properties.getDescription())
.title(properties.getTitle())
.version(properties.getVersion())
.build();
}


// @Override
// public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// this.beanFactory = beanFactory;
// }
}

SpringUtil工具类的实现

@Component
public class SpringUtil implements BeanFactoryPostProcessor {

private static ConfigurableListableBeanFactory beanFactory;

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
SpringUtil.beanFactory = beanFactory;
}

public static ConfigurableListableBeanFactory getBeanFactory() {
return beanFactory;
}

public static <T> void setBean(String name, T t) {
beanFactory.autowireBean(t);
beanFactory.registerSingleton(name, t);
}

public static <T> T getBean(String name) {
return (T) beanFactory.getBean(name);
}

public static <T> T getBean(Class<T> clazz) {
return beanFactory.getBean(clazz);
}
}

基本注解

@Api()

用于在Controller类上描述,描述当前类的作用

tags:说明该类的作用,参数是个数组,可以填多个。
value="该参数没什么意义,在UI界面上不显示,所以不用配置"
description = "用户基本信息操作"

@ApiOperation()

用于在Controller类下方法上,描述当前方法的作用

value="方法的用途和作用"    
notes="方法的注意事项和备注"

@ApiParam()

用在方法入参上,用于描述入参的类型,是否必填等信息

name="参数名称"
value="参数的简要说明"
defaultValue="参数默认值"
required="true" 表示属性是否必填,默认为false

@ApiModel()

用在实体类上,用于描述实体类信息

description="描述实体的作用"  

@ApiModelProperty()

用在实体类属性上,描述每个属性的作用,是否必须

value="姓名"  描述参数的意义
name="name" 参数的变量名
required=true 参数是否必选