Spring Boot API 接口文檔 Swagger 入門

轉載自 芋道 Spring Boot API 接口文檔 Swagger 入門

摘要: 原創出處 http://www.iocoder.cn/Spring-Boot/Swagger/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!

本文在提供完整代碼示例,可見 https://github.com/YunaiV/SpringBoot-Labs 的 lab-24 目錄。

原創不易,給點個 Star 嘿,一起衝鴨!

1. 概述

目前,大多數系統都採用前後端分離。在享受前後端分離的好處的同時,接口聯調往往成爲團隊效率的瓶頸,甚至產生前後端的矛盾。簡單歸結來說,有幾方面的原因:

  • 問題一,接口設計滯後。 後端團隊往往不喜歡 API 接口設計先行,提前和前端溝通好接口。而在開發階段的中後期,在後端提供 API 接口後,而這些接口和前端的預期有一些偏差,很容易就產生抱怨,特別是項目週期比較緊張的情況下。

  • 問題二,接口不規範。 當團隊裏沒有同意明確的接口規範時,又或者代碼 Review 做的不是很好的情況下,千奇百怪、各式各樣的 API 接口可能就產生了。前端在對接這樣的 API 接口,苦不堪言,在一口 mmp 一嘴 fuck xxx 之中,調完接口。

  • 問題三,接口文檔更新不及時,或者遺忘更新。 因爲後端 API 代碼和 API 接口在兩個地方,我們無法保證提交 API 代碼的同時,及時更新文檔。有的時候,我們甚至會遺忘更新 API 接口。隨着時間的流逝,API 文檔和 API 接口不一致的地方越來越多,前端會對 API 接口的信任度越來越低,然後不知道不覺之中,回到原始時代,直接問後端開發 API 是什麼樣的。

對於問題一問題二,更多是開發流程上的問題,所以不在本文的範圍內。當然話癆的艿艿,還是要給點粗淺的建議,完全攔不住我啊。

  • 接口設計先行。設計完成後,後端和前端進行簡單溝通,看看是否能夠滿足訴求。

  • 統一的接口規範。一定要制定統一的接口規範文檔,即使比較簡陋,也能保證團隊的 API 接口相對統一一致。😈 即使錯,咱也錯的一模一樣,而不是千奇百怪。當然,接口規範是無法覆蓋到所有的場景的,藉助於“接口設計先行”,我們可以提前去 Review 每個接口的設計。

對於問題三,就進入了本文的主角 Swagger 。通過在 API 接口上,添加相應的 Swagger 提供的註解,自動生成 API 文檔。醬紫,API 接口和文檔就在一起了,從此過上了幸福快樂的生活。

FROM 《RESTful 風格的 Web 服務框架 Swagger》

Swagger 是一個規範和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。

總體目標是使客戶端和文件系統作爲服務器以同樣的速度來更新。文件的方法、參數和模型緊密集成到服務器端的代碼,允許 API 來始終保持同步。Swagger 讓部署管理和使用功能強大的 API 從未如此簡單。

預覽圖

2. 快速入門 Swagger

示例代碼對應倉庫:lab-24-apidoc-swagger 。

在本小節,我們來快速入門 Swagger ,可以更加直觀的感受到其提供的便利性。

2.1 引入依賴

在 pom.xml 文件中,引入相關依賴。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-24-apidoc-swagger</artifactId>

    <dependencies>
        <!-- 實現對 Spring MVC 的自動化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 引入 Swagger 依賴 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!-- 引入 Swagger UI 依賴,以實現 API 接口的 UI 界面 -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

    </dependencies>

</project>

具體每個依賴的作用,胖友自己認真看下艿艿添加的所有註釋噢。

2.2 SwaggerConfiguration

因爲 Spring Boot 暫未提供 Swagger 內置的支持,所以我們需要自己定義配置類。

在 cn.iocoder.springboot.lab24.apidoc.config 包路徑下,創建 SwaggerConfiguration 配置類,用於配置 Swagger 。代碼如下:

// SwaggerConfiguration.java

@Configuration
@EnableSwagger2 // 標記項目啓用 Swagger API 接口文檔
public class SwaggerConfiguration {

