Spring Boot 集成 Swagger 生成 RESTful API 文檔

原文連接:html

簡介

Swagger 官網是這麼描述它的:The Best APIs are Built with Swagger Toolsjava

Swagger 是一套基於 OpenAPI 規範構建的開源工具,能夠幫助咱們設計、構建、記錄以及使用 Rest API。Swagger 主要包含了如下三個部分:git

  1. Swagger Editor:基於瀏覽器的編輯器,咱們可使用它編寫咱們 OpenAPI 規範。
  2. Swagger UI:它會將咱們編寫的 OpenAPI 規範呈現爲交互式的 API 文檔,後文我將使用瀏覽器來查看而且操做咱們的 Rest API。
  3. Swagger Codegen:它能夠經過爲 OpenAPI(之前稱爲 Swagger)規範定義的任何 API 生成服務器存根和客戶端 SDK 來簡化構建過程。

Spring Boot 使得開發 RESTful 服務變得簡單。那麼編寫 Spring Boot 接口,爲什麼要用 Swagger 呢?github

  • 代碼改變,文檔就會改變。只須要少許的註釋,Swagger 就能夠根據代碼自動生成 API 文檔。
  • Swagger UI 是一份交互式的 API 文檔,能夠直接在 Web 界面調用 API。這裏有一份 Swagger UI 的 Live Demo,看看官方是怎麼寫 RESTful API 的。

添加依賴

pom.xml 引入 Swagger 相關的依賴:web

<!-- swagger2 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${swagger.version}</version>
</dependency>
<!-- swagger2 ui -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${swagger.version}</version>
</dependency>

使用 property 定義了 Swagger 的版本,所以還須要添加:spring

<swagger.version>2.9.2</swagger.version>

依賴說明:shell

  • springfox-swagger2 Swagger 的 Java 實現
  • springfox-swagger-ui Swagger UI 頁面的依賴

Swagger 配置類

使用註解 @Configuration 編寫 Swagger 配置類—— SwaggerConfig數據庫

新建 config 的包,建立 SwaggerConifg 的配置類:編程

//經過@Configuration註解,讓Spring來加載該類配置
@Configuration
//經過@EnableSwagger2註解來啓用Swagger2
@EnableSwagger2
//@ConditionalOnExpression 爲Spring的註解,用戶是否實例化本類,用因而否啓用Swagger的判斷(生產環境須要屏蔽Swagger)
@ConditionalOnExpression("${swagger.enable:true}")
public class SwaggerConfig {

    // select()函數返回一個ApiSelectorBuilder實例用來控制哪些接口暴露給Swagger來展示,本例採用指定掃描的包路徑來定義,
    // Swagger會掃描該包下全部Controller定義的API,併產生文檔內容(除了被@ApiIgnore指定的請求)
    @Bean
    public Docket createRestApi() {
        // apiInfo()用來建立該Api的基本信息(這些基本信息會展示在文檔頁面中
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("標題: Spring Boot 項目集成 Swagger 示例文檔")
                .description("描述: 個人博客地址是 https://michael728.github.io")
                .termsOfServiceUrl("https://michael728.github.io/")
                .version("1.0")
                .build();

        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                // select()函數返回一個ApiSelectorBuilder實例
                .select()
                // 決定了暴露哪些接口給 Swagger
                .paths(regex("/api/.*"))
                .build()
                .useDefaultResponseMessages(false)
                .glo
        return docket;
    }
}

說明:segmentfault

  • @Configuration 是告訴 Spring Boot 須要加載這個配置類;
  • @EnableSwagger2 是啓用 Swagger2,沒加的話,就看不到效果了;
  • ApiInfo 對象用來設置一些文檔的版本號、聯繫人郵箱、網站、版權、開源協議等等信息(這些基本信息會展示在文檔頁面中)。並使用 Docket.apiInfo() 方法來設置;
  • Docket 上增長篩選。提供了 apis()paths() 兩個方法幫助咱們在不一樣級別上過濾接口:
    • apis() 這種方式咱們能夠指定包名的方式,讓 Swagger 只去某些包下面掃描;
    • paths() 這種方式能夠經過篩選 API 的 url 來進行篩選;
  • @ConditionalOnExpression("${swagger.enable:true}") 這個註解控制了是否啓用 Swagger,咱們須要在 appplication.properties 中加上 swagger.enable=true

