Spring Boot使用Swagger2構(gòu)建RESTful文檔

Spring Boot給Java開發(fā)人員的生產(chǎn)力帶來(lái)極大的提高,尤其是構(gòu)建RESTful API更是方便箍邮。使用RESTful服務(wù)通常是涉及到多個(gè)終端的團(tuán)隊(duì),比如Android杖剪、iOS菩收、WEB等。為了讓大家溝通順暢鬓椭,通常我們需要編寫一份詳細(xì)的RESTful業(yè)務(wù)接口文檔颠猴,文檔形式有Word或者Excel。但是我們也會(huì)發(fā)現(xiàn)有如下問(wèn)題:

  • 接口非常多小染,細(xì)節(jié)又復(fù)雜翘瓮,如果由程序員高質(zhì)量的輸出一個(gè)文檔,經(jīng)常耗時(shí)長(zhǎng)而且效果也不好裤翩,抱怨聲不絕與耳资盅。
  • 隨著時(shí)間的推移,文檔需要與代碼保持同步踊赠。但由于大部分程序員都還有著文檔不重要的思想呵扛,于是總有這樣那樣的原因?qū)е鲁绦騿T不愿意或遺忘了更新文檔。

我一直認(rèn)為筐带,代碼就是最好的文檔今穿,如果能將代碼和注釋說(shuō)明很好結(jié)合在一塊。既減輕了研發(fā)人員的負(fù)擔(dān)伦籍,又能輸出高質(zhì)量的文檔蓝晒,那就最好不過(guò)了。這一點(diǎn)Spring Boot也替我們想到了帖鸦,那就是RESTful API的重磅好伙伴 Swagger2芝薇。
具體效果圖如下:

RESTful API Docs

下面我們以Chapter 3-1-1: 構(gòu)建一個(gè)復(fù)雜的RESTful API及單元測(cè)試中的代碼為例,看看如何將Swagger2集成到Spring Boot工程中創(chuàng)建一個(gè)RESTful API文檔

pom.xml中添加Swagger2依賴

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.2.2</version>
</dependency>

創(chuàng)建Swagger2配置類

在RestApplication.java同級(jí)路徑下創(chuàng)建SwaggerConfig.java

@Configuration
@EnableSwagger2
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("使用Swagger2構(gòu)建RESTful APIs")
                .description("客戶端與服務(wù)端接口文檔")
                .termsOfServiceUrl("http://localost:8080")
                .contact("bluecoffee")
                .version("1.0.0")
                .build();

        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.bluecoffee.rest"))
                .paths(PathSelectors.any())
                .build();
    }

}

上述代碼中富蓄,通過(guò)@Configuration注解剩燥,讓Spring來(lái)加載該類配置,通過(guò)@EnableSwagger2注解來(lái)啟用Swagger2立倍。

再通過(guò)createRestApi函數(shù)創(chuàng)建Docket的Bean之后灭红,apiInfo是用來(lái)創(chuàng)建接口文檔的基本信息(這些基本信息會(huì)展現(xiàn)在文檔頁(yè)面中)。select()函數(shù)返回一個(gè)ApiSelectorBuilder實(shí)例用來(lái)控制哪些接口暴露給Swagger來(lái)展現(xiàn)口注,本例采用指定掃描的包路徑來(lái)定義变擒,Swagger會(huì)掃描該包下所有Controller定義的API,并產(chǎn)生文檔內(nèi)容(除了被@ApiIgnore指定的請(qǐng)求)寝志。

創(chuàng)建API接口描述信息

@RestController
@RequestMapping(value="/books")
public class BookController {

    // 創(chuàng)建線程安全的Map
    static Map<Long, Book> books = Collections.synchronizedMap(new HashMap<Long, Book>());

    @ApiOperation(value="獲取書籍列表", notes="")
    @RequestMapping(value={"/"}, method=RequestMethod.GET)
    public List<Book> getBookList() {
        // 處理"/books/"的GET請(qǐng)求娇斑,用來(lái)獲取圖書列表
        // 還可以通過(guò)@RequestParam傳遞參數(shù)來(lái)進(jìn)行查詢條件或者翻頁(yè)信息的傳遞
        List<Book> r = new ArrayList<Book>(books.values());
        return r;
    }

    @ApiOperation(value="創(chuàng)建書籍", notes="根據(jù)Book對(duì)象創(chuàng)建書籍")
    @ApiImplicitParam(name = "book", value = "書籍實(shí)體對(duì)象Book", required = true, dataType = "Book")
    @RequestMapping(value="/", method=RequestMethod.POST,produces = "application/json")
    public JsonResult createBook(@RequestBody Book book) {
        // 處理"/books/"的POST請(qǐng)求策添,用來(lái)創(chuàng)建User
        // 除了@ModelAttribute綁定參數(shù)之外,還可以通過(guò)@RequestParam從頁(yè)面中傳遞參數(shù)
        books.put(book.getBookId(), book);
        JsonResult jr = new JsonResult();
        jr.setIsSuccessful(true);
        jr.setResultCode("0000");
        jr.setResultDesc("success");
        return jr;
    }