    @Bean
    public Docket createRestApi() {
        // 創建 Docket 對象
        return new Docket(DocumentationType.SWAGGER_2) // 文檔類型,使用 Swagger2
                .apiInfo(this.apiInfo()) // 設置 API 信息
                // 掃描 Controller 包路徑,獲得 API 接口
                .select()
                .apis(RequestHandlerSelectors.basePackage("cn.iocoder.springboot.lab24.apidoc.controller"))
                .paths(PathSelectors.any())
                // 構建出 Docket 對象
                .build();
    }

    /**
     * 創建 API 信息
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("測試接口文檔示例")
                .description("我是一段描述")
                .version("1.0.0") // 版本號
                .contact(new Contact("芋艿", "http://www.iocoder.cn", "[email protected]")) // 聯繫人
                .build();
    }

}
  • 在類上,添加 @EnableSwagger2 註解, 標記項目啓用 Swagger API 接口文檔。

  • 通過 #createRestApi() 方法,創建 Swagger Docket Bean 。每個屬性的作用,胖友看看艿艿的註釋。大多數情況下,胖友使用這些屬性是足夠的。不過如果想看看其它配置,胖友可以自己去如下兩個類翻翻:

    • Docket.java

    • ApiInfo.java

2.3 Application

創建 Application.java 類,配置 @SpringBootApplication 註解即可。代碼如下:

// Application.java

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

先暫時不啓動項目。等我們添加好 Controller 。

2.4 UserController

在 cn.iocoder.springboot.lab24.apidoc.controller 包路徑下,創建 UserController 類,提供用戶 API 接口。代碼如下:

// UserController.java

@RestController
@RequestMapping("/users")
@Api(tags = "用戶 API 接口")
public class UserController {

    @GetMapping("/list")
    @ApiOperation(value = "查詢用戶列表", notes = "目前僅僅是作爲測試,所以返回用戶全列表")
    public List<UserVO> list() {
        // 查詢列表
        List<UserVO> result = new ArrayList<>();
        result.add(new UserVO().setId(1).setUsername("yudaoyuanma"));
        result.add(new UserVO().setId(2).setUsername("woshiyutou"));
        result.add(new UserVO().setId(3).setUsername("chifanshuijiao"));
        // 返回列表
        return result;
    }

    @GetMapping("/get")
    @ApiOperation("獲得指定用戶編號的用戶")
    @ApiImplicitParam(name = "id", value = "用戶編號", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
    public UserVO get(@RequestParam("id") Integer id) {
        // 查詢並返回用戶
        return new UserVO().setId(id).setUsername(UUID.randomUUID().toString());
    }

    @PostMapping("add")
    @ApiOperation("添加用戶")
    public Integer add(UserAddDTO addDTO) {
        // 插入用戶記錄,返回編號
        Integer returnId = UUID.randomUUID().hashCode();
        // 返回用戶編號
        return returnId;
    }

    @PostMapping("/update")
    @ApiOperation("更新指定用戶編號的用戶")
    public Boolean update(UserUpdateDTO updateDTO) {
        // 更新用戶記錄
        Boolean success = true;
        // 返回更新是否成功
        return success;
    }

    @PostMapping("/delete")
    @ApiOperation(value = "刪除指定用戶編號的用戶")
    @ApiImplicitParam(name = "id", value = "用戶編號", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
    public Boolean delete(@RequestParam("id") Integer id) {
        // 刪除用戶記錄
        Boolean success = false;
        // 返回是否更新成功
        return success;
    }

}
  • 相比我們之前使用 SpringMVC 來說,我們在類和接口上,額外增加了 Swagger 提供的註解。

  • 從使用習慣上,我比較喜歡先添加 SpringMVC 的註解,再添加 Swagger 的註解。

  • 因爲已經使用了 Swagger 的註解,所以類和方法上的註釋,一般可以刪除了,除非有特殊訴求。

  • 其中涉及到的 POJO 類,有 UserAddDTO、UserUpdateDTO、UserVO 。

執行 Application 啓動項目。然後瀏覽器訪問 http://127.0.0.1:8080/swagger-ui.html 地址,就可以看到 Swagger 生成的 API 接口文檔。如下圖所示:

至此,我們已經完成了 Swagger 的快速入門。不過考慮到胖友能夠更好的使用,我們來一個一個註解瞭解。

2.5 註解

在 swagger-annotations 庫中,在 io.swagger.annotations 包路徑下,提供了我們會使用到的所有 Swagger 註解。Swagger 提供的註解還是比較多的,大多數場景下,只需要使用到我們在 「2.4 UserController」 中用到的註解。

2.5.1 @Api

@Api 註解,添加在 Controller 類上,標記它作爲 Swagger 文檔資源。

示例如下:

// UserController.java

@RestController
@RequestMapping("/users")
@Api(tags = "用戶 API 接口")
public class UserController {

    // ... 省略
}

效果如下:

@Api 註解的常用屬性,如下:

  • tags 屬性:用於控制 API 所屬的標籤列表。[] 數組,可以填寫多個。

    • 可以在一個 Controller 上的 @Api 的 tags 屬性,設置多個標籤,那麼這個 Controller 下的 API 接口,就會出現在這兩個標籤中。

    • 如果在多個 Controller 上的 @Api 的 tags 屬性,設置一個標籤,那麼這些 Controller 下的 API 接口,僅會出現在這一個標籤中。

    • 本質上,tags 就是爲了分組 API 接口,和 Controller 本質上是一個目的。所以絕大數場景下,我們只會給一個 Controller 一個唯一的標籤。例如說,UserController 的 tags 設置爲 "用戶 API 接口" 。

@Api 註解的不常用屬性,如下:

  • produces 屬性:請求請求頭的可接受類型( Accept )。如果有多個,使用 , 分隔。

  • consumes 屬性:請求請求頭的提交內容類型( Content-Type )。如果有多個,使用 , 分隔。

  • protocols 屬性:協議,可選值爲 "http""https""ws""wss" 。如果有多個,使用 , 分隔。

  • authorizations 屬性:授權相關的配置,[] 數組,使用 @Authorization 註解。

  • hidden 屬性:是否隱藏,不再 API 接口文檔中顯示。

@Api 註解的廢棄屬性,不建議使用,有 valuedescriptionbasePathposition 。

2.5.2 @ApiOperation

@ApiOperation 註解,添加在 Controller 方法上,標記它是一個 API 操作。

示例如下:

// UserController.java

@GetMapping("/list")
@ApiOperation(value = "查詢用戶列表", notes = "目前僅僅是作爲測試,所以返回用戶全列表")
public List<UserVO> list() {
    // 查詢列表
    List<UserVO> result = new ArrayList<>();
    result.add(new UserVO().setId(1).setUsername("yudaoyuanma"));
    result.add(new UserVO().setId(2).setUsername("woshiyutou"));
    result.add(new UserVO().setId(3).setUsername("chifanshuijiao"));
    // 返回列表
    return result;
}

效果如下:

@ApiOperation 註解的常用屬性,如下:

  • value 屬性:API 操作名。

  • notes 屬性:API 操作的描述。

@ApiOperation 註解的不常用屬性,如下:

  • tags 屬性:和 @API 註解的 tags 屬性一致。

  • nickname 屬性:API 操作接口的唯一標識,主要用於和第三方工具做對接。

  • httpMethod 屬性:請求方法,可選值爲 GETHEADPOSTPUTDELETEOPTIONSPATCH 。因爲 Swagger 會解析 SpringMVC 的註解,所以一般無需填寫。

  • produces 屬性:和 @API 註解的 produces 屬性一致。

  • consumes 屬性:和 @API 註解的 consumes 屬性一致。

  • protocols 屬性:和 @API 註解的 protocols 屬性一致。

  • authorizations 屬性:和 @API 註解的 authorizations 屬性一致。

  • hidden 屬性:和 @API 註解的 hidden 屬性一致。

  • response 屬性:響應結果類型。因爲 Swagger 會解析方法的返回類型,所以一般無需填寫。

  • responseContainer 屬性:響應結果的容器,可選值爲 ListSetMap 。

  • responseReference 屬性:指定對響應類型的引用。這個引用可以是本地,也可以是遠程。並且,當設置了它時,會覆蓋 response 屬性。說人話,就是可以忽略這個屬性,哈哈哈。

  • responseHeaders 屬性:響應頭,[] 數組,使用 @ResponseHeader 註解。

  • code 屬性:響應狀態碼,默認爲 200 。

  • extensions 屬性:拓展屬性,[] 屬性,使用 @Extension 註解。

  • ignoreJsonView 屬性:在解析操作和類型,忽略 JsonView 註釋。主要是爲了向後兼容。

@ApiOperation 註解的廢棄屬性,不建議使用,有 position 。

2.5.3 @ApiImplicitParam

@ApiImplicitParam 註解,添加在 Controller 方法上,聲明每個請求參數的信息。

示例如下:

// UserController.java

@PostMapping("/delete")
@ApiOperation(value = "刪除指定用戶編號的用戶")
@ApiImplicitParam(name = "id", value = "用戶編號", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
public Boolean delete(@RequestParam("id") Integer id) {
    // 刪除用戶記錄
    Boolean success = false;
    // 返回是否更新成功
    return success;
}

效果如下:

@ApiImplicitParam 註解的常用屬性,如下:

  • name 屬性:參數名。

  • value 屬性:參數的簡要說明。

  • required 屬性:是否爲必傳參數。默認爲 false 。

  • dataType 屬性:數據類型,通過字符串 String 定義。

  • dataTypeClass 屬性:數據類型,通過 dataTypeClass 定義。在設置了 dataTypeClass 屬性的情況下,會覆蓋 dataType 屬性。推薦採用這個方式

  • paramType 屬性:參數所在位置的類型。有如下 5 種方式:

    • "path" 值:對應 SpringMVC 的 @PathVariable 註解。

    • 默認值"query" 值:對應 SpringMVC 的 @PathVariable 註解。

    • "body" 值:對應 SpringMVC 的 @RequestBody 註解。

    • "header" 值:對應 SpringMVC 的 @RequestHeader 註解。

    • "form" 值:Form 表單提交,對應 SpringMVC 的 @PathVariable 註解。

    • 😈 絕大多數情況下,使用 "query" 值這個類型即可。

  • example 屬性:參數值的簡單示例。

  • examples 屬性:參數值的複雜示例,使用 @Example 註解。

@ApiImplicitParam 註解的不常用屬性,如下:

  • defaultValue 屬性:默認值。

  • allowableValues 屬性:允許的值。如果要設置多個值,有兩種方式:

    • 數組方式,即 {value1, value2, value3} 。例如說,{1, 2, 3} 。

    • 範圍方式,即 [value1, value2] 或 [value1, value2) 。例如說 [1, 5] 表示 1 到 5 的所有數字。如果有無窮的,可以使用 (-infinity, value2] 或 [value1, infinity) 。

  • allowEmptyValue 屬性:是否允許空值。

  • allowMultiple 屬性:是否允許通過多次傳遞該參數來接受多個值。默認爲 false 。

  • type 屬性:搞不懂具體用途,對應英文註釋爲 Adds the ability to override the detected type 。

  • readOnly 屬性:是否只讀。

  • format 屬性:自定義的格式化。

  • collectionFormat 屬性:針對 Collection 集合的,自定義的格式化。

當我們需要添加在方法上添加多個 @ApiImplicitParam 註解時,可以使用 @ApiImplicitParams 註解中添加多個。示例如下:

@ApiImplicitParams({ // 參數數組
        @ApiImplicitParam(name = "id", value = "用戶編號", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024"), // 參數一
        @ApiImplicitParam(name = "name", value = "暱稱", paramType = "query", dataTypeClass = String.class, required = true, example = "芋道"), // 參數二
})

2.5.4 @ApiModel

@ApiModel 註解,添加在 POJO 類,聲明 POJO 類的信息。而在 Swagger 中,把這種 POJO 類稱爲 Model 類。所以,我們下文就統一這麼稱呼。

示例如下:

// UserVO.java

@ApiModel("用戶 VO")
public class UserVO {

    // ... 省略

}

效果如下:

@ApiModel 註解的常用屬性,如下:

  • value 屬性:Model 名字。

  • description 屬性:Model 描述。

@ApiModel 註解的不常用屬性,如下:

  • parent 屬性:指定該 Model 的父 Class 類,用於繼承父 Class 的 Swagger 信息。

  • subTypes 屬性:定義該 Model 類的子類 Class 們。

  • discriminator 屬性:搞不懂具體用途,對應英文註釋爲 Supports model inheritance and polymorphism.

  • reference 屬性:搞不懂具體用途,對應英文註釋爲 Specifies a reference to the corresponding type definition, overrides any other metadata specified

2.5.5 @ApiModelProperty

@ApiModelProperty 註解,添加在 Model 類的成員變量上,聲明每個成員變量的信息。

示例如下:

// UserVO.java

@ApiModel("用戶 VO")
public class UserVO {

    @ApiModelProperty(value = "用戶編號", required = true, example = "1024")
    private Integer id;
    @ApiModelProperty(value = "賬號", required = true, example = "yudaoyuanma")
    private String username;

    // ... 省略 set/get 方法
}

效果如下:

@ApiModelProperty 註解的常用屬性,如下:

  • value 屬性:屬性的描述。

  • dataType 屬性:和 @ApiImplicitParam 註解的 dataType 屬性一致。不過因爲 @ApiModelProperty 是添加在成員變量上,可以自動獲得成員變量的類型。

  • required 屬性:和 @ApiImplicitParam 註解的 required 屬性一致。

  • example 屬性:@ApiImplicitParam 註解的 example 屬性一致。

@ApiModelProperty 註解的不常用屬性,如下:

  • name 屬性:覆蓋成員變量的名字,使用該屬性進行自定義。

  • allowableValues 屬性:和 @ApiImplicitParam 註解的 allowableValues 屬性一致。

  • position 屬性:成員變量排序位置,默認爲 0 。

  • hidden 屬性:@ApiImplicitParam 註解的 hidden 屬性一致。

  • accessMode 屬性:訪問模式,有 AccessMode.AUTOAccessMode.READ_ONLYAccessMode.READ_WRITE 三種,默認爲 AccessMode.AUTO 。

  • reference 屬性:和 @ApiModel 註解的 reference 屬性一致。

  • allowEmptyValue 屬性:和 @ApiImplicitParam 註解的 allowEmptyValue 屬性一致。

  • extensions 屬性:和 @ApiImplicitParam 註解的 extensions 屬性一致。

@ApiModelProperty 註解的廢棄屬性,不建議使用,有 readOnly 。

2.5.6 @ApiResponse

在大多數情況下,我們並不需要使用 @ApiResponse 註解,因爲我們會類似 UserController#get(id) 方法這個接口,返回一個 Model 即可。所以 @ApiResponse 註解,艿艿就簡單講解,嘿嘿。

@ApiResponse 註解,添加在 Controller 類的方法上,聲明每個響應參數的信息。

@ApiResponse 註解的屬性,基本已經被 @ApiOperation 註解所覆蓋,如下:

  • message 屬性:響應的提示內容。

  • code 屬性:和 @ApiOperation 註解的 code 屬性一致。

  • response 屬性:和 @ApiOperation 註解的 response 屬性一致。

  • reference 屬性:和 @ApiOperation 註解的 responseReference 屬性一致。

  • responseHeaders 屬性:和 @ApiOperation 註解的 responseHeaders 屬性一致。

  • responseContainer 屬性:和 @ApiOperation 註解的 responseContainer 屬性一致。

  • examples 屬性:和 @ApiOperation 註解的 examples 屬性一致。

當我們需要添加在方法上添加多個 @ApiResponse 註解時,可以使用 @ApiResponses 註解中添加多個。

至此,我們已經瞭解完 Swagger 項目中提供的主要註解。如果想要看到更多的 Swagger 的使用示例,可以看看艿艿開源的 onemall 項目。

咳咳咳,整理 Swagger 註解的每個屬性,真的是花費時間。如果有哪個解釋不到位,請一定給艿艿留言,我去優化和調整下,嘻嘻。

2.6 測試接口

在 Swagger 的 UI 界面上,提供了簡單的測試接口的工具。我們僅僅需要點開某個接口,點擊「Try it out」按鈕。如下圖:

然後,點擊「Execute」按鈕,即可執行一次 API 接口的調用。如下圖:

在三個紅圈中,我們可以看到 Swagger 給我們提供了:

  • 提供了 curl 命令,讓我們可以直接在命令行執行。

  • 提供了 Request URL 地址,方便我們在瀏覽器中訪問。

  • 提供了執行結果,我們可以人肉看看,是否符合我們希望的結果。

😈 當然,實際項目開發中,艿艿還是喜歡 Postman 來測試接口,嘿嘿。

3. 更好看的 Swagger UI 界面

示例代碼對應倉庫:lab-24-apidoc-swagger-knife4j 。

springfox-swagger-ui 提供的 UI 界面,基本能夠滿足我們的日常使用,但是距離好用,還是有一段距離。幸福的是,社區有人開源了 swagger-bootstrap-ui 項目,提供更好看且好用的 UI 界面。

具體的演示示例,可以訪問:http://swagger-bootstrap-ui.xiaominfo.com/doc.html 查看。

在 「2. 快速入門 Swagger」 的 lab-24-apidoc-swagger 示例的基礎上,我們複製出 lab-24-apidoc-swagger-knife4j 項目,進行改造。

3.1 修改依賴

在 pom.xml 文件中,修改相關依賴。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>lab-24-apidoc-swagger-knife4j</artifactId>

    <dependencies>
        <!-- 實現對 Spring MVC 的自動化配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- 1. swagger-bootstrap-ui 目前改名爲 knife4j -->
        <!-- 2. 實現 swagger-bootstrap-ui 的自動化配置  -->
        <!-- 3. 因爲 knife4j-spring 已經引入 Swagger 依賴,所以無需重複引入 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring</artifactId>
            <version>1.9.6</version>
        </dependency>
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-ui</artifactId>
            <version>1.9.6</version>
        </dependency>

    </dependencies>

</project>

具體每個依賴的作用,胖友自己認真看下艿艿添加的所有註釋噢。

3.2 界面一覽

直接使用 Application 啓動項目,無需做其它任何的變更,方便的說。

瀏覽器訪問 http://localhost:8080/doc.html 地址,就可以看到 的 Swagger 生成的 API 接口文檔。

😈 注意下,界面上艿艿添加的紅圈和紅字噢。更多功能,胖友自己看 官方文檔 喲。非常推薦生產中,使用它,嘿嘿。

4. 更強大的 YApi

雖然說 Swagger 已經挺強大了,可以很好的完成提供後端 API 接口文檔的功能,但是實際場景下,我們還是會碰到很多問題:

  • Swagger 沒有內置 Mock 功能。在實際的開發中,在後端定義好 API 接口之後,前端會根據 API 接口,進行接口的 Mock ,從而實現前後端的並行開發。

  • 多個項目的 API 接口文檔的整合。隨着微服務的流行,一個產品實際是拆分成多個微服務項目,提供 API 接口。那麼,一個微服務項目,一個接口文檔,肯定會氣死前端。氣死一個前端小哥哥沒事,如果是小姐姐那多可惜啊。

所以,我們需要更加強大的 API 接口管理平臺。目前艿艿團隊採用的解決方案是:

  • 後端開發,還是使用 Swagger 註解,生成 API 接口文檔。

  • 使用 YApi 可視化接口管理平臺,自動調用 Swagger 提供的 v2/api-docs 接口,採集 Swagger 註解生成的 API 接口信息,從而錄入到 YApi 中。

這樣,我們既可以享受到 Swagger 帶給我們編寫 API 接口文檔的便利性與及時性,又能享受到 YApi 的強大功能。

FROM https://github.com/YMFE/yapi

YApi 是高效易用功能強大的 api 管理平臺,旨在爲開發、產品、測試人員提供更優雅的接口管理服務。可以幫助開發者輕鬆創建、發佈、維護 API,YApi 還爲用戶提供了優秀的交互體驗,開發人員只需利用平臺提供的接口數據寫入工具以及簡單的點擊操作就可以實現接口的管理。

  • 基於 Json5 和 Mockjs 定義接口返回數據的結構和文檔,效率提升多倍

  • 扁平化權限設計,即保證了大型企業級項目的管理,又保證了易用性

  • 類似 postman 的接口調試

  • 自動化測試, 支持對 Response 斷言

  • MockServer 除支持普通的隨機 mock 外,還增加了 Mock 期望功能,根據設置的請求過濾規則,返回期望數據

  • 支持 postman, har, swagger 數據導入

  • 免費開源,內網部署,信息再也不怕泄露了

胖友可以訪問 http://yapi.demo.qunar.com/ 地址,快速體驗下 Yapi 的功能。

下面,我們就一起來搭建一個 YApi 平臺,美滋滋。因爲 YApi 基於 NodeJS 語言開發,使用 MongoDB 作爲數據庫存儲接口信息,所以我們需要先安裝 NodeJS 和 MongoDB 。

艿艿:目前手頭上只有 MacOS 和 CentOS 環境,所以如下的步驟,暫支也只保證這兩個環境,抱歉~

如果使用 Windows 或者 Ubuntu 的同學,請辛苦自行解決下。

4.1 安裝 MongoDB

參考 《芋道 MongoDB 極簡入門》 文章,先進行下安裝 MongoDB 數據庫。

安裝完成,記得參考文章,創建一個 yapi 數據庫,後續我們會使用到。

4.2 安裝 NodeJS

如果胖友是 CentOS 環境,使用 yum install nodejs 命令,進行安裝。

如果胖友是 MacOS 環境,使用 brew install node 命令,進行安裝。如果沒有 brew 的胖友,這麼 666 的神器,不趕緊安裝下嘛?!

4.3 安裝 yapi-cli

使用我們提供的 yapi-cli 工具,部署 YApi 平臺是非常容易的。執行 yapi server 啓動可視化部署程序,輸入相應的配置和點擊開始部署,就能完成整個網站的部署。部署完成之後,可按照提示信息,執行 node/{網站路徑/server/app.js} 啓動服務器。在瀏覽器打開指定 url, 點擊登錄輸入您剛纔設置的管理員郵箱,默認密碼爲 ymfe.org 登錄系統(默認密碼可在個人中心修改)。

# 安裝 yapi-cli 工具
$ npm install -g yapi-cli --registry https://registry.npm.taobao.org

# 啓動 YApi 平臺部署工具
$ yapi server
在瀏覽器打開 http://0.0.0.0:9090 訪問。非本地服務器,請將 0.0.0.0 替換成指定的域名或ip

4.4 YApi 平臺部署

在瀏覽器打開 http://127.0.0.1:9090 地址,設置 YApi 平臺部署的信息。如下圖:

點擊「開始部署」按鈕,會彈出“部署日誌”窗口。如下圖:

耐心等待,直到出現日誌如下:

初始化管理員賬號成功,賬號名:"[email protected]",密碼:"ymfe.org"
部署成功,請切換到部署目錄,輸入: "node vendors/server/app.js" 指令啓動服務器, 然後在瀏覽器打開 http://127.0.0.1:3000 訪問

此時,我們可以在命令行執行 ctrl-c 操作,關閉YApi 平臺部署工具。

4.5 YApi 平臺啓動

在命令行中,執行如下命令,啓動 YApi 平臺。

# 進入 yapi 部署路徑
$ cd /Users/yunai/my-yapi/

# 啓動 yapi 平臺
$ node vendors/server/app.js
log: -------------------------------------swaggerSyncUtils constructor-----------------------------------------------
log: 服務已啓動,請打開下面鏈接訪問:
http://127.0.0.1:3000/
log: mongodb load success...

項目啓動完成。如果真正開始使用時,建議使用 pm2 方便服務管理維護。命令如下:

npm install pm2 -g  // 安裝pm2
cd  {項目目錄}
pm2 start "vendors/server/app.js" --name yapi // pm2管理yapi服務
pm2 info yapi // 查看服務信息
pm2 stop yapi // 停止服務
pm2 restart yapi // 重啓服務

這裏,我們可以先略過這個操作,繼續往下看。畢竟,咱現在的重心是先入門。

4.5 創建項目

瀏覽器打開 http://127.0.0.1:3000/ 地址,輸入賬號密碼登陸。

  • 登陸賬號,就是管理員郵箱。例如說,艿艿這裏使用的是 [email protected]

  • 登陸密碼,默認使用 ymfe.org 。

登陸成功後,自動跳轉到主界面,點擊右邊的「添加項目」按鈕,進入「新建項目」的界面(http://127.0.0.1:3000/add-project) 。如下圖:

點擊下方的「創建項目」按鈕,完成項目的創建。創建成功後,我們會自動動跳轉到剛纔創建的項目下。如下圖:

4.6 設置 Swagger 自動同步

點擊「設置」欄目,然後選擇「Swagger自動同步」欄目,設置 Swagger 自動同步信息。如下圖:

友情提示:Swagger 默認會自動暴露 項目地址/v2/api-docs 接口,提供 Swagger 根據註解自動生成的 API 接口信息。胖友可以手動請求下該接口,感受下。

實際上,無論是 Swagger UI 也是基於該接口,獲得 API 接口信息。

點擊「保存」按鈕。成功後,點擊「接口」欄目,就可以看到自動同步到的接口信息。如下圖:

至此,我們已經完成搭建 YApi 平臺,並自動採集 Swagger 提供的 API 接口信息。YApi 的功能非常強大,一定要翻一翻 官方文檔 喲。例如說,數據 Mock、高級 Mock 、自動化測試等等功能,都是非常值得在項目中實踐使用。

666. 彩蛋

那麼,在有了 API 接口文檔之後,如何和前端更好的溝通呢?

一般來說,每一個版本的需求,產品都會提供 Axure 文檔。後端開發在設計完接口之後,可以考慮在每個界面上,標記上使用到的接口的文檔地址。注意,是接口的文檔地址啊!!!例如說,登陸界面需要使用到登陸接口,那麼我們可以把登陸接口對應的文檔地址 http://127.0.0.1:3000/project/14/interface/api/11 標記到這個界面的原型上。

當然,做標記的原則是,需要跟產品協商好可以用來標記的區域,不能影響到他們的工作。例如說:

友情提示:Axure 也是支持 團隊協作 的噢。如果胖友家的產品還沒使用,批評(怒噴)一下他們。

這樣,在原型上標記好接口之後,我們就可以找前端妹子,對着原型,順着接口走一遍流程。如果走的很順暢,說明咱的接口棒棒的。嘿嘿~

一定要記住,工具僅僅是工具,一定要儘早達成前後端的一致。


下面,進入話癆艿艿的碎碎念環節,分享下艿艿在 API 接口文檔的心路歷程。

艿艿最早是在 2010 年的時候,接觸到前後端分離的架構。當時前端使用 ActionScript ,後端使用 Servlet + JDBC ,通過 JSON 數據格式做交互,開發一款 QQ 農場的網頁遊戲。😈 嘿嘿,不要嫌棄 Servlet + JDBC 很搓,當時才學 Java 3 個月左右。那時候吧,一個前端 + 兩個後端,人少,直接 QQ 上發 API 接口的定義。是不是非常遠古時代的做法,嘻嘻。

在 2011 年的時候,開始第一份工作的實習。公司管理後臺前端採用的是 ExtJS ,後端使用 SpringMVC 提供接口。架構還是採用前後端分離,不過前端 JS 代碼還是後端開發來編寫,所以也就不存在 API 接口文檔一說了。這個時候,更多的是自我約束,強制自己先設計好 API 接口,然後順着產品原型走一圈。如果沒問題,就開始編寫後端 API 接口的實現。完成之後,在編寫前端 JS 代碼~

在 2013 年的時候,開始了又一次創業的遨遊。項目的前端是 iOS 和 Android 客戶端,順理成章的還是前後端分離。因爲客戶端分成 iOS 和 Android 客戶端版本,並且還是兩個不同的開發小哥(是的,竟然沒一個是小姐姐),所以艿艿只好提供 API 接口的文檔。這個時候的 API 接口的文檔方案比較土,土豆的土,使用的是 Word 文檔 + SVN 協作。可想而知,大幾十頁的,一點打開的慾望都沒有。😈 更痛苦的是,Word 文檔的內容,是不支持 SVN 比對合並的,這就導致未來的一段時間,我們發展到 10+ 後端開發的時候,瘋狂的衝突。

在 2015 年的時候,差不多是這個點吧,記憶有點模糊了。我們開始使用 Confluence 作爲我們的 Wiki 工具,新的 API 接口文檔自然就被調整到在上面編寫,而老的 API 接口慢慢遷移上來。帶來的好處不言而喻,終於解決多人協作老衝突的問題。同時,Confluence 支持 Template 模板,也比較容易的控制 API 接口的格式和規範。當然,比較大的困擾,還是文頭提到的問題三,經常有同學忘記更新 API 文檔,導致代碼和文檔越來越不一致。

在 2016 年的時候,愛倒騰的艿艿,無意中發現網易提供的 NEI 接口管理平臺。當時從 Confluence 替換成 NEI 的原因,有點不太記得,好像是 NEI 更加結構化,也更加專業。畢竟,Confluence 是一個 Wiki 工具,而不是專爲 API 接口設計的管理平臺。當然,此時問題三還是存在的。

在 2019 年的時候,剛好開始了一個新項目,抱着比較嘗試的心態,使用了 Swagger 來編寫接口文檔,效果其好,主要也是解決了問題三。更舒服的是,相比 NEI 上編寫接口文檔,😈 可以複製粘貼代碼,效率也提升了蠻多。

再後來,我們引入了 YApi 接口管理平臺,形成了我們 Swagger + YApi + Axure 標記的整體方案。大體就是醬紫。深夜 02:16 了,結束今天的嗶嗶,迎接明天的嗶嗶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章