編寫控制器類——Controller 類

咱們先介紹一下在用 Swagger 時的經常使用註解:

  • @API 類的註解,能夠給控制器增長描述和標籤信息。用在請求的類上,表明了這個類是 Swagger 的資源
    • tags:控制器標籤,對該類進行「分類」,參數是個字符串數組,若是配置了多個值,會在多個分類中看到;
    • value:該參數沒什麼意義,在 UI 界面上並不顯示,可不用配置
  • @ApiModel 類註解,對 API 涉及的對象作描述,可用於響應實體類,說明實體做用
    • value Model 展現時的名稱,默認是 實體類的名稱,好比 UserEntity
    • description 實體類的描述

model.jpg

類成員變量的的註解:

  • @ApiModelProperty 用在實體類的屬性上
    • value 屬性字段描述;
    • required 參數是否必選;
    • name 重寫字段名稱;
    • dataType 重寫字段類型;
    • allowEmptyValue 是否容許爲空;
    • allowbleValues 該字段容許的值。當咱們 API 某個參數爲枚舉類型時,使用這個參數就能夠清楚高速 API 使用者能容許傳入的值

方法的註解:

  • @ApiOperation 描述方法的用途,用來展開對接口的描述
    • value 接口簡要描述;
    • notes 接口發佈說明,詳細描述;
  • @ApiImplicitParams 用於描述接口的非對象參數集,通常與 @ApiImplicitParams 組合使用
  • @ApiImplicitParam 描述參數信息
    • value 參數意義的描述
    • name 參數名字;
    • required 默認 false,參數是否必傳
    • dataType 參數數據類型,只做爲標誌說明,並無實際驗證
      • Long
      • String
    • paramType 參數類型,表示參數放在哪裏
      • query,默認值,Query String 的方式傳參,請求參數的獲取:@RequestParam
      • path 路徑參數,請求參數的獲取:@PathVariable
      • header 請求參數的獲取:@RequestHeader
  • @PathVariable 路徑參數,給相似 @GetMappIng("/user/{id}") 參數經過路徑傳入

其餘:

  • @ApiIgnore:用於類或者方法上,屏蔽接口不被顯示在頁面上;
  • @Profile({"dev","test"}):用於配置類上,表示對什麼環境啓用;
  • @ApiParam 不能直接用在方法上,而是用在方法的形參定義中,下文會有示例;

實體類示例:

@Data
@ApiModel(value = "用戶實體")
public class UserEntity {
    public static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "用戶 id")
    private int id;
    @ApiModelProperty(value = "用戶名", required = true)
    private String userName;
    @ApiModelProperty(value = "密碼" )
    private String passWord;
    @ApiModelProperty(value = "性別")
    private UserSexEnum userSex;
    @ApiModelProperty(value = "暱稱" )
    private String nickName;

    public UserEntity(Integer id, String userName, String passWord) {
        this.id = id;
        this.userName = userName;
        this.passWord = passWord;
    }
}

下面是一個控制類的示例:

@RestController
@RequestMapping("/api/v1/")
@Api(tags = {"用戶相關接口"}, value = "用戶模塊")
public class UserController {

    // 模擬數據庫
    public static List<UserEntity> users = new ArrayList<>();

    static {
        UserEntity user1 = new UserEntity(1, "michael", "123");
        UserEntity user2 = new UserEntity(2, "qq", "123");
        UserEntity user3 = new UserEntity(3, "hh", "123");
        users.add(user1);
        users.add(user2);
        users.add(user3);
    }

    @ApiOperation(value = "獲取用戶列表", notes = "獲取所有用戶信息")
    @RequestMapping(value = "/users", method = RequestMethod.GET)
    public List<UserEntity> getUsers() {
        return users;
    }

    @ApiOperation(value = "查詢單用戶", notes = "根據用戶id 查詢其信息")
    @ApiImplicitParam(name = "id", value = "用戶id", paramType = "query", required = true)
    @GetMapping("/user/{id}")
    public UserEntity getUser(@PathParam("id") int id) {
        UserEntity user = users.get(id);
        return user;
    }

    @ApiOperation(value = "存儲用戶信息", notes = "存儲用戶詳細信息")
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public UserEntity saveUser(@ApiParam(value = "用戶信息", required = true)
                               @RequestBody UserEntity user) {
        users.add(user);
        return user;
    }