    @ApiOperation(value="獲取書籍詳細(xì)信息", notes="根據(jù)URL中的bookId來(lái)獲取書籍詳細(xì)信息")
    @ApiImplicitParam(name = "bookId", value = "書籍ID", required = true, dataType = "Long")
    @RequestMapping(value="/{bookId}", method=RequestMethod.GET)
    public Book getBook(@PathVariable Long bookId) {
        // 處理"/books/{id}"的GET請(qǐng)求毫缆,用來(lái)獲取url中id值的Book信息
        // url中的id可通過(guò)@PathVariable綁定到函數(shù)的參數(shù)中
        return books.get(bookId);
    }

    @ApiOperation(value="更新書籍信息", notes="根據(jù)URL中的bookId來(lái)指定更新書籍唯竹,并根據(jù)傳過(guò)來(lái)的Book信息來(lái)更新書籍詳細(xì)信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "bookId", value = "書籍ID", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "book", value = "書籍詳細(xì)實(shí)體book", required = true, dataType = "Book")
    })
    @RequestMapping(value="/{bookId}", method=RequestMethod.PUT)
    public JsonResult putBook(@PathVariable Long bookId, @RequestBody Book book) {
        // 處理"/books/{bookId}"的PUT請(qǐng)求,用來(lái)更新Book信息
        Book b = books.get(bookId);
        b.setTitle(book.getTitle());
        b.setAuthor(book.getAuthor());
        books.put(bookId, b);
        JsonResult jr = new JsonResult();
        jr.setIsSuccessful(true);
        jr.setResultCode("0000");
        jr.setResultDesc("success");
        return jr;
    }

    @ApiOperation(value="刪除書籍", notes="根據(jù)URL中的bookId來(lái)指定刪除書籍")
    @ApiImplicitParam(name = "bookId", value = "書籍ID", required = true, dataType = "Long")
    @RequestMapping(value="/{bookId}", method=RequestMethod.DELETE)
    public JsonResult deleteBook(@PathVariable Long bookId) {
        // 處理"/books/{bookId}"的DELETE請(qǐng)求苦丁,用來(lái)刪除Book
        books.remove(bookId);
        JsonResult jr = new JsonResult();
        jr.setIsSuccessful(true);
        jr.setResultCode("0000");
        jr.setResultDesc("success");
        return jr;
    }
}

我們通過(guò)@ApiOperation注解來(lái)給API增加說(shuō)明浸颓、通過(guò)@ApiImplicitParams、@ApiImplicitParam注解來(lái)給參數(shù)增加說(shuō)明旺拉。

完成這些工作后产上,我們?cè)賳?dòng)Spring Boot程序,訪問(wèn):http://localhost:8080/swagger-ui.html蛾狗。就能看到之前所展示的RESTful API的頁(yè)面晋涣。我們可以再點(diǎn)開具體的API請(qǐng)求,以POST類型的/books/為例:

創(chuàng)建書籍API

API測(cè)試

在上圖中我們可以看到book的Value是一個(gè)輸入框沉桌,下方還有一個(gè)"Try it out!"按鈕谢鹊。沒(méi)錯(cuò),Swagger2還提供了接口測(cè)試功能留凭,我們只要按照Book對(duì)象的Model Schema(黃色區(qū)域)示例進(jìn)行參數(shù)修改撇贺,然后點(diǎn)擊"Try it out!"按鈕就可以進(jìn)行接口測(cè)試了,大家也可以自行測(cè)試一下其他接口冰抢。

小結(jié)

相比編寫Word或Excel文檔而言,Swagger2雖然對(duì)代碼有一定的侵入性艘狭,但是我個(gè)人覺(jué)得還是可以接受的挎扰,畢竟減少了很多工作量,同時(shí)也增加了代碼的可讀性巢音,非常值得推薦遵倦。
對(duì)比Swagger2,我還使用過(guò)apiDoc這個(gè)工具官撼,使用感覺(jué)也不錯(cuò)梧躺,大家有興趣也可以去試試看。

完整代碼戳這里: Chapter 3-1-3 - 利用Swagger2構(gòu)建RESTful API文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末傲绣,一起剝皮案震驚了整個(gè)濱河市掠哥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌秃诵,老刑警劉巖续搀,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異菠净,居然都是意外死亡禁舷,警方通過(guò)查閱死者的電腦和手機(jī)彪杉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)牵咙,“玉大人派近,你說(shuō)我怎么就攤上這事〗嘧溃” “怎么了渴丸?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)战坤。 經(jīng)常有香客問(wèn)我曙强,道長(zhǎng),這世上最難降的妖魔是什么途茫? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任碟嘴,我火速辦了婚禮,結(jié)果婚禮上囊卜,老公的妹妹穿的比我還像新娘娜扇。我一直安慰自己,他們只是感情好栅组,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布雀瓢。 她就那樣靜靜地躺著,像睡著了一般玉掸。 火紅的嫁衣襯著肌膚如雪刃麸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天司浪,我揣著相機(jī)與錄音泊业,去河邊找鬼。 笑死啊易,一個(gè)胖子當(dāng)著我的面吹牛吁伺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播租谈,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼篮奄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了割去?” 一聲冷哼從身側(cè)響起窟却,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呻逆,沒(méi)想到半個(gè)月后间校,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡页慷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年憔足,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胁附。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡滓彰,死狀恐怖控妻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情揭绑,我是刑警寧澤弓候,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站他匪,受9級(jí)特大地震影響菇存,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜邦蜜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一依鸥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悼沈,春花似錦贱迟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至壤靶,卻和暖如春缚俏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贮乳。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工袍榆, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人塘揣。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宿崭,于是被迫代替她去往敵國(guó)和親亲铡。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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