Swagger詳細(xì)了解一下

簡(jiǎn)介

Swagger 是最流行的 API 開發(fā)工具,它遵循 OpenAPI Specification(OpenAPI 規(guī)范,也簡(jiǎn)稱 OAS)。
Swagger 可以貫穿于整個(gè) API 生態(tài),如 API 的設(shè)計(jì)、編寫 API 文檔、測(cè)試和部署。
Swagger 是一種通用的,和編程語言無關(guān)的 API 描述規(guī)范。

應(yīng)用場(chǎng)景

  • 如果你的 RESTful API 接口都開發(fā)完成了,你可以用 Swagger-editor 來編寫 API 文檔( yaml 文件 或 json 文件),然后通過 Swagger-ui 來渲染該文件,以非常美觀的形式將你的 API 文檔,展現(xiàn)給你的團(tuán)隊(duì)或者客戶。
  • 如果你的 RESTful API 還未開始,也可以使用 Swagger ,來設(shè)計(jì)和規(guī)范你的 API,以 Annotation (注解)的方式給你的源代碼添加額外的數(shù)據(jù)。這樣,Swagger 就可以檢測(cè)到這些數(shù)據(jù),自動(dòng)生成對(duì)應(yīng)的 API 文檔。

規(guī)范

Swagger Specification(Swagger 規(guī)范),規(guī)定了如何對(duì) API 的信息進(jìn)行正確描述。
Swagger 規(guī)范,以前稱作 Swagger Specification,現(xiàn)在稱作 OpenAPI Specification(簡(jiǎn)稱 OAS)。
Swagger 規(guī)范本身是與編程語言無關(guān)的,它支持兩種語法風(fēng)格:

  • YAML 語法
  • JSON 語法

這兩種語法風(fēng)格可以相互轉(zhuǎn)換,都可以用來對(duì)我們的 RESTful API 接口的信息進(jìn)行準(zhǔn)確描述,便于人類和機(jī)器閱讀。
在 Swagger 中,用于描述 API 信息的文檔被稱作 Swagger 文檔。Swagger 的規(guī)范主要有兩種:

  • Swagger 2.0
  • OpenAPI 3.0

關(guān)于 Swagger 規(guī)范的詳細(xì)信息,請(qǐng)參考官方文檔

Swagger文檔

Swagger 文檔(文件),指的是符合 Swagger 規(guī)范的文件,用于對(duì) API 的信息進(jìn)行完整地描述。
Swagger 文檔是整個(gè) Swagger 生態(tài)的核心。
Swagger 文檔的類型有兩種:yaml 文件和 json 文件。
yaml 文件用的是 YAML 語法風(fēng)格;json 文件用的是 JSON 語法風(fēng)格。這兩種文件都可以用來描述 API 的信息,且可以相互轉(zhuǎn)換。
簡(jiǎn)單的說,Swagger 文檔就是 API 文檔,只不過 Swagger 文檔是用特定的語法來編寫的。Swagger 文檔本身看起來并不美觀,這時(shí),就需要一個(gè)好的 UI 工具將其渲染一番,這個(gè)工具就是 Swagger-ui。
我們可以用任何編輯器來編寫 Swagger 文檔,但為了方便在編輯的同時(shí),檢測(cè) Swagger 文檔是否符合規(guī)范,就有了 Swagger-editor 編輯器。


在這里插入圖片描述

Swagger工具

Swagger提供了多種工具,幫助解決api的不同的情況下的問題


在這里插入圖片描述

Swagger-editor

【功能】

  • 編寫 Swagger 文檔
  • 實(shí)時(shí)檢測(cè) Swagger 文檔是否符合 Swagger 規(guī)范
  • 調(diào)試 Swagger 文檔里描述的 API 接口
  • 轉(zhuǎn)換 Swagger 文檔(yaml 轉(zhuǎn) json,或 json 轉(zhuǎn) yaml)

【安裝】

  • Web 版本的 Swagger-editor 直接運(yùn)行在公網(wǎng)上,Swagger 已經(jīng)給我們配置好了在線的 Swagger-editor。
  • 也可以選擇本地運(yùn)行 Swagger-editor,需要 Node.js 環(huán)境支持。

本文使用docker部署,下載swagger-editor的容器

docker pull swaggerapi/swagger-editor
docker run -d -p 81:8080 swaggerapi/swagger-editor 
//啟動(dòng),81:8080 將容器的8080端口暴露給localhost的81端口

在瀏覽中輸入:localhost:81,就可以在容器中編輯api文檔