    @ApiOperation(value = "刪除用戶", notes = "根據用戶id刪除用戶信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "用戶id", required = true, paramType = "path")
    })
    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public int deleteUser(@PathVariable("id") int id) {
        users.remove(id);
        return id;
    }


    @ApiOperation(value = "更新用戶信息", notes = "更新用戶的我的信息")
    @PutMapping("/user/")
    public UserEntity updateUser(@RequestBody UserEntity user) {
        int id = user.getId();
        UserEntity oldUser = users.get(id);
        users.set(id, user);
        return user;
    }
}

啓動

啓動應用,訪問 localhost:8080/swagger-ui.html 能夠訪問到 Swagger UI,能夠點擊 Try it out 按鈕,調用 API:

Jietu20190713-211403-swagger.jpg

頁面上還會有一個 Models 的分類。Swagger UI 會根據咱們在實體上使用的 @ApiModel@ApiModelProperty 註解來自動補充實體以及其屬性的描述和備註。

model.jpg

示例代碼

One More Thing

Web API 的風格

開發 API,先了解一下有哪些 Web API 的風格吧:

  • RPC:RPC 面向過程,RPC 形式的 API 組織形態是類和方法,API 的命名每每是一個動詞,好比 GetUserInfo,CreateUser;
  • REST:REST 面向資源,也是下文將要介紹的一種 API 風格;
  • GraphQL:就是面向數據查詢,採用GraphQL,甚至不須要有任何的接口文檔,在定義了Schema以後,服務端實現Schema,客戶端能夠查看Schema,而後構建出本身須要的查詢請求來得到本身須要的數據

REST

上文提到了 RESTful API 的概念,我以爲,不如趁機瞭解一下。由於在實際的項目中發現,並非每一個 Spring Boot 的開發人員都能意識到開發的 API 要儘可能符合 RESTful 規則的。REST 實際上只是一種設計風格,它並非標準。

術語:

  • Endpoint 終點,能夠理解爲路徑,表示 API 的具體網址。
  • API(Application Programming Interface),應用程序編程接口
  • RESTRepresentational State Transfer 的縮寫。若是一個架構符合 REST 原則,就稱它爲 RESTful 架構。RESTful API 就是 REST 風格的 API
    • Resource:資源,即數據。
    • Representational:某種表現形式,好比用 JSON,XML,JPEG 等;
    • State Transfer:狀態變化。經過 HTTP 動詞實現

在 RESTful 架構中,每一個網址表明一種資源(resource),因此網址中不能有動詞,只能有名詞,並且所用的名詞每每與數據庫的表格名對應。

資源的操做

RESTful 的核心思想就是,客戶端發出的數據操做指令都是"動詞 + 賓語"的結構。好比,GET /articles 這個命令,GET 是動詞,/articles 是賓語。

對於資源的具體操做類型,由 HTTP 動詞表示(括號裏是對應的 SQL 命令):

  • GET(SELECT):從服務器取出資源(一項或多項)。
  • POST(CREATE):在服務器新建一個資源。
  • PUT(UPDATE):在服務器更新資源(客戶端提供改變後的完整資源)。
  • PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。
  • DELETE(DELETE):從服務器刪除資源

還有兩個不經常使用的 HTTP 動詞:

  • HEAD:獲取資源的元數據。
  • OPTIONS:獲取信息,關於資源的哪些屬性是客戶端能夠改變的

知乎上的一個回答,我以爲很精闢:

  • 看 Url 就知道要什麼
  • 看 http method 就知道幹什麼
  • 看 http status code 就知道結果如何

一位答主給出的示例:

GET /rest/api/getDogs --> GET /rest/api/dogs 獲取全部小狗狗
GET /rest/api/addDogs --> POST /rest/api/dogs 添加一個小狗狗
GET /rest/api/editDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一個小狗狗
GET /rest/api/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 刪除一個小狗狗

信息過濾 Filtering

若是記錄數量不少,服務器不可能都將它們返回給用戶。API 應該提供參數,過濾返回結果

  • ?limit=10:指定返回記錄的數量
  • ?offset=10:指定返回記錄的開始位置。
  • ?page=2&per_page=100:指定第幾頁,以及每頁的記錄數

參考

API 介紹

歡迎關注我的公衆號 「iPlayMichael」

iPlayMichael

相關文章
相關標籤/搜索