前言
經(jīng)過之前文章的學(xué)習(xí)修己,我們學(xué)會了:
- 5分鐘入手Spring Boot孝情;
-
Spring Boot項目中訪問數(shù)據(jù)庫;
1. Spring Boot數(shù)據(jù)庫交互之Spring Data JPA狂秦;
2. Spring Boot數(shù)據(jù)庫交互之Mybatis细溅; - Spring Boot視圖技術(shù);
有了這些基礎(chǔ)知識研儒,可以說豫缨,我們已經(jīng)擁有Spring Boot項目開發(fā)的入門基礎(chǔ)了独令。
現(xiàn)實場景中,我們往往需要知道API的文檔好芭,才能用于測試燃箭、交付等,土一點的做法是開發(fā)人員編寫API文檔舍败,如Wiki招狸、Word、其他在線文檔等邻薯,實際上裙戏,有很多開源資源幫我們從技術(shù)上實現(xiàn)了API規(guī)格的文檔化,而Swagger是Spring Boot生態(tài)中的佼佼者厕诡,也是官方推薦的累榜。
Swagger的主要優(yōu)點有:
- 免費開源,并且官網(wǎng)提供了豐富的工具和文檔介紹灵嫌;
- 通過代碼添加注解壹罚,自動生成API文檔;
- 提供在線API文檔寿羞,API文檔隨API變化而自動同步更新猖凛;
- 可開啟UI界面,界面美觀绪穆、清晰辨泳;
- UI界面支持在線測試API;
- 支持多種語言(Java玖院,PHP...)菠红;
- 采用OpenAPI 規(guī)范;
(OpenAPI定義了RESTful APIs的編寫規(guī)范司恳。規(guī)范中指定了一套模式/模型途乃。這套規(guī)范是Swagger為各種編程語言編寫的服務(wù)提供接口文檔奠定了基礎(chǔ)。) - ...
那么扔傅,我們今天就一起來學(xué)習(xí):
Spring Boot中通過Swagger來做API文檔。
本文使用的項目代碼烫饼,是基于上一篇文章使用的Spring Boot項目:
Spring Boot數(shù)據(jù)庫交互之Mybatis
主要步驟
- 添加依賴猎塞;
- 創(chuàng)建config包;
- 創(chuàng)建配置類杠纵;
- 編寫配置類荠耽;
- 修飾Controller;
- 修飾項目啟動類比藻;
- 啟動項目铝量、使用Swagger倘屹;
1.添加依賴;
//在pom.xml文件中的dependencies節(jié)點內(nèi)添加以下內(nèi)容:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
2.創(chuàng)建config包慢叨;
項目根目錄下創(chuàng)建config包:
3.創(chuàng)建配置類纽匙;
4.編寫配置類;
1. 編寫Swagger配置類拍谐;
該步驟的意義:
配置Swagger要掃描API的Controller位置烛缔、要顯示的API path的樣式、初始化的Swagger頁面的一些基礎(chǔ)信息(見apiInfo()方法)轩拨;
-
特別注意践瓷,要使用@EnableSwagger2注解;
-
設(shè)置生成API接口信息的被掃描Controller路徑亡蓉,常見寫法:
//生成指定包下的所有API接口信息
RequestHandlerSelectors.basePackage("com.mycompany.sample.controller")
//生成所有API接口
RequestHandlerSelectors.any()
//所有API接口都不生成
RequestHandlerSelectors.none()
//只生成被@Api 這個注解注解過的類接口
RequestHandlerSelectors.withClassAnnotation(Api.class)
//只生成被@ApiOperation 這個注解注解過的API接口
RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)
-
設(shè)置API路徑篩選規(guī)則晕翠,常見寫法有:
//所有API均允許生成
PathSelectors.any()
//所有API均不允許生成
PathSelectors.none()
//正則表達(dá)式匹配,匹配上則允許生成砍濒,如包含getLead的API:
PathSelectors.regex("^(?!getLead).*$")
//只掃描指定的路徑下的請求淋肾,如只想掃描getLead API路徑下的:
//getLead為API path的一部分
PathSelectors.ant("/getLead/**")
代碼如下:
package com.mycompany.sample.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author : dylanz
* @since : 07/17/2020
**/
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket api() {//名字不限
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.enable(true)
.select()
.apis(RequestHandlerSelectors.basePackage("com.mycompany.sample.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {//名字不限
Contact contact = new Contact("Dylan Zhang", "http://www.reibang.com/u/56578a39a99a", "997604787@qq.com");
return new ApiInfoBuilder()
.title("Lead API")
.contact(contact)
.description("Lead related operations")
.termsOfServiceUrl("http://127.0.0.1:8080/getLead/10130546")
.version("1.0")
.build();
}
}
-
如果想關(guān)閉Swagger UI:
enable設(shè)置為:.enable(false),之后訪問Swagger UI時就會如下:
2. 編寫WebMvcConfig配置類梯影;
該步驟的意義:覆蓋巫员、重寫項目配置的(如有)、默認(rèn)的靜態(tài)資源路徑甲棍,這樣才能讀取到Swagger jar包內(nèi)的靜態(tài)文件(html简识、css文件等);
package com.mycompany.sample.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import javax.annotation.PostConstruct;
/**
* @author : dylanz
* @since : 07/17/2020
**/
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
@PostConstruct
public void init() {
System.out.println("Init in WebMvcConfig...");
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/statics/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
5.修飾Controller感猛;
package com.mycompany.sample.controller;
import com.mycompany.sample.domain.Lead;
import com.mycompany.sample.service.LeadService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author : dylanz
* @since : 07/07/2020
**/
@RestController
@Api
public class LeadController {
@Autowired
private LeadService leadService;
@GetMapping("/getLead/{leadId}")
@ResponseBody
@ApiOperation(value = "get lead by leadId", httpMethod = "GET")
@ApiImplicitParams(
{@ApiImplicitParam(name = "leadId", value = "leadId", required = true, paramType = "path", dataType = "Long", example = "10130546")}
)
public Lead getLead(@PathVariable(name = "leadId") Long leadId) {
return leadService.getLeadByLeadId(leadId);
}
}
1. @Api 注解用來描述該服務(wù)的信息七扰,如果不使用則顯示類名稱;
2. @ApiOperation 注解用于描述接口信息;
3. @ApiParam,@ApiImplicitParam陪白,@ApiImplicitParams 注解用于描述接口的參數(shù);
4. @ApiResponse颈走,@ApiResponses 注解用于描述API返回的信息,不使用會使用默認(rèn)的咱士、根據(jù)接口情況自動生成的描述信息立由,可在此處自定義錯誤返回信息,如:
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
5. @ApiVersion 注解用于描述接口的版本信息序厉;
6.修飾項目啟動類锐膜;
特別注意,只增加使用@EnableSwagger2注解即可弛房;
package com.mycompany.sample;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author : dylanz
* @since : 07/07/2020
**/
@SpringBootApplication
@EnableSwagger2
@MapperScan(basePackages = "com.mycompany.sample.dao")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
7.啟動項目道盏、使用Swagger;
-
啟動項目;
-
訪問Swagger UI荷逞;
Swagger UI HTML站點:http://localhost:8080/swagger-ui.html
頁面組成:
1. 標(biāo)題媒咳;
2. API文檔JSON入口:http://localhost:8080/v2/api-docs;
3. 作者信息种远;
4. API文檔主體涩澡;
5. 等。
打開折疊的API列表院促,我們能看到API的規(guī)格:
以及API使用的實體對象信息:
我們還可以編輯實體類筏养,修改、細(xì)化實體的展示:
package com.mycompany.sample.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
/**
* @author : dylanz
* @since : 07/07/2020
**/
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@ApiModel
public class Lead implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "leadId", dataType = "Long", name = "id", example = "10130546")
private Long leadId;
@ApiModelProperty(value = "email", dataType = "String", name = "email", example = "dylan.zhang@xxxx.com")
private String email;
}
@ApiModel:生成swagger時掃描的實體注解常拓;
@ApiModelProperty:屬性注解渐溶,可用于描述實體屬性;
修改后弄抬,效果如下:
還有我特別喜歡的測試API的功能
1. 點擊API規(guī)格右上角的"Try it out"按鈕:
2. 點擊Execute按鈕茎辐,測試API:
3. API測試返回:
我們可以在頁面上修改API參數(shù),如本例為leadId掂恕,進(jìn)行不同參數(shù)值的測試(Request Body也支持)拖陆,而不需要其他測試工具或測試代碼,相當(dāng)方便懊亡;
(本例中依啰,我們在controller內(nèi)@ApiImplicitParam注解中設(shè)置了默認(rèn)值:example = "10130546")
使用Swagger來管理API文檔是十分方便、快捷的店枣,界面美觀速警、并且有測試API的功能,對開發(fā)人員鸯两、測試人員十分友好闷旧,滿足了絕大多數(shù)API文檔化的需求。
凡事也要從不同的角度來看待钧唐,Swagger強(qiáng)大的背后忙灼,也有其一定的局限性:
- 僅對于Restful API支持較為友好,其他類型的API支持得不是很好钝侠;
- 對代碼有一定的侵入性该园;
- Swagger與代碼需要強(qiáng)綁定;
(每個API都需要人為添加注解帅韧,如果有人偷懶爬范,在API開發(fā)時沒有加上Swagger對應(yīng)的注解,那么Swagger UI上是看不到該API的) - ...
綜合來看弱匪,我還是很喜歡Swagger的,使用簡單,功能強(qiáng)大O艚搿3饽选!
你Get到了嗎帘饶?