SpringBoot 如何生成接口文檔,老鳥們都這么玩的!
為什么要用Swagger ?
“ 作為一名程序員,我們最討厭兩件事:1. 別人不寫注釋。2. 自己寫注釋。 而作為一名接口開發(fā)者,我們同樣討厭兩件事:1. 別人不寫接口文檔,文檔不及時更新。2. 需要自己寫接口文檔,還需要及時更新。 ”
自動生成文檔:只需要少量的注解,Swagger 就可以根據(jù)代碼自動生成 API 文檔,很好的保證了文檔的時效性。 跨語言性,支持 40 多種語言。 Swagger UI 呈現(xiàn)出來的是一份可交互式的 API 文檔,我們可以直接在文檔頁面嘗試 API 的調(diào)用,省去了準備復雜的調(diào)用參數(shù)的過程。 還可以將文檔規(guī)范導入相關(guān)的工具(例如 SoapUI), 這些工具將會為我們自動地創(chuàng)建自動化測試。
Swagger集成
第一步:引入依賴包
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger-ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
第二步:修改配置文件
application.properties 加入配置
# 用于控制是否開啟Swagger,生產(chǎn)環(huán)境記得關(guān)閉Swagger,將值設(shè)置為 false
springfox.swagger2.enabled = true
@Configuration
@EnableSwagger2
@ConditionalOnClass(Docket.class)
public class SwaggerConfig {
private static final String VERSION = "1.0";
@Value("${springfox.swagger2.enabled}")
private Boolean swaggerEnabled;
@Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2)
.enable(swaggerEnabled)
.groupName("SwaggerDemo")
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
.paths(PathSelectors.any())
.build();
}
/**
* 添加摘要信息
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("接口文檔")
.contact(new Contact("JAVA日知錄","http://javadaily.cn","[email protected]"))
.description("Swagger接口文檔")
.version(VERSION)
.build();
}
}
.apis(RequestHandlerSelectors.withClassAnnotation(Api.class))標明給加上@Api注解的類自動生成接口文檔。第三步,配置API接口
@RestController
@Api(tags = "參數(shù)校驗")
@Slf4j
@Validated
public class ValidController {
@PostMapping("/valid/test1")
@ApiOperation("RequestBody校驗")
public String test1(@Validated @RequestBody ValidVO validVO){
log.info("validEntity is {}", validVO);
return "test1 valid success";
}
@ApiOperation("Form校驗")
@PostMapping(value = "/valid/test2")
public String test2(@Validated ValidVO validVO){
log.info("validEntity is {}", validVO);
return "test2 valid success";
}
@ApiOperation("單參數(shù)校驗")
@PostMapping(value = "/valid/test3")
public String test3(@Email String email){
log.info("email is {}", email);
return "email valid success";
}
}
@Api注解標注需要生成接口文檔,通過@ApiOperation注解標注接口名。ValidVO也加上對應(yīng)的注解@Data
@ApiModel(value = "參數(shù)校驗類")
public class ValidVO {
@ApiModelProperty("ID")
private String id;
@ApiModelProperty(value = "應(yīng)用ID",example = "cloud")
private String appId;
@NotEmpty(message = "級別不能為空")
@ApiModelProperty(value = "級別")
private String level;
@ApiModelProperty(value = "年齡")
private int age;
...
}
@ApiModel標注這是一個參數(shù)實體,通過@ApiModelProperty標注字段說明。Unable to infer base url
http://localhost:8080/swagger-ui.html體驗一下。ResponseBodyAdvice統(tǒng)一處理返回值/響應(yīng)體,導致給Swagger的返回值也包裝了一層,UI頁面無法解析。可以通過http://localhost:8080/v2/api-docs?group=SwaggerDemo觀察Swagger返回的json數(shù)據(jù)。@RestControllerAdvice(basePackages = "com.jianzh5.blog")
@Slf4j
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
...
}
For input string: ""
java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Long.parseLong(Long.java:702)
at java.base/java.lang.Long.valueOf(Long.java:1144)
給int類型的字段使用 @ApiModelPorperty注解時添加example屬性
@ApiModelProperty(value = "年齡",example = "10")
private int age;
去除原swagger中的 swagger-models和swagger-annotations,自行引入高版本的annotations和models
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.22</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-models</artifactId>
<version>1.5.22</version>
</dependency>
Swagger美化
knife4j優(yōu)化一下。第一步:引入依賴包
<!--整合Knife4j-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
“ 由于knife4j中已經(jīng)帶了 swagger-annotations和swagger-models的依賴,所以我們可以把上文中手動添加的兩個依賴刪除。”
第二步:啟用knife4j增強
@Configuration
@EnableSwagger2
@ConditionalOnClass(Docket.class)
@EnableKnife4j
public class SwaggerConfig {
...
}
http://localhost:8080/doc.html即可看到效果。Swagger參數(shù)分組
@ApiOperation("新增")
@PostMapping(value = "/valid/add")
public String add(@Validated(value = {ValidGroup.Crud.Create.class}) ValidVO validVO){
log.info("validEntity is {}", validVO);
return "test3 valid success";
}
@ApiOperation("更新")
@PostMapping(value = "/valid/update")
public String update(@Validated(value = ValidGroup.Crud.Update.class) ValidVO validVO){
log.info("validEntity is {}", validVO);
return "test4 valid success";
}
ValidVO來接收前端參數(shù),只不過使用了參數(shù)校驗中的分組,然后我們打開kife4j頁面觀察兩者的接口文檔有何不同。@Configuration
@EnableSwagger2
@ConditionalOnClass(Docket.class)
@EnableKnife4j
public class SwaggerConfig {
...
@Bean
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public GroupOperationModelsProviderPlugin groupOperationModelsProviderPlugin() {
return new GroupOperationModelsProviderPlugin();
}
@Bean
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public GroupModelBuilderPlugin groupModelBuilderPlugin() {
return new GroupModelBuilderPlugin();
}
@Bean
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public GroupModelPropertyBuilderPlugin groupModelPropertyBuilderPlugin() {
return new GroupModelPropertyBuilderPlugin();
}
@Bean
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public GroupExpandedParameterBuilderPlugin groupExpandedParameterBuilderPlugin() {
return new GroupExpandedParameterBuilderPlugin();
}
@Bean
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public GroupOperationBuilderPlugin groupOperationBuilderPlugin() {
return new GroupOperationBuilderPlugin();
}
@Bean
@Primary
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public GroupModelAttributeParameterExpander groupModelAttributeParameterExpander(FieldProvider fields, AccessorsProvider accessors, EnumTypeDeterminer enumTypeDeterminer) {
return new GroupModelAttributeParameterExpander(fields, accessors, enumTypeDeterminer);
}
}
分組使用說明
@Null(groups = ValidGroup.Crud.Create.class)
@NotNull(groups = ValidGroup.Crud.Update.class,message = "應(yīng)用ID不能為空")
@ApiModelProperty(value = "應(yīng)用ID",example = "cloud")
private String appId;
@ApiOperation("新增")
@PostMapping(value = "/valid/add")
public String add(@Validated(value = {ValidGroup.Crud.Create.class}) ValidVO validVO){
log.info("validEntity is {}", validVO);
return "test3 valid success";
}
小結(jié)
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??








