前言
經(jīng)過(guò)之前文章的學(xué)習(xí),我們學(xué)會(huì)了:
- 5分鐘入手Spring Boot;
-
Spring Boot項(xiàng)目中訪問(wèn)數(shù)據(jù)庫(kù);
1. Spring Boot數(shù)據(jù)庫(kù)交互之Spring Data JPA;
2. Spring Boot數(shù)據(jù)庫(kù)交互之Mybatis; - Spring Boot視圖技術(shù);
有了這些基礎(chǔ)知識(shí),可以說(shuō),我們已經(jīng)擁有Spring Boot項(xiàng)目開(kāi)發(fā)的入門基礎(chǔ)了。
現(xiàn)實(shí)場(chǎng)景中,我們往往需要知道API的文檔,才能用于測(cè)試、交付等,土一點(diǎn)的做法是開(kāi)發(fā)人員編寫API文檔,如Wiki、Word、其他在線文檔等,實(shí)際上,有很多開(kāi)源資源幫我們從技術(shù)上實(shí)現(xiàn)了API規(guī)格的文檔化,而Swagger是Spring Boot生態(tài)中的佼佼者,也是官方推薦的。
Swagger的主要優(yōu)點(diǎn)有:
- 免費(fèi)開(kāi)源,并且官網(wǎng)提供了豐富的工具和文檔介紹;
- 通過(guò)代碼添加注解,自動(dòng)生成API文檔;
- 提供在線API文檔,API文檔隨API變化而自動(dòng)同步更新;
- 可開(kāi)啟UI界面,界面美觀、清晰;
- UI界面支持在線測(cè)試API;
- 支持多種語(yǔ)言(Java,PHP...);
- 采用OpenAPI 規(guī)范;
(OpenAPI定義了RESTful APIs的編寫規(guī)范。規(guī)范中指定了一套模式/模型。這套規(guī)范是Swagger為各種編程語(yǔ)言編寫的服務(wù)提供接口文檔奠定了基礎(chǔ)。) - ...
那么,我們今天就一起來(lái)學(xué)習(xí):
Spring Boot中通過(guò)Swagger來(lái)做API文檔。
本文使用的項(xiàng)目代碼,是基于上一篇文章使用的Spring Boot項(xiàng)目:
Spring Boot數(shù)據(jù)庫(kù)交互之Mybatis
主要步驟
- 添加依賴;
- 創(chuàng)建config包;
- 創(chuàng)建配置類;
- 編寫配置類;
- 修飾Controller;
- 修飾項(xiàng)目啟動(dòng)類;
- 啟動(dòng)項(xiàng)目、使用Swagger;
1.添加依賴;
//在pom.xml文件中的dependencies節(jié)點(diǎn)內(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包;
項(xiàng)目根目錄下創(chuàng)建config包:
3.創(chuàng)建配置類;
4.編寫配置類;
1. 編寫Swagger配置類;
該步驟的意義:
配置Swagger要掃描API的Controller位置、要顯示的API path的樣式、初始化的Swagger頁(yè)面的一些基礎(chǔ)信息(見(jiàn)apiInfo()方法);
-
特別注意,要使用@EnableSwagger2注解;
-
設(shè)置生成API接口信息的被掃描Controller路徑,常見(jiàn)寫法:
//生成指定包下的所有API接口信息
RequestHandlerSelectors.basePackage("com.mycompany.sample.controller")
//生成所有API接口
RequestHandlerSelectors.any()
//所有API接口都不生成
RequestHandlerSelectors.none()
//只生成被@Api 這個(gè)注解注解過(guò)的類接口
RequestHandlerSelectors.withClassAnnotation(Api.class)
//只生成被@ApiOperation 這個(gè)注解注解過(guò)的API接口
RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)
-
設(shè)置API路徑篩選規(guī)則,常見(jiàn)寫法有:
//所有API均允許生成
PathSelectors.any()
//所有API均不允許生成
PathSelectors.none()
//正則表達(dá)式匹配,匹配上則允許生成,如包含getLead的API:
PathSelectors.regex("^(?!getLead).*$")
//只掃描指定的路徑下的請(qǐng)求,如只想掃描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.lxweimin.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),之后訪問(wèn)Swagger UI時(shí)就會(huì)如下:
2. 編寫WebMvcConfig配置類;
該步驟的意義:覆蓋、重寫項(xiàng)目配置的(如有)、默認(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 注解用來(lái)描述該服務(wù)的信息,如果不使用則顯示類名稱;
2. @ApiOperation 注解用于描述接口信息;
3. @ApiParam,@ApiImplicitParam,@ApiImplicitParams 注解用于描述接口的參數(shù);
4. @ApiResponse,@ApiResponses 注解用于描述API返回的信息,不使用會(huì)使用默認(rèn)的、根據(jù)接口情況自動(dòng)生成的描述信息,可在此處自定義錯(cuò)誤返回信息,如:
@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
5. @ApiVersion 注解用于描述接口的版本信息;
6.修飾項(xiàng)目啟動(dòng)類;
特別注意,只增加使用@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.啟動(dòng)項(xiàng)目、使用Swagger;
-
啟動(dòng)項(xiàng)目;
-
訪問(wèn)Swagger UI;
Swagger UI HTML站點(diǎn):http://localhost:8080/swagger-ui.html
頁(yè)面組成:
1. 標(biāo)題;
2. API文檔JSON入口:http://localhost:8080/v2/api-docs;
3. 作者信息;
4. API文檔主體;
5. 等。
打開(kāi)折疊的API列表,我們能看到API的規(guī)格:
以及API使用的實(shí)體對(duì)象信息:
我們還可以編輯實(shí)體類,修改、細(xì)化實(shí)體的展示:
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時(shí)掃描的實(shí)體注解;
@ApiModelProperty:屬性注解,可用于描述實(shí)體屬性;
修改后,效果如下:
還有我特別喜歡的測(cè)試API的功能
1. 點(diǎn)擊API規(guī)格右上角的"Try it out"按鈕:
2. 點(diǎn)擊Execute按鈕,測(cè)試API:
3. API測(cè)試返回:
我們可以在頁(yè)面上修改API參數(shù),如本例為leadId,進(jìn)行不同參數(shù)值的測(cè)試(Request Body也支持),而不需要其他測(cè)試工具或測(cè)試代碼,相當(dāng)方便;
(本例中,我們?cè)赾ontroller內(nèi)@ApiImplicitParam注解中設(shè)置了默認(rèn)值:example = "10130546")
使用Swagger來(lái)管理API文檔是十分方便、快捷的,界面美觀、并且有測(cè)試API的功能,對(duì)開(kāi)發(fā)人員、測(cè)試人員十分友好,滿足了絕大多數(shù)API文檔化的需求。
凡事也要從不同的角度來(lái)看待,Swagger強(qiáng)大的背后,也有其一定的局限性:
- 僅對(duì)于Restful API支持較為友好,其他類型的API支持得不是很好;
- 對(duì)代碼有一定的侵入性;
- Swagger與代碼需要強(qiáng)綁定;
(每個(gè)API都需要人為添加注解,如果有人偷懶,在API開(kāi)發(fā)時(shí)沒(méi)有加上Swagger對(duì)應(yīng)的注解,那么Swagger UI上是看不到該API的) - ...
綜合來(lái)看,我還是很喜歡Swagger的,使用簡(jiǎn)單,功能強(qiáng)大!!!
你Get到了嗎?