8.5 Spring Boot集成Swagger2構(gòu)建自動化Rest API文檔
Swagger2的API文檔
在以往的項目中,關(guān)于API接口文檔,我們一般使用wiki或者干脆就是“線下文檔”。缺點是很明顯的:在迭代開發(fā)過程中,API會頻繁變動,這樣文檔需要同步修改。繁瑣。如果不及時更新,就會出生調(diào)用方?jīng)]有及時了解到API簽名的變化,導(dǎo)致較大的溝通很改動成本。
微服務(wù)時代,效率第一。
使用Swagger可以在部署的時候,實時生成最新的在線API文檔,而且不僅僅是文檔,同時支持API接口的測試。
我們使用Swagger,只需要在我們的開發(fā)代碼中,加上少量的注解配置,即可 自動化構(gòu)建Rest API文檔。在多人協(xié)作的開發(fā)過程中,API文檔不僅可以減少等待,也能保證開發(fā)的持續(xù)進(jìn)行。有一些單元測試框架可以生成API文檔,而Swagger可以在不寫單元測試的情況下生成在線的API頁面,并且可以直接在頁面進(jìn)行API調(diào)試。
SpringBoot集成Swagger2步驟
1.添加工程依賴的jar
在build.gradle中添加swagger2的依賴:
// https://mvnrepository.com/artifact/io.springfox/springfox-swagger2
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.6.1'
// https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.6.1'
完整的build.gradle配置如下:
group 'com.easy.springboot'
version '1.0-SNAPSHOT'
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
sourceCompatibility = 1.8
repositories {
// mavenCentral()
// jcenter()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.3.11'
testCompile group: 'junit', name: 'junit', version: '4.12'
compile('org.springframework.boot:spring-boot-starter-web')
// https://mvnrepository.com/artifact/io.springfox/springfox-swagger2
compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.6.1'
// https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui
compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.6.1'
}
buildscript {
ext {
springBootVersion = '1.5.2.RELEASE'
}
repositories {
// mavenCentral()
// jcenter()
maven {
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
2.配置Swagger的Docket Bean
@Configuration
class SwaggerConfig {
/**
* Docket: Springfox’s, primary api configuration mechanism is initialized for swagger specification 2.0
*
* A builder which is intended to be the primary interface into the swagger-springmvc framework.
* Provides sensible defaults and convenience methods for configuration.
* @return
*/
@Bean
Docket myApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.easy.springboot.h5perf"))
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
}
def apiInfo() {
return new ApiInfoBuilder()
.title("Spring Boot集成Swagger2構(gòu)建自動化Rest API文檔")
.description("Spring Boot開發(fā)從0到1教程")
.version("1.0")
.build()
}
}
這個 Docket類,是Springfox 框架的API配置機(jī)制實現(xiàn)的builder類。
我們通過@Configuration標(biāo)記此類為配置類,會在SpringBoot項目啟動的時候加載,
實際上我們已經(jīng)完成了對Swagger的配置,Swagger會自動掃描我們配置的cn.com.wenyi.controller包下的接口自動生成接口文檔。
3.配置WebMvc的addResourceHandlers
package com.easy.springboot.h5perf.config
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
/**
* Created by jack on 2017/4/23.
* http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.EnableWebMvcConfiguration.html
*/
@Configuration
class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/")
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/")
}
}
4.Swagger的API注解在Controller上面的使用
package com.easy.springboot.h5perf.controller
import com.easy.springboot.h5perf.mapper.TestCaseMapper
import com.easy.springboot.h5perf.model.TestCase
import com.easy.springboot.h5perf.result.Result
import groovy.json.JsonOutput
import io.swagger.annotations.Api
import io.swagger.annotations.ApiImplicitParam
import io.swagger.annotations.ApiOperation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
import org.springframework.ui.Model
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.ResponseBody
import springfox.documentation.swagger2.annotations.EnableSwagger2
/**
* Created by jack on 2017/4/22.
* http://springfox.github.io/springfox/docs/current/#springfox-samples
*/
@Api(value = "測試任務(wù)管理", tags = ["測試任務(wù)管理API"], description = "描述信息")
@Controller
class TestCaseController {
@Autowired
TestCaseMapper testCaseMapper
@PostMapping("/saveTestCase")
@ResponseBody
def saveTestCase(TestCase testCase) {
testCase.gmtCreated = new Date()
println("testCase===" + testCase)
int insert = testCaseMapper.insert(testCase)
println("testCase===" + testCase)
Result result = new Result()
if (insert == 1) {
result.success = true
result.result = testCase
} else {
result.success = false
result.result = testCase
}
def jsonOutput = new JsonOutput()
println("saveTestCase result===" + jsonOutput.toJson(result))
result
}
@GetMapping("/listTestCase")
def listTestCase(Model model) {
model.addAttribute("testCaseList", testCaseMapper.findAll())
"/test_case/list"
}
@ApiOperation(value = "list all TestCase Json", notes = "listTestCaseJson", produces = "application/json")
@GetMapping("/listTestCaseJson")
@ResponseBody
def listTestCaseJson() {
testCaseMapper.findAll()
}
@ApiOperation(value = "findOne TestCase Json", notes = "findOne TestCase", produces = "application/json")
@ApiImplicitParam(name = "id",
value = "測試任務(wù)ID",
dataType = "Integer",//This can be the class name or a primitive
required = true,
paramType = "query")//Valid values are {@code path}, {@code query}, {@code body}, {@code header} or {@code form}
@GetMapping("/findOne")
@ResponseBody
def findOne(@RequestParam(value = "id", required = true) Integer id) {
testCaseMapper.findOne(id)
}
}
@API表示這個類提供一個開放的API,可以通過description簡要描述該API的功能。
在一個@API下,可有多個@ApiOperation,表示針對該API的CRUD操作。
在ApiOperation Annotation中可以通過value,notes描述該操作的作用,response描述正常情況下該請求的返回對象類型。 在一個ApiOperation下,可以通過ApiResponses描述該API操作可能出現(xiàn)的異常情況。
ApiParam用于描述該API操作接受的參數(shù)類型
我們也可以為項目的Model對象添加Swagger Annotation,這樣Swagger Scanner可以獲取更多關(guān)于Model對象的信息。但是,這樣感覺侵入的代碼有點多。酌情考慮。
5.啟動@EnableSwagger2
在Application.groovy 微服務(wù)程序入口類上添加注解@EnableSwagger2:
package com.easy.springboot.h5perf
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ComponentScan
import org.springframework.web.servlet.config.annotation.EnableWebMvc
import springfox.documentation.swagger2.annotations.EnableSwagger2
/**
* Created by jack on 2017/4/22.
*/
@SpringBootApplication
@EnableWebMvc
@EnableSwagger2
@ComponentScan("com.easy.springboot.h5perf")
//@MapperScan('com.easy.springboot.h5perf.mapper') // 此處注解,與在Mapper接口上添加@Mapper注解功能等效
class Application implements CommandLineRunner {
static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
@Override
void run(String... args) throws Exception {
}
}
@EnableSwagger2這個注解用來啟動Swagger的文檔配置功能,我們通過源碼可以看到,它Import了配置類Swagger2DocumentationConfiguration。
而Swagger2DocumentationConfiguration類又@Import了SpringfoxWebMvcConfiguration,SwaggerCommonConfiguration配置類。到最后,SpringfoxWebMvcConfiguration類Import了配置類ModelsConfiguration。
Swagger具體的實現(xiàn)原理,可以參考[1]~[6]。
6.運行測試
文檔展示

實時測試

小結(jié)
Swagger可以充當(dāng)前后端協(xié)同工作,自由聯(lián)調(diào)的重要橋梁。方便快捷。很實用。
使用Swagger,我們可以自由生產(chǎn),顯示和消費自己的RESTful服務(wù)。不需要代理和第三方服務(wù)。同時,集成swagger-ui,通過Swagger API動態(tài)的生成漂亮的文檔和API測試空間。
本章工程源代碼:
https://github.com/EasySpringBoot/h5perf
參考資料:
1.http://springfox.github.io/springfox/docs/current/#springfox-configuration-and-demo-applications
2.http://swagger.io/
3.https://github.com/martypitt/swagger-springmvc
4.https://github.com/swagger-api/swagger-ui
5.https://github.com/swagger-api/swagger-core
6.https://github.com/swagger-api/swagger-spec