Swagger使用
Swagger有什么用?
swagger是一個流行的API開發框架,這個框架以“開放API聲明”(OpenAPI Specification,OAS)為基礎,
對整個API的開發周期都提供了相應的解決方案,是一個非常龐大的項目(包括設計、編碼和測試,幾乎支持所有語言)。
Swagger 是一個規范和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。
總體目標是使客戶端和文件系統作為服務器以同樣的速度來更新。
文件的方法,參數和模型緊密集成到服務器端的代碼,允許API來始終保持同步。Swagger 讓部署管理和使用功能強大的API從未如此簡單。
springfox大致原理:
springfox的大致原理就是,在項目啟動的過種中,spring上下文在初始化的過程,
框架自動跟據配置加載一些swagger相關的bean到當前的上下文中,並自動掃描系統中可能需要生成api文檔那些類,
並生成相應的信息緩存起來。如果項目MVC控制層用的是springMvc那么會自動掃描所有Controller類,並生成對應的文檔描述數據.
該數據是json格式,通過路徑:項目地址/ v2/api-docs可以訪問到該數據,然后swaggerUI根據這份數據生成相應的文檔描述界面。
因為我們能拿到這份數據,所以我們也可以生成自己的頁面.
SpringBoot 與 Swagger2
由於java的強大的注解功能,我們使用SpringBoot來結合Swagger2,在使用起來非常簡單.
由於Spring的流行,Marty Pitt編寫了一個基於Spring的組件swagger-springmvc,用於將swagger集成到springmvc中來。
第一步: 新建SpringBoot項目,引入依賴.
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.7.0</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.7.0</version> </dependency>
上面兩個依賴的作用:
springfox-swagger2依然是依賴OSA規范文檔,也就是一個描述API的json文件,而這個組件的功能就是幫助我們自動生成這個json文件,
springfox-swagger-ui就是將這個json文件解析出來,用一種更友好的方式呈現出來。
第二步:創建api
/** * @author shianliang * @create 2018-01-05 8:23 **/ @RestController public class UserController { @RequestMapping("/hello",method = RequestMethod.GET) public String hello(){ return "hello"; } }
配置Swagger2
現在Swagger2還不能為我們生成API文檔,因為我們還沒有對它進行配置.
我們需要創建一個配置類,進行如下配置:
/** * @author shianliang * @create 2018-01-04 13:36 **/ @Configuration @EnableSwagger2 public class SwaggerConfig{ @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.itguang.springbootswaggerdemo1.web")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("Spring Boot中使用Swagger2構建RESTful API") .description("rest api 文檔構建利器") .termsOfServiceUrl("http://blog.csdn.net/itguangit") .contact("itguang") .version("1.0") .build(); } }
springfox為我們提供了一個Docket(摘要的意思)類,我們需要把它做成一個Bean注入到spring中,
顯然,我們需要一個配置文件,並通過一種方式(顯然它會是一個注解)告訴程序,這是一個Swagger配置文件。
springfox允許我們將信息組合成一個ApiInfo的類,作為構造參數傳給Docket(當然也可以不構造這個類,而直接使用null,但是你的這個API就太low了)。
搞定
現在我們要做的配置已經能滿足一個生成API文檔的基本要求了,讓我們啟動項目,訪問:http://localhost/swagger-ui.html
會看到如下界面:
這是Swagger-ui 為我們生成的界面.
Swagger2 注解使用
接下來我們就要好好研究下 springfox-swagger2 給我們提供的注解了.
我們新建一個Controller,用來對 User 類進行增刪改查常用操作,
/** * @author shianliang * @create 2018-01-04 13:31 **/ @RestController @RequestMapping(value = "/user", produces = APPLICATION_JSON_VALUE) //配置返回值 application/json @Api(description = "用戶管理") public class HelloController { ArrayList<User> users = new ArrayList<>(); @ApiOperation(value = "獲取用戶列表", notes = "獲取所有用戶信息") @RequestMapping(value = {""}, method = RequestMethod.GET) public List<User> hello() { users.add(new User("邏輯", "luoji")); users.add(new User("葉文傑", "yewenjie")); return users; } }
可以看到我們在Controller上使用了 @Api(description = “用戶管理”) 注解,在方法上使用了 @ApiOperation(value = “獲取用戶列表”, notes = “獲取所有用戶信息”) 注解,
這會產生什么養的效果呢? 我們可以再次訪問下試試看啊:
可以看到我們紅框裱起來的地方發生了改變,並且神奇的是它還自動判斷出了我們的返回類型:
[ { "age": 0, "email": "string", "enabled": true, "id": "string", "password": "string", "username": "string" } ]
但是我們如果想選擇性的忽略某個字段,而不是把User類中的所有字段暴露出去呢?別着急,我們可以使用另一個注解: @ApiModelProperty(hidden = true)
此注解可以作用在字段或者方法上,只要 hidden 屬性為 true ,該字段或者方法就不會被生成api文檔.
如下:
/** * @author shianliang * @create 2017-12-30 14:39 **/ @Data public class User { private String id; private String username; @ApiModelProperty(hidden = true) private String password; private String email; private Integer age; private Boolean enabled; }
我們有意忽略了 password 字段,再次刷新瀏覽器,會看到:
確實 password 字段不見了.
接下來我們在模擬一個創建用戶的api:
@ApiOperation(value = "創建用戶", notes = "根據User對象創建用戶") @RequestMapping(value = "/create", method = RequestMethod.POST) public User postUser(User user) { return user; }
可以看到我們需要客戶端傳給我們一個User對象,用來創建和該用戶,這里我們什么也不做,只是把接受到的User對象返回給客戶端,來表示創建成功.
我們刷新瀏覽器看下:
可以看到請求參數並不是讓我們很滿意啊,第一沒有字段說明,第一有些字段在創建用戶時我們並不需要啊,還是不要着急,我們也有辦法解決:
@ApiModelProperty(hidden = true) private String id; @ApiModelProperty(value = "用戶名") private String username; @ApiModelProperty(value = "密碼") private String password; @ApiModelProperty(value = "郵箱") private String email; @ApiModelProperty(hidden = true) private Integer age; @ApiModelProperty(hidden = true) private Boolean enabled;
我們在User對象的字段上添加 上面的注解: @ApiModelProperty(hidden = true)
和@ApiModelProperty(value = "用戶名")
value屬性指明了該字段的含義(描述 Description),再次刷新瀏覽器試試:
怎么樣,是不是很簡單.
下面我們看看 如何傳遞參數:添加一個方法,根據id獲取用戶信息
@ApiOperation(value = "獲取用戶詳細信息", notes = "根據url的id來獲取用戶詳細信息") @RequestMapping(value = "getUser/{id}", method = RequestMethod.GET) public User getUser( @PathVariable(value = "id") String id) { return new User(id, "itguang", "123456"); }
刷新瀏覽器,看到
我們需要客戶端傳入一個參數 id ,現在我們要給 id 這個參數一個說明(Description),該咋辦呢? 還是不要着急,很簡單像下面這樣即可:
@ApiOperation(value = "獲取用戶詳細信息", notes = "根據url的id來獲取用戶詳細信息") @RequestMapping(value = "getUser/{id}", method = RequestMethod.GET) public User getUser(@ApiParam(value = "用戶id", required = true) //[注意] @ApiParam與 Controller中方法並列使用,也可以省略的 @PathVariable(value = "id") String id) { return new User(id, "itguang", "123456"); }
我們添加了 @ApiParam(value = "用戶id", required = true)
這個注解,需要注意的是,這個注解方法的參數前面,不能直接用在方法上面.
再次刷新瀏覽器:
常用注解說明:
通過上面的了解,我們大概已經會使用Swagger2 了,但我們只介紹了一些簡單常用的注解,下面我們系統的總結一下:
Swagger2 基本使用(重點加粗顯示):
@Api: 描述類/接口的主要用途
@ApiOperation: 描述方法用途
@ApiImplicitParam: 描述方法的參數
@ApiImplicitParams: 描述方法的參數(Multi-Params)
可以在上面 創建用戶的方法上添加 @ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
試試看.
@ApiParam:請求屬性
@ApiIgnore: 忽略某類/方法/參數的文檔
注意與 @ApiModelProperty(hidden = true)
不同, @ApiIgnore
不能用在模型數據上
@ApiIgnore: 忽略某類/方法/參數的文檔
如: @ApiResponse(code = 400, message = "無效的用戶信息")
,注意這只是在 生成的Swagger文檔上有效,不要和實際的客戶端調用搞混了.
通常我們都是統一JSON返回,用不到這個注解
@ApiResponses:響應集配置
@ResponseHeader: 響應頭設置
例如: @ResponseHeader(name=”head1”,description=”response head conf”)
@ApiModelProperty:添加和操作模型屬性的數據
我想看中文的
經過上面的介紹,你已經會使用 Swagger2 了,但是對於有些人來說,看上面的英文表示很難受,有沒有中文的?
有!
根據官方文檔上的提示,在springboot下更換界面和語言還是很簡單的,首先我們需要對 SpringBoot 的資源目錄有個了解:
Spring Boot 默認“約定”從資源目錄的這些子目錄讀取靜態資源:
src/main/resources/META-INF/resources src/main/resources/static (推薦) src/main/resources/public
舉個栗子:現在static目錄下有一張圖片,kumamon.jpg
訪問地址: http://localhost:8080/img/kumamon.jpg
注:若不同靜態目錄含有相同路徑圖片,則按上述優先級,即META-INF/resources目錄優先級最高。
了解了 SpringBoot 的資源目錄 的優先級,我們來看看之前引入的 springfox-swagger-ui 這個包,打開maven依賴找到它:
展開如下所示:
還記得我們之前為什么瀏覽器輸入 http://localhost/swagger-ui.html 就會看到一個Swagger 的頁面嗎,沒錯就是這里啦,
其中 swagger-ui.html就是首頁,
打開看下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Swagger UI</title> <link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-32x32.png" sizes="32x32"/> <link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-16x16.png" sizes="16x16"/> <link href='webjars/springfox-swagger-ui/css/typography.css' media='screen' rel='stylesheet' type='text/css'/> <link href='webjars/springfox-swagger-ui/css/reset.css' media='screen' rel='stylesheet' type='text/css'/> <link href='webjars/springfox-swagger-ui/css/screen.css' media='screen' rel='stylesheet' type='text/css'/> <link href='webjars/springfox-swagger-ui/css/reset.css' media='print' rel='stylesheet' type='text/css'/> <link href='webjars/springfox-swagger-ui/css/print.css' media='print' rel='stylesheet' type='text/css'/> <script src='webjars/springfox-swagger-ui/lib/object-assign-pollyfill.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/jquery-1.8.0.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/jquery.slideto.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/jquery.wiggle.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/jquery.ba-bbq.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/handlebars-4.0.5.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/lodash.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/backbone-min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/swagger-ui.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/highlight.9.1.0.pack.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/highlight.9.1.0.pack_extended.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/jsoneditor.min.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/marked.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lib/swagger-oauth.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/springfox.js' type='text/javascript'></script> </head> <body class="swagger-section"> <div id='header'> <div class="swagger-ui-wrap"> <a id="logo" href="http://swagger.io"><img class="logo__img" alt="swagger" height="30" width="30" src="webjars/springfox-swagger-ui/images/logo_small.png" /><span class="logo__title">swagger</span></a> <form id='api_selector'> <div class='input'> <select id="select_baseUrl" name="select_baseUrl"/> </div> <div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div> <div id='auth_container'></div> <div class='input'><a id="explore" class="header__btn" href="#" data-sw-translate>Explore</a></div> </form> </div> </div> <div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div> <div id="swagger-ui-container" class="swagger-ui-wrap"></div> </body> </html>
看不懂? 好吧,看不懂也沒關系,我們想要漢化該咋辦呢?
我們也不能直接在這里修改源碼啊,還記得我們前面提到的 Spring boot 資源目錄的優先級嗎? 沒錯,我們只需要在記得項目下創建 META-INF 這個資源目錄就行啊,
Spring boot 默認會把我們項目的 src/main/resources/META-INF/resources 覆蓋其它的依賴下的文件.
開始漢化
創建 資源目錄 src/main/resources/META-INF/resources,如下:
swagger-ui.html 的內容如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>itguang</title>
<link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-32x32.png" sizes="32x32"/>
<link rel="icon" type="image/png" href="webjars/springfox-swagger-ui/images/favicon-16x16.png" sizes="16x16"/>
<link href='webjars/springfox-swagger-ui/css/typography.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='webjars/springfox-swagger-ui/css/reset.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='webjars/springfox-swagger-ui/css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='webjars/springfox-swagger-ui/css/reset.css' media='print' rel='stylesheet' type='text/css'/>
<link href='webjars/springfox-swagger-ui/css/print.css' media='print' rel='stylesheet' type='text/css'/>
<script src='webjars/springfox-swagger-ui/lib/object-assign-pollyfill.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/handlebars-4.0.5.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/lodash.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/backbone-min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/swagger-ui.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/highlight.9.1.0.pack.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/highlight.9.1.0.pack_extended.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/jsoneditor.min.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/marked.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/lib/swagger-oauth.js' type='text/javascript'></script>
<script src='webjars/springfox-swagger-ui/springfox.js' type='text/javascript'></script>
<!--國際化操作:選擇中文版 -->
<script src='webjars/springfox-swagger-ui/lang/translator.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lang/zh-cn.js' type='text/javascript'></script>
</head>
<body class="swagger-section">
<div id='header'>
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.io">
<img class="logo__img" alt="swagger" height="30" width="30" src="webjars/springfox-swagger-ui/images/logo_small.png" />
<span class="logo__title">swagger</span></a>
<form id='api_selector'>
<div class='input'>
<select id="select_baseUrl" name="select_baseUrl"></select>
</div>
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl" type="text"/></div>
<div id='auth_container'></div>
<div class='input'><a id="explore" class="header__btn" href="#" data-sw-translate>Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap" data-sw-translate> </div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
</body>
</html>
其實我們只添加了兩行代碼:
<!--國際化操作:選擇中文版 --> <script src='webjars/springfox-swagger-ui/lang/translator.js' type='text/javascript'></script> <script src='webjars/springfox-swagger-ui/lang/zh-cn.js' type='text/javascript'></script>
zh-cn.js 文件內容如下:
'use strict'; /* jshint quotmark: double */ window.SwaggerTranslator.learn({ "Warning: Deprecated":"警告:已過時", "Implementation Notes":"實現備注", "Response Class":"響應類", "Status":"狀態", "Parameters":"參數", "Parameter":"參數", "Value":"值", "Description":"描述", "Parameter Type":"參數類型", "Data Type":"數據類型", "Response Messages":"響應消息", "HTTP Status Code":"HTTP狀態碼", "Reason":"原因", "Response Model":"響應模型", "Request URL":"請求URL", "Request Headers":"請求頭", "Response Body":"響應體", "Response Code":"響應碼", "Response Headers":"響應頭", "Hide Response":"隱藏響應", "Headers":"頭", "Try it out!":"試一下!", "Show/Hide":"顯示/隱藏", "List Operations":"顯示操作", "Expand Operations":"展開操作", "Raw":"原始", "can't parse JSON. Raw result":"無法解析JSON. 原始結果", "Example Value":"示例", "Click to set as parameter value":"點擊設置參數", "Model Schema":"模型架構", "Model":"模型", "apply":"應用", "Username":"用戶名", "Password":"密碼", "Terms of service":"服務條款", "Created by":"創建者", "See more at":"查看更多:", "Contact the developer":"聯系開發者", "api version":"api版本", "Response Content Type":"響應Content Type", "Parameter content type:":"參數類型:", "fetching resource":"正在獲取資源", "fetching resource list":"正在獲取資源列表", "Explore":"瀏覽", "Show Swagger Petstore Example Apis":"顯示 Swagger Petstore 示例 Apis", "Can't read from server. It may not have the appropriate access-control-origin settings.":"無法從服務器讀取。可能沒有正確設置access-control-origin。", "Please specify the protocol for":"請指定協議:", "Can't read swagger JSON from":"無法讀取swagger JSON於", "Finished Loading Resource Information. Rendering Swagger UI":"已加載資源信息。正在渲染Swagger UI", "Unable to read api":"無法讀取api", "from path":"從路徑", "server returned":"服務器返回" });
你也可以自己定義中文名稱啦.
漢化搞定.
到此,swagger的漢化工作已經做完,是不是很簡單,重新啟動項目,訪問 http://localhost/swagger-ui.html 就可以看到文檔已經完全漢化啦:
小結:
好了,關於Swagger2在項目中的使用教程就到這里。
源碼下載:https://github.com/shianliang/springboot-swagger-demo.git