在這里插入圖片描述

【使用說明】
Swagger-editor 分為菜單欄和主體界面兩個(gè)部分。
主體界面分為左右兩欄,左側(cè)是編輯區(qū),右側(cè)是顯示區(qū)。

  • 編輯區(qū)里默認(rèn)有一個(gè) Swagger 文檔的樣例,你可以將其清空,編寫自己的 API 描述。
  • 顯示區(qū)是對(duì)應(yīng)編輯區(qū)中的Swagger 文檔的 UI 渲染情況,也就是說,右側(cè)顯示區(qū)的結(jié)果和使用 Swagger-ui 渲染 Swagger 文檔后的顯示結(jié)果基本一致。

Swagger-editor 的菜單欄包含以下幾個(gè)菜單:

  • File: 用于導(dǎo)入、導(dǎo)出、轉(zhuǎn)換、清空 Swagger 文檔
  • Edit: 用于轉(zhuǎn)換為標(biāo)準(zhǔn)的 YAML 格式文件,比如刪除空白行等
  • Generate Server: 用于構(gòu)建服務(wù)器端 stub
  • Generate Client: 用于構(gòu)建客戶端 SDK

選擇菜單欄【File】Save as YAML,保存為swagger.yaml文件,就是我們所說的swagger文檔。

文檔編輯參考swagger從入門到精通

Swagger-ui

Swagger-ui 是一套 HTML/CSS/JS 框架,用于渲染 Swagger 文檔,以便提供美觀的 API 文檔界面。也就是說,Swagger-ui 是一個(gè) UI 渲染工具。
【安裝】
docker部署,下載swagger-ui的容器

docker pull swaggerapi/swagger-ui

【使用】

  1. 使用上面部署的Swagger-editor,在編輯框中完成文檔編輯后在頁面上上方點(diǎn)擊 File -> Download JSON,將文件下載到本地(/Users/jiangsuyao/Downloads)命名為swagger.json
  2. json文件掛在到容器中
//-e:執(zhí)行容器中/foo/swagger.json
//-v:將/Users/fanfan/Downloads中的swagger.json掛在到 /foo中執(zhí)行
docker run -p 82:8080 -e SWAGGER_JSON=/foo/swagger.json -v /Users/jiangsuyao/Downloads:/foo swaggerapi/swagger-ui

瀏覽器輸入:localhost:82,即可看到與Swagger-editor的顯示區(qū)同樣的內(nèi)容

在這里插入圖片描述

【基于swagger-ui的接口測(cè)試】
1. 選擇接口點(diǎn)擊【try it out】
在這里插入圖片描述

2. 修改“Example Value Model”里面參數(shù),點(diǎn)擊“Execute”發(fā)送請(qǐng)求
在這里插入圖片描述

3. 點(diǎn)擊發(fā)送后會(huì)出現(xiàn)下面視圖,不管發(fā)送成功/失敗。你可以通過下面視圖來查看請(qǐng)求數(shù)據(jù):
在這里插入圖片描述

【springboot集成swagger-ui自動(dòng)生成API文檔】

  1. 添加依賴
<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>
  1. 編寫配置文件
    在application同級(jí)目錄新建swagger2文件,添加swagger2配置類
