Spring Boot之整合Swagger

前言

經(jīng)過之前文章的學(xué)習(xí)修己,我們學(xué)會了:

有了這些基礎(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)點有:

  1. 免費開源,并且官網(wǎng)提供了豐富的工具和文檔介紹灵嫌;
  2. 通過代碼添加注解壹罚,自動生成API文檔;
  3. 提供在線API文檔寿羞,API文檔隨API變化而自動同步更新猖凛;
  4. 可開啟UI界面,界面美觀绪穆、清晰辨泳;
  5. UI界面支持在線測試API;
  6. 支持多種語言(Java玖院,PHP...)菠红;
  7. 采用OpenAPI 規(guī)范;
    (OpenAPI定義了RESTful APIs的編寫規(guī)范司恳。規(guī)范中指定了一套模式/模型途乃。這套規(guī)范是Swagger為各種編程語言編寫的服務(wù)提供接口文檔奠定了基礎(chǔ)。)
  8. ...

那么扔傅,我們今天就一起來學(xué)習(xí):

Spring Boot中通過Swagger來做API文檔。

本文使用的項目代碼烫饼,是基于上一篇文章使用的Spring Boot項目:
Spring Boot數(shù)據(jù)庫交互之Mybatis

主要步驟

  1. 添加依賴猎塞;
  2. 創(chuàng)建config包;
  3. 創(chuàng)建配置類杠纵;
  4. 編寫配置類荠耽;
  5. 修飾Controller;
  6. 修飾項目啟動類比藻;
  7. 啟動項目铝量、使用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包:

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時就會如下:

關(guān)閉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

HTML站點

頁面組成:

1. 標(biāo)題媒咳;
2. API文檔JSON入口:http://localhost:8080/v2/api-docs
3. 作者信息种远;
4. API文檔主體涩澡;
5. 等。

打開折疊的API列表院促,我們能看到API的規(guī)格:

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"按鈕:

Try it out

2. 點擊Execute按鈕茎辐,測試API:

Execute

3. API測試返回:

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)大的背后忙灼,也有其一定的局限性:
  1. 僅對于Restful API支持較為友好,其他類型的API支持得不是很好钝侠;
  2. 對代碼有一定的侵入性该园;
  3. Swagger與代碼需要強(qiáng)綁定;
    (每個API都需要人為添加注解帅韧,如果有人偷懶爬范,在API開發(fā)時沒有加上Swagger對應(yīng)的注解,那么Swagger UI上是看不到該API的)
  4. ...
綜合來看弱匪,我還是很喜歡Swagger的,使用簡單,功能強(qiáng)大O艚搿3饽选!

你Get到了嗎帘饶?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哑诊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子及刻,更是在濱河造成了極大的恐慌镀裤,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缴饭,死亡現(xiàn)場離奇詭異暑劝,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)颗搂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門担猛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丢氢,你說我怎么就攤上這事傅联。” “怎么了疚察?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵蒸走,是天一觀的道長。 經(jīng)常有香客問我貌嫡,道長比驻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任衅枫,我火速辦了婚禮嫁艇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弦撩。我一直安慰自己步咪,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布益楼。 她就那樣靜靜地躺著猾漫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪感凤。 梳的紋絲不亂的頭發(fā)上悯周,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機(jī)與錄音陪竿,去河邊找鬼禽翼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的闰挡。 我是一名探鬼主播锐墙,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼长酗!你這毒婦竟也來了溪北?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤夺脾,失蹤者是張志新(化名)和其女友劉穎之拨,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體咧叭,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蚀乔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了佳簸。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乙墙。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖生均,靈堂內(nèi)的尸體忽然破棺而出听想,到底是詐尸還是另有隱情,我是刑警寧澤马胧,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布汉买,位于F島的核電站,受9級特大地震影響佩脊,放射性物質(zhì)發(fā)生泄漏蛙粘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一威彰、第九天 我趴在偏房一處隱蔽的房頂上張望出牧。 院中可真熱鬧,春花似錦歇盼、人聲如沸舔痕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伯复。三九已至,卻和暖如春邢笙,著一層夾襖步出監(jiān)牢的瞬間啸如,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工氮惯, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留叮雳,地道東北人想暗。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像债鸡,于是被迫代替她去往敵國和親江滨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,490評論 2 348