因项目中的接口越来越多,使用swagger调试接口的时候,因接口太杂太乱,不太容易找到想要调试的接口,所以研究了一下swagger分组的方法
但是分组是需要配置多个Docket的bean,而一般配置,就是一个docket一个函数定义并加上@Bean注解,代码冗余太多,所以就想着用灵活的方式去配置swagger分组。
@Configuration
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(documentationType.OAS_30)
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描指定包
.apis(RequestHandlerSelectors.basePackage("com.xxx.xxx"))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping(pathMapping)
.groupName("全部");
}
private ApiInfo apiInfo() {
// 用ApiInfoBuilder进行定制
return new ApiInfoBuilder()
// 设置标题
.title("标题:xxx系统_接口文档")
// 描述
.description("描述:用于管理xxxxx信息,具体包括XXX,XXX模块...")
// 作者信息
.contact(new Contact("xxxx", null, null))
// 版本
.version("版本号:" + "1.0")
.build();
}
}
就像普通的swagger配置,一个docket包含所有接口, 而这样的话,swagger文档看起来就非常的杂乱,所以分组是个不错的选择
但是一般的分组是多个Docket去配置,比如:
@Bean
public Docket createRestApi1() {
return new Docket(documentationType.OAS_30)
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描指定包
.apis(RequestHandlerSelectors.basePackage("com.xxx.xxx"))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping(pathMapping)
.groupName("分组1");
}
@Bean
public Docket createRestApi2() {
return new Docket(documentationType.OAS_30)
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描指定包
.apis(RequestHandlerSelectors.basePackage("com.xxx.xxx"))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
.pathMapping(pathMapping)
.groupName("分组2");
}
...
一个分组就要复制一个docker定义,如果分组比较多的话,冗余代码太多,而且看起来也不是很美观,所以我才在想如果灵活配置的方式
分析简化方案首先我想的就是,这里面重复代码这么多,能不能将这些重复代码去掉。
所以我想出了一个简单的方案,就是将不同的定义信息封装成一个定义信息集,而通过循环的方式将不同的信息当作变量放入。
于是我想到了这样一个方式,通过循环定义信息集,动态的去创建Docket并注册到Bean工厂中,但是这样的话,就需要操作spring Bean工厂,于是我又写了一个工具类,去操作spring bean工厂,然后通过这种方式实现了这个想法
实现简化方案swagger的分组我是通过扫描不同的包来分的组,但是也可以使用url去区分
@Bean
public Docket createRestApi1() {
return new Docket(documentationType.OAS_30)
// 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 扫描所有
.apis(RequestHandlerSelectors.any())
// 扫描指定url
.paths(PathSelectors.ant("/xxx
GROUP1("分组1", "com.xxx.xxx.xxxx0"),
GROUP2("分组2", "com.xxx.xxx.xxxx1")
;
SwaggerEntity(String groupName, String... basePackages) {
this.groupName = groupName;
this.basePackages = basePackages;
}
private final String groupName;
private final String[] basePackages;
public String getGroupName() {
return groupName;
}
public String[] getbasePackages() {
return basePackages;
}
}
basePackages为何定义为数据类型是因为一个Docket可能要扫描多个包,如不需要,则改为String类型就可
下面就开始最关键的注入代码, 因需要项目启动就注入进去,所以使用@PostConstruct来使服务启动完就执行
@PostConstruct
public void importDocketGroup() {
// 循环SwaggerEntity中的所有定义
for (SwaggerEntity value : SwaggerEntity.values()) {
// 注册bean
Docket docket = SpringUtils.registerBean(null, Docket.class, Lists.newArrayList(documentationType.OAS_30), null);
// 执行docket的一些定义
docket // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
.apiInfo(apiInfo())
// 设置哪些接口暴露给Swagger展示
.select()
// 设置SwaggerEntity中定义的需要扫描的包
.apis(RequestHandlerSelectors.basePackage(value.getbasePackages()))
// 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build()
// 设置分组名
.groupName(value.getGroupName());
}
}
关于SpringUtils工具类请移步 spring bean工具类
上述定义的是一个docket扫描单个包的情况,如需扫描多个包的情况请移步 swagger多包扫描



