swagger 快速生成接口測試文檔詳解及注意要點

Swagger使用總結(jié)

1. Swagger是什么?

官方說法:Swagger是一個規(guī)范和完整的框架,用于生成、描述、調(diào)用和可視化 RESTful 風(fēng)格的 Web 服務(wù)??傮w目標(biāo)是使客戶端和文件系統(tǒng)作為服務(wù)器以同樣的速度來更新。文件的方法,參數(shù)和模型緊密集成到服務(wù)器端的代碼,允許API來始終保持同步。

個人覺得,swagger的一個最大的優(yōu)點是能實時同步api與文檔。在項目開發(fā)過程中,發(fā)生過多次:修改代碼但是沒有更新文檔,前端還是按照老舊的文檔進行開發(fā),在聯(lián)調(diào)過程中才發(fā)現(xiàn)問題的情況(當(dāng)然依據(jù)開閉原則,對接口的修改是不允許的,但是在項目不穩(wěn)定階段,這種情況很難避免)。

2. spring boot 集成 Swagger

目前維護的系統(tǒng)是基于springboot框架開發(fā)的,因此本文會詳細描述springboot與swagger集成的過程。

3,Swagger使用步驟:

3.1 導(dǎo)入相關(guān)的maven依賴


io.springfox

springfox-swagger2

2.5.0

io.springfox

springfox-swagger-ui

2.5.0

io.springfox

springfox-staticdocs

2.5.0


3.2 創(chuàng)建相關(guān)實體,controller,響應(yīng)對象,主要看其中的注解的使用。

1 ,@Api(description = "用戶相關(guān)接口文檔")每個controller上的注解,表示這個controller主要的業(yè)務(wù)模塊

2,@ApiOperation(value = "用戶首頁", notes = "訪問頁面")每個方法的注解,表示這個方法的業(yè)務(wù)功能是什么

3, @ApiParam(name = "userName",value = "用戶昵稱",required = true)方法參數(shù)注解,表示這個在這個業(yè)務(wù)方法中的名稱,生成后的文檔對該字段的說明,同樣支持對象類型(引用類型),通過@ApiModelProperty(value = "用戶id", required = true)來說明引用類型每個屬性的作用。

4,@RequestHeader("token") String token 這個注解可以獲取和設(shè)置header的參數(shù),如用戶身份簽名。

controller

package org.kewei.zhang.controllers;

import io.swagger.annotations.Api;

import io.swagger.annotations.ApiOperation;

import io.swagger.annotations.ApiParam;

import org.kewei.zhang.Beans.TbTest;

import org.kewei.zhang.entites.Constants;

import org.kewei.zhang.entites.Result;

import org.kewei.zhang.entites.UserVo;

import org.kewei.zhang.mapper.TbTestMapper;

import org.kewei.zhang.utils.DateUtil;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import java.text.ParseException;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import java.util.Random;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

/**

* @author : kewei.zhang

* @Date: 2017/10/19

* @Time: 下午3:00

* Description: 用于處理所有天網(wǎng)案件action的統(tǒng)一入口

*/

@SuppressWarnings("ALL")

@RestController

@RequestMapping("/case")

@Api(description = "用戶相關(guān)接口文檔")

