这篇文章中我们来深入学习一下Spring Boot中swagger3 的其他高级用法。在日常的开发中,为了减少工作量,我们会遇到一种情况,就是将前端的接口与后端的接口编写到同一个代码中,这样也提高了代码的复用率,减少了重复开发代码的工作量。这个时候我们就需要将接口文档也进行拆分。分为前端接口和后端接口两个部分。
在Swagger3.0中如何进行接口分组呢?
Swagger3.0 接口分组操作
通过之前的例子我们知道,我们往容器中注入一个Docket就是注入了一个文档,其中我们设置了groupName的分组名称。要想注入多个文档,意思就是需要往容器中注入多个Docket。既然是这样,我们就需要修改之前的Swagger的配置文件,将其改为如下的代码。
@EnableOpenApi
@Configuration
@EnableConfigurationProperties(value = {SwaggerProperties.class})
public class Swagger3Config {
@Autowired
private SwaggerProperties swaggerProperties;
@Bean
public Docket frontApi(){
return new Docket(DocumentationType.OAS_30)
// 是否开启,根据环境配置
.enable(swaggerProperties.getFront().getEnable())
.groupName(swaggerProperties.getFront().getGroupName())
.apiInfo(frontApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getFront().getBasePackege()))
.paths(PathSelectors.any())
.build();
}
// 前台API信息
private ApiInfo frontApiInfo(){
return new ApiInfoBuilder()
.title(swaggerProperties.getFront().getTitle())
.description(swaggerProperties.getFront().getDescription())
.version(swaggerProperties.getFront().getVersion())
.contact(
// 添加开发者信息
new Contact(
swaggerProperties.getFront().getContactName(),
swaggerProperties.getFront().getContactUrl(),
swaggerProperties.getFront().getContactEmail())
).build();
}
@Bean
public Docket backApi(){
return new Docket(DocumentationType.OAS_30)
// 是否开启,根据环境配置
.enable(swaggerProperties.getBack().getEnable())
.groupName(swaggerProperties.getBack().getGroupName())
.apiInfo(backApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBack().getBasePackege()))
.paths(PathSelectors.any())
.build();
}
// 前台API信息
private ApiInfo backApiInfo(){
return new ApiInfoBuilder()
.title(swaggerProperties.getBack().getTitle())
.description(swaggerProperties.getBack().getDescription())
.version(swaggerProperties.getBack().getVersion())
.contact(
// 添加开发者信息
new Contact(
swaggerProperties.getBack().getContactName(),
swaggerProperties.getBack().getContactUrl(),
swaggerProperties.getBack().getContactEmail())
).build();
}
}
我们会看到在这个配置类中注入了两个Docket,分别代表前端的接口和后端的接口,那么在配置文件中如何进行配置呢?
首先我们先来看一下其配置类,代码如下
@Data
@ConfigurationProperties(prefix = "spring.swagger3")
public class SwaggerProperties {
private SwaggerEntity front;
private SwaggerEntity back;
@Data
public static class SwaggerEntity{
private String groupName;
private String basePackege;
private String title;
private String description;
private String contactName;
private String contactEmail;
private String contactUrl;
private String version;
private Boolean enable;
}
}
全局配置类
spring:
swagger3:
front:
enable: true
groupName: 前端接口
basePackege: com.example.demo.controller.api
title: 前端测试接口
description: 前端测试Spring Boot整合Swagger3.0
contactName: nihui
contactEmail: 18202504057@163.com
contactUrl: https://blog.csdn.net/nihui123
version: 0.0.1
back:
enable: true
groupName: 后端接口
basePackege: com.example.demo.controller.web
title: 后端测试接口
description: 后端测试Spring Boot整合Swagger3.0
contactName: nihui
contactEmail: 18202504057@163.com
contactUrl: https://blog.csdn.net/nihui123
version: 0.0.1
mvc:
pathmatch:
matching-strategy: ant_path_matcher
通过上面的配置完成配置之后,就会看到在接口页面会有两个分组,一个是前端接口、一个是后端接口分组。
添加授权认证信息
在很多对外提供服务的API接口中,都会有一个授权认证的操作,否则这些接口是无法进行调用的。例如在一般的情况下,会在接口中包含一个TOKEN参数。
那么在Swagger3.0中如何对这个认证信息进行配置,这样在每次请求的时候都会带着这个参数进行请求,这样就避免了我们在测试过程中,每次都需要添加这个信息的麻烦。
要完成授权信息的添加,我们需要在Docket方法中添加如下的内容
@Configuration
public class BaseSwagger3Config {
@Autowired
private BaseSwagger3Properties properties;
@Bean
public Docket baseApi(){
return new Docket(DocumentationType.OAS_30)
// 是否开启,根据环境配置
.enable(properties.getEnable())
.groupName(properties.getGroupName())
.apiInfo(frontApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(properties.getBasePackege()))
.paths(PathSelectors.any())
.build()
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private List<SecurityScheme> securitySchemes(){
ApiKey apiKey = new ApiKey("TOKEN","token", In.HEADER.toValue());
return Collections.singletonList(apiKey);
}
private List<SecurityContext> securityContexts(){
return Collections.singletonList(SecurityContext.builder().
securityReferences(Collections.singletonList(
new SecurityReference("TOKEN",new AuthorizationScope[]
{new AuthorizationScope("global","")}))).build());
}
// 前台API信息
private ApiInfo frontApiInfo(){
return new ApiInfoBuilder()
.title(properties.getTitle())
.description(properties.getDescription())
.version(properties.getVersion())
.contact(
// 添加开发者信息
new Contact(
properties.getContactName(),
properties.getContactUrl(),
properties.getContactEmail())
).build();
}
}
完成上述配置之后,会看到在接口页面上会多出一个认证的按钮。通过这个认证的按钮我们可以设置对应的参数值
添加公共参数
在不同的平台使用的时候,除了携带请求Token之外还会有一些用户进行用户分析,大数据分析的参数被传到请求中。那么如何在Swagger3.0中去定义这些公共参数呢?这个时候我们需要在配置代码中添加如下的内容。
@Configuration
public class BaseSwagger3Config {
@Autowired
private BaseSwagger3Properties properties;
@Bean
public Docket baseApi(){
RequestParameter requestParameter = new RequestParameterBuilder()
.name("clientType")
.description("客户端类型")
.in(ParameterType.HEADER)
.required(true)
.build();
//创建一个请求参数集合
List<RequestParameter> requestParameterList = Collections.singletonList(requestParameter);
return new Docket(DocumentationType.OAS_30)
// 是否开启,根据环境配置
.enable(properties.getEnable())
.groupName(properties.getGroupName())
.apiInfo(frontApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage(properties.getBasePackege()))
.paths(PathSelectors.any())
.build()
.globalRequestParameters(requestParameterList)
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private List<SecurityScheme> securitySchemes(){
ApiKey apiKey = new ApiKey("TOKEN","token", In.HEADER.toValue());
return Collections.singletonList(apiKey);
}
private List<SecurityContext> securityContexts(){
return Collections.singletonList(SecurityContext.builder().
securityReferences(Collections.singletonList(
new SecurityReference("TOKEN",new AuthorizationScope[]
{new AuthorizationScope("global","")}))).build());
}
// 前台API信息
private ApiInfo frontApiInfo(){
return new ApiInfoBuilder()
.title(properties.getTitle())
.description(properties.getDescription())
.version(properties.getVersion())
.contact(
// 添加开发者信息
new Contact(
properties.getContactName(),
properties.getContactUrl(),
properties.getContactEmail())
).build();
}
}
会看到上述代码中通过,RequestParameter定义了一个公共的参数,并且将其放入到了一个参数集合中,通过Docket的.globalRequestParameters(requestParameterList)方法将其添加到Swagger3.0文档中。然后运行项目会看到在接口中就会携带这对应的参数出现,并且这个参数是全局的,也就是说每个接口中都需要有这一个参数。
到这里,Swagger的相关内容就告一段落了。细心的读者会发现,在前面我们添加分组配置的时候在配置类上添加了好多的注解,但是在我们演示认证信息与全局参数的时候,配置类中只是简单的添加了一个@Configuration 注解。这是为什么呢?下面我们就来探索一下源码。
OpenApiAutoConfiguration 源码
会看到在这段源码中,好像什么功能都没实现,但是它确完成了Swagger3.0大多数的配置,而对于@EnableOpenApi 注解来讲。
@Configuration
@EnableConfigurationProperties(SpringfoxConfigurationProperties.class)
@ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
@Import({
OpenApiDocumentationConfiguration.class,
SpringDataRestConfiguration.class,
BeanValidatorPluginsConfiguration.class,
Swagger2DocumentationConfiguration.class,
SwaggerUiWebFluxConfiguration.class,
SwaggerUiWebMvcConfiguration.class
})
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
public class OpenApiAutoConfiguration {
}
@EnableOpenApi 注解
对于@EnableOpenApi注解来讲其关键的代码就是@Import(
OpenApiDocumentationConfiguration.class) 引入的还是这个类。
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = {java.lang.annotation.ElementType.TYPE})
@Documented
@Import(OpenApiDocumentationConfiguration.class)
public @interface EnableOpenApi {
}
这里我们会发现为什么在没有@EnableOpenApi注解的时候也会生效呢?那就是用到了我们Spring Boot自动配置的原理了。关于自动配置的原理在后续的分析中我们来进行讲解,这里就先不做过多说明。提示大家的就是找到如下图中的代码就可以理解自动配置的原理
总结
通过上面的内容我们了解了swagger3的一些扩展性的用法,当然Swagger的用法远远不止这些,但是这些内容已经可以支持在我们日常开发中的一些工作。希望大家多多关注,笔者会为大家带来更多精彩分享。