package com.abel.example;
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.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Swagger2 {
    /**
     * 創(chuàng)建API應(yīng)用
     * apiInfo() 增加API相關(guān)信息
     * 通過select()函數(shù)返回一個(gè)ApiSelectorBuilder實(shí)例,用來控制哪些接口暴露給Swagger來展現(xiàn),
     * 本例采用指定掃描的包路徑來定義指定要建立API的目錄。
     *
     * @return
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.abel.example.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 創(chuàng)建該API的基本信息(這些基本信息會(huì)展現(xiàn)在文檔頁面中)
     * 訪問地址:http://項(xiàng)目實(shí)際地址/swagger-ui.html
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Spring Boot中使用Swagger2構(gòu)建RESTful APIs")
                .description("更多請(qǐng)關(guān)注https://blog.csdn.net/u012373815")
                .termsOfServiceUrl("https://blog.csdn.net/u012373815")
                .contact("abel")
                .version("1.0")
                .build();
    }
}
  1. 在controller上添加注解,自動(dòng)生成API
package com.abel.example.controller;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

import com.abel.example.bean.User;
import io.swagger.annotations.*;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


import com.abel.example.service.UserService;
import com.abel.example.util.CommonUtil;


@Controller
@RequestMapping(value = "/users")
@Api(value = "用戶的增刪改查")
public class UserController {

    @Autowired
    private UserService userService;


    /**
     * 查詢所有的用戶
     * api :localhost:8099/users
     * @return
     */
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "獲取用戶列表,目前沒有分頁")
    public ResponseEntity<Object> findAll() {
        return new ResponseEntity<>(userService.listUsers(), HttpStatus.OK);
    }

    /**
     * 通過id 查找用戶
     * api :localhost:8099/users/1
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    @ResponseBody
    @ApiOperation(value = "通過id獲取用戶信息", notes="返回用戶信息")
    public ResponseEntity<Object> getUserById(@PathVariable Integer id) {
        return new ResponseEntity<>(userService.getUserById(Long.valueOf(id)), HttpStatus.OK);
    }


    /**
     * 通過spring data jpa 調(diào)用方法
     * api :localhost:8099/users/byname?username=xxx
     * 通過用戶名查找用戶
     * @param request
     * @return
     */
    @RequestMapping(value = "/byname", method = RequestMethod.GET)
    @ResponseBody
    @ApiImplicitParam(paramType = "query",name= "username" ,value = "用戶名",dataType = "string")
    @ApiOperation(value = "通過用戶名獲取用戶信息", notes="返回用戶信息")
    public ResponseEntity<Object> getUserByUserName(HttpServletRequest request) {
        Map<String, Object> map = CommonUtil.getParameterMap(request);
        String username = (String) map.get("username");
        return new ResponseEntity<>(userService.getUserByUserName(username), HttpStatus.OK);
    }

    /**
     * 通過spring data jpa 調(diào)用方法
     * api :localhost:8099/users/byUserNameContain?username=xxx
     * 通過用戶名模糊查詢
     * @param request
     * @return
     */
    @RequestMapping(value = "/byUserNameContain", method = RequestMethod.GET)
    @ResponseBody
    @ApiImplicitParam(paramType = "query",name= "username" ,value = "用戶名",dataType = "string")
    @ApiOperation(value = "通過用戶名模糊搜索用戶信息", notes="返回用戶信息")
    public ResponseEntity<Object> getUsers(HttpServletRequest request) {
        Map<String, Object> map = CommonUtil.getParameterMap(request);
        String username = (String) map.get("username");
        return new ResponseEntity<>(userService.getByUsernameContaining(username), HttpStatus.OK);
    }


    /**
     * 添加用戶啊
     * api :localhost:8099/users
     *
     * @param user
     * @return
     */
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    @ApiModelProperty(value="user",notes = "用戶信息的json串")
    @ApiOperation(value = "新增用戶", notes="返回新增的用戶信息")
    public ResponseEntity<Object> saveUser(@RequestBody User user) {
        return new ResponseEntity<>(userService.saveUser(user), HttpStatus.OK);
    }

    /**
     * 修改用戶信息
     * api :localhost:8099/users
     * @param user
     * @return
     */
    @RequestMapping(method = RequestMethod.PUT)
    @ResponseBody
    @ApiModelProperty(value="user",notes = "修改后用戶信息的json串")
    @ApiOperation(value = "新增用戶", notes="返回新增的用戶信息")
    public ResponseEntity<Object> updateUser(@RequestBody User user) {
        return new ResponseEntity<>(userService.updateUser(user), HttpStatus.OK);
    }

    /**
     * 通過ID刪除用戶
     * api :localhost:8099/users/2
     * @param id
     * @return
     */
    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
    @ResponseBody
    @ApiOperation(value = "通過id刪除用戶信息", notes="返回刪除狀態(tài)1 成功 0 失敗")
    public ResponseEntity<Object> deleteUser(@PathVariable Integer id) {
        return new ResponseEntity<>(userService.removeUser(id.longValue()), HttpStatus.OK);
    }
}

注解說明

  • @Api:用在類上,說明該類的作用。
  • @ApiOperation:注解來給API增加方法說明。
  • @ApiImplicitParams : 用在方法上包含一組參數(shù)說明。
  • @ApiImplicitParam:用來注解來給方法入?yún)⒃黾诱f明。
  • @ApiResponses:用于表示一組響應(yīng)
  • @ApiResponse:用在@ApiResponses中,一般用于表達(dá)一個(gè)錯(cuò)誤的響應(yīng)信息
  • @ApiModel:描述一個(gè)Model的信息(一般用在請(qǐng)求參數(shù)無法使用@ApiImplicitParam注解進(jìn)行描述的時(shí)候)
  • @ApiModelProperty:描述一個(gè)model的屬性