public class SnCaseController extends BaseController {

@Autowired

private TbTestMapper tbTestMapper;

@GetMapping("/index")

@ApiOperation(value = "用戶首頁", notes = "訪問頁面")

public String index() {

TbTest tbTest = new TbTest();

tbTest.setAge(1);

tbTest.setBrithday(new Date());

tbTest.setHigh(172);

tbTest.setIsboy((short) 1);

tbTest.setName("張克巍");

tbTest.setSchool("皖西學(xué)院");

tbTest.setWigth(158);

tbTestMapper.insert(tbTest);

return "index";

}

@RequestMapping(value = "/add", method = RequestMethod.POST)

@ApiOperation(value = "添加用戶", notes = "增加用戶")

public Result add(@ApiParam(name = "token", value = "token",required = true) @RequestParam(name = "token", required = true) String token,

@ApiParam(name = "userName",value = "用戶昵稱",required = true)@RequestParam(name = "userName",required = true)String userName,

@ApiParam(name = "mobile",value = "手機",required = true)@RequestParam(name = "mobile",required = true)String mobile,

@ApiParam(required = true, name = "email", value = "郵箱") @RequestParam(name = "email", required = true) String email ) {

return new Result(Constants.SUCCESS,Constants.MSG_SUCCESS,new UserVo());

}

@RequestMapping(value = {"/toAdd","/testAdd"}, method = RequestMethod.GET)

@ApiOperation(value = "用戶添加", notes = "用戶增加")

public Result toAdd(@ApiParam(name = "token", value = "token",required = true) @RequestParam(name = "token", required = true) String token,

@ApiParam(name = "userName",value = "用戶昵稱",required = true)@RequestParam(name = "userName",required = true)String userName,

@ApiParam(name = "mobile",value = "手機",required = true)@RequestParam(name = "mobile",required = true)String mobile,

@ApiParam(required = true, name = "email", value = "郵箱") @RequestParam(name = "email", required = true) String email ) {

return new Result(Constants.SUCCESS,Constants.MSG_SUCCESS,new UserVo());

}

@RequestMapping(value = "/update", method = RequestMethod.POST)

@ApiOperation(value = "更新用戶", notes = "用戶更新")

public Result update(@ApiParam(name = "user", value = "user",required = true)@RequestBody UserVo userVo ) {

return new Result(Constants.SUCCESS,Constants.MSG_SUCCESS,userVo);

}

@RequestMapping(value = "/getHeader", method = RequestMethod.POST)

@ApiOperation(value = "獲取用戶頭部信息", notes = "獲取用戶頭部信息")

public Result getHeader(@ApiParam(name = "token", value = "用戶身份",required = true)@RequestHeader("token") String token,

@ApiParam(name = "userName",value = "用戶昵稱",required = true)@RequestParam(name = "userName",required = true)String userName,

@ApiParam(name = "mobile",value = "手機",required = true)@RequestParam(name = "mobile",required = true)String mobile) {

UserVo userVo= new UserVo();

userVo.setUserName(token+userName+mobile);

return new Result(Constants.SUCCESS,Constants.MSG_SUCCESS,userVo);

}

}

bean 這里需要注意,如果有boolean類型,要為其添加getXX

X和setXXX方法,不是isXXX,因為swagger不識別isXXX

package org.kewei.zhang.entites;

import io.swagger.annotations.ApiModel;

import io.swagger.annotations.ApiModelProperty;

/**

* @author: kewei.zhang

* @Date: 2017/12/5

* @Time: 下午3:15

* Description:

*/

@ApiModel(value = "用戶信息")

public class UserVo {

@ApiModelProperty(value = "用戶id", required = true)

private long userId=10;

@ApiModelProperty(value = "昵稱", required = true)

private String userName="張克巍";

public long getUserId() {

return userId;

}

public void setUserId(long userId) {

this.userId = userId;

}

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

}

響應(yīng)實體

package org.kewei.zhang.entites;

import com.fasterxml.jackson.annotation.JsonInclude;

import io.swagger.annotations.ApiModel;

import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;

/**

* @author: kewei.zhang

* @Date: 2017/12/5

* @Time: 下午3:11

* Description:

*/

@ApiModel

@JsonInclude(JsonInclude.Include.NON_NULL)

public class Result implements Serializable {

private static final long serialVersionUID = 1L;

// 200成功

@ApiModelProperty(value = "錯誤碼", name = "錯誤碼")

private int code;

// 返回消息,成功為“success”,失敗為具體失敗信息

@ApiModelProperty(value = "錯誤碼描述", name = "錯誤碼描述")

private String desc;

// 返回數(shù)據(jù)

@ApiModelProperty(value = "數(shù)據(jù)對象", name = "數(shù)據(jù)對象")

private T data;

public Result() {

}

public Result(int code, String desc) {

this.code = code;

this.desc = desc;

}

public Result(int code, String desc, T data) {

this.code = code;

this.desc = desc;

this.data = data;

}

public int getCode() {

return code;

}

public void setCode(int code) {

this.code = code;

}

public String getDesc() {

return desc;

}

public void setDesc(String desc) {

this.desc = desc;

}

public T getData() {

return data;

}

public void setData(T data) {

this.data = data;

}

@Override

public String toString() {

return "Result{" +

"code=" + code +

", desc='" + desc + '\'' +

", data=" + data +

'}';

}

}

package org.kewei.zhang.entites;

/**

* @author: kewei.zhang

* @Date: 2017/12/5

* @Time: 下午3:13

* Description:

*/

public interface Constants {

////////////// 系統(tǒng)標(biāo)識符 開始//////////////////

/**

* 錯誤 描述

*/

String MSG_ERROR = "error";

/**

* 成功 描述

*/

String MSG_SUCCESS = "OK";

////////////// 系統(tǒng)狀態(tài)碼 開始//////////////////

/**

* 請求失敗

*/

int ERROR = 100;

/**

* 請求成功

*/

int SUCCESS = 200;

}

