上一篇提到了SpringBoot整合Swagger2,但现在微服务盛行,一个项目可能就要搭建许多微服务,于是就想着将swagger2放到公共模块中,到时候直接把包引入就能用。基本上和上一篇一样,只不过就是把 swagger2的开关 和 描述提取到了配置文件中,使得引入公共模块的项目能在application.yml中控制swagger。
1. 需要了解的一些知识
- Springboot整合Swagger2 - (jianshu.com)
- SpringBoot条件装配
- SpringBoot配置文件中的数据格式
- SpringBoot读取和使用配置文件中的数据
2. 1. 导包
io.springfox
springfox-swagger2
2.9.2
io.swagger
swagger-annotations
io.swagger
swagger-models
io.springfox
springfox-swagger-ui
2.9.2
io.swagger
swagger-annotations
1.5.21
io.swagger
swagger-models
1.5.21
3. 配置
-
- 添加swagger属性文件,以后在项目的application.yml文件中配置
@ConfigurationProperties(prefix = "swagger", ignoreUnknownFields = true) @Data public class SwaggerProperties { /** * 是否开启swagger,生产环境一般关闭,所以这里定义一个变量 */ private Boolean enable; /** * 文档标题 */ private String title; /** * 描述 */ private String description; /** * 版本号 */ private String version; /** * api扫描包路径 */ private String[] basePackage; /** * 是否开启head参数 */ private Boolean headEnable = false; /** * head参数 */ private List
headParams; } -
- 一个小类
@Data public class HeadParam { private String param; private Boolean required = false; }
-
- swagger配置文件
import java.util.ArrayList; import java.util.List; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 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 com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import springfox.documentation.RequestHandler; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Parameter; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * @ConditionalOnClass({Docket.class, ApiInfoBuilder.class}) 当存在Docket和ApiInfoBuilder类的时候才加 载Bean; * @ConditionalOnMissingClass 不存在某个类的时候才会实例化Bean; * @ConditionalOnProperty(prefix = "swagger", value = "enable", matchIfMissing = true) * 当存在swagger为前缀的属性,才会实例化Bean; * @ConditionalOnMissingBean 当不存在某个Bean的时候才会实例化; */ @Configuration @EnableSwagger2 @ConditionalOnClass({Docket.class, ApiInfoBuilder.class}) @ConditionalOnProperty(prefix = "swagger", value = "enable", matchIfMissing = true) @EnableConfigurationProperties(SwaggerProperties.class) public class SwaggerConfig { // 定义分隔符,配置Swagger多包 private static final String splitor = ";"; @Bean @ConditionalOnMissingBean public SwaggerProperties swaggerProperties() { return new SwaggerProperties(); } @Bean public Docket api() { SwaggerProperties properties = swaggerProperties(); // header参数设置 List
headParams = new ArrayList<>(); List hpList = properties.getHeadParams(); if (properties.getHeadEnable() == true && hpList.size() > 0) { for (HeadParam hp : hpList) { ParameterBuilder pb = new ParameterBuilder(); headParams.add( pb.name(hp.getParam()) .modelRef(new ModelRef("string")) .parameterType("header") .required(hp.getRequired()) .build()); } } // 扫描的包路径 String[] basePackageList = properties.getBasePackage(); String basePackage = "xyz.2020555"; if (basePackageList != null && basePackageList.length > 0) { basePackage += ";" + ArrayUtil.join(basePackageList, ";"); } return new Docket(DocumentationType.SWAGGER_2) // 开关 .enable(properties.getEnable() == null?false:properties.getEnable()) .select() // 指定扫描1个包 // .apis(RequestHandlerSelectors.basePackage("com.test.controller")) // 扫描多包 .apis(scanBasePackage(basePackage)) // 只有标记了@Api的类方法才会暴露出给swagger .apis(RequestHandlerSelectors.withClassAnnotation(Api.class)) // 只有标记了@ApiOperation的方法才会暴露出给swagger .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) // 匹配路径 .paths(PathSelectors.any()) .build() .globalOperationParameters(headParams) .apiInfo(apiInfo(properties)); } private ApiInfo apiInfo(SwaggerProperties properties) { return new ApiInfoBuilder() .title(properties.getTitle()) .description(properties.getDescription()) .version(properties.getVersion()) .build(); } /** * 切割扫描的包生成Predicate */ public static Predicate scanBasePackage(final String basePackage) { if (StrUtil.isBlank(basePackage)) { throw new NullPointerException("basePackage不能为空,多个包扫描使用" + splitor + "分隔"); } String[] controllerPack = basePackage.split(splitor); Predicate predicate = null; for (int i = controllerPack.length - 1; i >= 0; i--) { String strBasePackage = controllerPack[i]; if (StrUtil.isNotBlank(strBasePackage)) { Predicate tempPredicate = (Predicate ) RequestHandlerSelectors .basePackage(strBasePackage); predicate = predicate == null ? tempPredicate : Predicates.or(tempPredicate, predicate); } } if (predicate == null) { throw new NullPointerException("basePackage配置不正确,多个包扫描使用" + splitor + "分隔"); } return predicate; } }
至此,公共模块中swagger配置这样的:
因为要在yml文件中配置swagger,所以在公共模块
META-INF
中加一些元数据:additional-spring-configuration-metadata.json
,非必须的,我用的eclipse,不想看见黄色感叹号,还能有提示
{"properties": [
{
"name": "swagger.enable",
"type": "java.lang.Boolean",
"description": "是否开启swagger'"
},
{
"name": "swagger.title",
"type": "java.lang.String",
"description": "文档标题'"
},
{
"name": "swagger.version",
"type": "java.lang.String",
"description": "版本号'"
},
{
"name": "swagger.description",
"type": "java.lang.String",
"description": "描述'"
},
{
"name": "swagger.head-enable",
"type": "java.lang.Boolean",
"description": "是否开启head参数'"
},
{
"name": "swagger.head-params",
"type": "java.util.List",
"description": "head参数'"
},
{
"name": "swagger.base-package",
"type": "java.util.List",
"description": "api扫描包路径"
}
]}
我放到这了:
配置,到这就完成了。
4. 使用
使用时,在其他微服务中导入公共模块的jar包,然后在yml文件中配置。
# 5.swagger
swagger:
enable: true
title: ${spring.application.name}
version: 1.0
base-package:
- com.test.controller
description: 访问地址:http://192.168.50.30:${server.port}${server.servlet.context-path}
head-enable: true
head-params:
- param: token1
required: true
- param: token2
required: false
自己封装自己用,可以自嗨了。。。。。。。