其中
@ApiResponse參數(shù):

  • code:數(shù)字,如400
  • message:信息,如“參數(shù)填寫錯(cuò)誤”
  • response:拋出異常的類
    @ApiImplicitParam參數(shù):
  • paramTpye:指定參數(shù)放在哪些地方(header/query/path/body/form)
  • name:參數(shù)名
  • dataTpye:參數(shù)類型
  • required:是否必輸(true/false)
  • value:說明參數(shù)的意思
  • defaultValue:參數(shù)默認(rèn)值
  1. 下載Swagger UI組件
    去官網(wǎng)下載Zip包,或者在github上下載也可以,需要將dist文件夾下的所有文件的復(fù)制到webapp目錄下

原理就是在系統(tǒng)加載的時(shí)候,Swagger配置類去掃描所有添加注釋的接口,并且儲(chǔ)存起來通過下面地址進(jìn)行訪問,返回JSON數(shù)據(jù),在前端界面顯示出來。
啟動(dòng)項(xiàng)目后,訪問http://localhost:8099/swagger-ui.html,顯示如下:

在這里插入圖片描述

Swagger-Codegen

Swagger Codegen是一個(gè)開源的代碼生成器,根據(jù)Swagger定義的RESTful API可以自動(dòng)建立服務(wù)端和客戶端的連接。Swagger Codegen的源碼可以在Github上找到。
GitHub:https://github.com/swagger-api/swagger-codegen
【安裝】
首先機(jī)器上需要有jdk,然后只要下載一個(gè)cli的文件就可以了

//下載
# wget https://oss.sonatype.org/content/repositories/releases/io/swagger/swagger-codegen-cli/2.2.1/swagger-codegen-cli-2.2.1.jar
//下載之后運(yùn)行,返回結(jié)果可查看其支持的語言
# java -jar swagger-codegen-cli-2.2.1.jar
Available languages: [android, aspnet5, async-scala, cwiki, csharp, cpprest, dart, flash, python-flask, go, groovy, java, jaxrs, jaxrs-cxf, jaxrs-resteasy, jaxrs-spec, inflector, javascript, javascript-closure-angular, jmeter, nancyfx, nodejs-server, objc, perl, php, python, qt5cpp, ruby, scala, scalatra, silex-PHP, sinatra, rails5, slim, spring, dynamic-html, html, html2, swagger, swagger-yaml, swift, tizen, typescript-angular2, typescript-angular, typescript-node, typescript-fetch, akka-scala, CsharpDotNet2, clojure, haskell, lumen, go-server]
//查看支持某個(gè)語言的具體使用幫助,比如java
# java -jar swagger-codegen-cli-2.2.1.jar config-help -l java

【使用】
利用swagger-codegen根據(jù)服務(wù)生成客戶端代碼

//http://petstore.swagger.io/v2/swagger.json是官方的一個(gè)例子,我們可以改成自己的服務(wù)
# java -jar swagger-codegen-cli-2.2.1.jar generate -i http://petstore.swagger.io/v2/swagger.json -l java -o samples/client/pestore/java

在上面這段代碼里,使用了三個(gè)參數(shù),分別是-i和-l和-o。

  • -i,指定swagger描述文件的路徑,url地址或路徑文件;該參數(shù)為必須

  • -l,指定生成客戶端代碼的語言,該參數(shù)為必須

  • -o,指定生成文件的位置(默認(rèn)當(dāng)前目錄)

除了可以指定上面三個(gè)參數(shù),還有一些常用的:

  • -c ,json格式的配置文件的路徑;文件為json格式,支持的配置項(xiàng)因語言的不同而不同

  • -a, 當(dāng)獲取遠(yuǎn)程swagger定義時(shí),添加授權(quán)頭信息;URL-encoded格式化的name,逗號(hào)隔開的多個(gè)值

  • --api-package, 指定生成的api類的包名

  • --artifact-id ,指定pom.xml的artifactId的值

  • --artifact-version ,指定pom.xml的artifact的版本

  • --group-id, 指定pom.xml的groupId的值

  • --model-package, 指定生成的model類的包名

  • -s ,指定該參數(shù)表示不覆蓋已經(jīng)存在的文件

  • -t ,指定模版文件所在目錄
    生成好的客戶端代碼:


    在這里插入圖片描述

參考文檔:
https://blog.csdn.net/u012373815/article/details/82685962
https://www.cnblogs.com/shamo89/p/7680771.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容