在上篇文章中我們介紹了Spring Boot 整合Swagger3.0的一些基礎用法,這篇文章中我們來深入學習一下Swagger3.0 還有其他進階用法。
在日常的開發中,為了減少工作量,我們會遇到一種情況,就是将前端的接口與後端的接口編寫到同一個代碼中,這樣也提高了代碼的複用率,減少了重複開發代碼的工作量。這個時候我們就需要将接口文檔也進行拆分。分為前端接口和後端接口兩個部分。
在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: [email protected]
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: [email protected]
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.0的一些擴充性的用法,當然Swagger的用法遠遠不止這些,但是這些内容已經可以支援在我們日常開發中的一些工作。希望大家多多關注,筆者會為大家帶來更多精彩幹活