javascript
Spring Boot 集成 Swagger 生成 RESTful API 文档
原文鏈接:
- Spring Boot 集成 Swagger 生成 RESTful API 文檔
簡介
Swagger 官網是這么描述它的:The Best APIs are Built with Swagger Tools。
Swagger 是一套基于 OpenAPI 規范構建的開源工具,可以幫助我們設計、構建、記錄以及使用 Rest API。Swagger 主要包含了以下三個部分:
Spring Boot 使得開發 RESTful 服務變得簡單。那么編寫 Spring Boot 接口,為何要用 Swagger 呢?
- 代碼改變,文檔就會改變。只需要少量的注釋,Swagger 就可以根據代碼自動生成 API 文檔。
- Swagger UI 是一份交互式的 API 文檔,可以直接在 Web 界面調用 API。這里有一份 Swagger UI 的 Live Demo,看看官方是怎么寫 RESTful API 的。
添加依賴
pom.xml 引入 Swagger 相關的依賴:
<!-- 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 的版本,因此還需要添加:
<swagger.version>2.9.2</swagger.version>依賴說明:
- 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指定的請求)@Beanpublic 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).gloreturn docket;} }說明:
- @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 實體類的描述
類成員變量的的注解:
- @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:
頁面上還會有一個 Models 的分類。Swagger UI 會根據我們在實體上使用的 @ApiModel 和 @ApiModelProperty 注解來自動補充實體以及其屬性的描述和備注。
示例代碼
- awesome-spring-boot-examples
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),應用程序編程接口
- REST 是 Representational 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:指定第幾頁,以及每頁的記錄數
參考
- CSDN-Spring Boot集成Swagger
- 官宣-Swagger
- IBM-在 Spring Boot 項目中使用 Swagger 文檔
- 蜻蜓HTTP-springboot 集成完整的swagger2
API 介紹
- 阮一峰-RESTful API 設計指南
- 阮一峰-RESTful API 最佳實踐
- segmentfault-Philipp Hauer-[譯]RESTful API 設計最佳實踐 推薦
- RESTful Service API 設計最佳工程實踐和常見問題解決方案 總結的相當好,博客值得閱讀
- 華為云-API設計中關于RPC和REST 兩種風格選擇的個人理解
- 跟著 Github 學習 Restful HTTP API 設計
- 梁桂釗——人人都是 API 設計師:我對 RESTful API、GraphQL、RPC API 的思考 作者分享了一些阿里團隊里做法
- 阿里研究員谷樸:API 設計最佳實踐的思考
- 朱曄的互聯網架構實踐心得S2E5:淺談四種API設計風格(RPC、REST、GraphQL、服務端驅動)
歡迎關注個人公眾號 「iPlayMichael」
轉載于:https://www.cnblogs.com/michael-xiang/p/11216862.html
總結
以上是生活随笔為你收集整理的Spring Boot 集成 Swagger 生成 RESTful API 文档的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对于变态数据搜索的心得
- 下一篇: 问答