3.3 swagger添加配置信息@Configuration@EnableSwagger2

package org.kewei.zhang.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.stereotype.Component;

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: kewei.zhang

* @Date: 2017/12/5

* @Time: 下午3:04

* Description:

*/

@Configuration

@EnableSwagger2

@Component

public class SwaggerConfig {

@Bean

public Docket userApi() {

return new Docket(DocumentationType.SWAGGER_2)

.groupName("用戶")

.select()

.apis(RequestHandlerSelectors.basePackage("org.kewei.zhang.controller"))// 選擇那些路徑和api會生成document,每個controller都需要添加

.paths(PathSelectors.any()) // 對所有路徑進行監(jiān)控

.build()

.apiInfo(userInfo());

}

private ApiInfo userInfo() {

ApiInfo apiInfo = new ApiInfo("用戶相關(guān)接口",//大標(biāo)題

"用戶有關(guān)的接口,包括增加刪除用戶",//小標(biāo)題

"0.1",//版本

"上海",

new Contact("zkw", "", ""),// 作者

"swagger url",//鏈接顯示文字

""http://網(wǎng)站鏈接

);

return apiInfo;

}

}

3.4 在瀏覽器中輸入http://ip:port/your-app-root/swagger-ui.html即可生成相應(yīng)的文檔并可以隨時測試。

圖片.png

圖片.png

圖中的文字說明都是通過之前的注解添加進去的

上述是完成生成api文檔的具體步驟,但是有這樣幾個問題值得大家思考。

接口文檔生成,需要嵌入我們的項目中,對我們的代碼有侵入,這一點現(xiàn)在避免不了,而且我們只希望用戶在我們的測試環(huán)境去測試,不希望生成環(huán)境去生成文檔,如何解決這個問題,方法有兩種,如下:

在配置中做管理

@Configuration

@EnableSwagger2

@EnableWebMvc

@ComponentScan("com.XXX.controller")

public class SwaggerConfig{

@Autowired

ConfigService configService;

@Bean

public Docket customDocket() {

if(configService.getServerEnv() == ServerEnvEnum.ONLINE) {

return new Docket(DocumentationType.SWAGGER_2)

.apiInfo(apiInfoOnline())

.select()

.paths(PathSelectors.none())//如果是線上環(huán)境,添加路徑過濾,設(shè)置為全部都不符合

.build();

}else {

return new Docket(DocumentationType.SWAGGER_2)

.apiInfo(apiInfo());

}

}

private ApiInfo apiInfo() {

return new ApiInfoBuilder()

.title("XXX系統(tǒng)")

.description("XXX系統(tǒng)接口")

.license("")

.licenseUrl("")

.termsOfServiceUrl("")

.version("1.0.0")

.contact(new Contact("","", ""))

.build();

}

private ApiInfo apiInfoOnline() {

return new ApiInfoBuilder()

.title("")

.description("")

.license("")

.licenseUrl("")

.termsOfServiceUrl("")

.version("")

.contact(new Contact("","", ""))

.build();

}

}

另一種方式是:

修改一下依賴,為了編譯通過,單獨把swagger-annotations拿出來,線上環(huán)境把springfox-swagger-ui的依賴配置成是provided,這樣可以實現(xiàn)http://localhost/swagger-ui.html訪問404。但是:http://localhost/v2/api-docshttp://localhost/swagger-resources等接口依然能夠訪問,盡管是空的!

io.swagger

swagger-annotations

${springfox-swagger-anno.version}

io.springfox

springfox-swagger2

${springfox-swagger.version}

io.springfox

springfox-swagger-ui

${swagger.scope}

${springfox-swagger.version}

online

online

provided

作者:時之令

鏈接:http://www.lxweimin.com/p/c8b5382c39dc

來源:簡書

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Swagger使用總結(jié) 1. Swagger是什么? 官方說法:Swagger是一個規(guī)范和完整的框架,用于生成、描...
    時之令閱讀 10,477評論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,993評論 19 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,779評論 18 399
  • Q 一些jar包提示Failed to resolve: com.squareup.retrofit:retrof...
    hp簡書閱讀 238評論 0 0
  • “行動吧,遇見更好的自己” 面試是個技術(shù)活,懵懵懂懂接到要去面試的電話,在網(wǎng)絡(luò)上匆忙查了一下公司的背景情況。其實并...
    SuperVicky閱讀 126評論 0 0