Spring boot 多模塊項目 + Swagger 讓你的API可視化
前言
手寫 Api 文檔的幾個痛點:
- 文檔需要更新的時候,需要再次發送一份給前端,也就是文檔更新交流不及時。
- 接口返回結果不明確
- 不能直接在線測試接口,通常需要使用工具,比如postman
- 接口文檔太多,不好管理
為了前后台更好的對接,為了以后交接方便,為了不再長篇大論的手寫 api 文檔,那么就來用Swagger吧(不是打廣告,確實強),它可以輕松的整合到 Spring 中,它既可以減少我們手寫 api 文檔的時間,同時又將說明文檔整合到我們的代碼中,這樣前台看着也方便,后台工作也舒坦。
Swagger 是一個規范和完整的框架,用於生成、描述、調用和可視化 RESTful 風格的 Web 服務。總體目標是使客戶端和文件系統作為服務器以同樣的速度來更新。文件的方法,參數和模型緊密集成到服務器端的代碼,允許API來始終保持同步。Swagger 讓部署管理和使用功能強大的API從未如此簡單(其他好處網上自己搜在這里就不再多說了)。
官網地址: https://swagger.io/
本篇內容:
(1)構建多模塊項目(可選單模塊步驟)
(2)pom.xml 配置加載依賴
(3)Swagger 配置類(Bean)
(4)啟動類配置
(5)創建工具類
(6)User 實例類
(7)定義 restful 接口(Controller 層)
為幫助快速入門上手使用,提供了簡單的增刪改查,使用的參數配置示例
本篇測試環境:
- SpringBoot 2.0.5.RELEASE
- Swagger 2.9.2
- JDK 1.8.191
成功截圖:
第一步:構建多模塊項目(可選步驟)
如果想使用多模塊,請先構建項目(建議):
如果不想使用多模塊(下面模塊請根據自己項目修改)
所有涉及到的文件結構:
第二步:pom.xml 配置加載依賴
Spring boot 項目都會有一些依賴,為了更直觀,只貼必要的部分
為你的 Spring Boot 項目再增加下面兩個依賴:
pom.xml 配置:
<!--可以去下面地址查看最近版本-->
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
第三步:Swagger 配置類(Bean)
注意:
- basePackage 是需要自己配置的,換成自己需要掃描的包,會掃描其所有子包
- 一個就配主模塊,多個就配大包,或分開配
用 @Configuration 注解該類,等價於XML中配置beans;
用 @Bean 標注方法等價於XML中配置bean
不是不可以使用 xml,提倡使用注解,是不是想起點什么?
SwaggerConfig.java 源代碼:
package com.xpwi.main.config;
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;
/**
* 描述:Swagger2 Config Bean
*
* @author Xiao Pengwei
* @since 2019-03-27
*/
@Configuration
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.xpwi"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("SpringBoot使用Swagger構建api文檔")
.description("簡單優雅的 restfun 風格 https://icode.blog.csdn.net")
.termsOfServiceUrl("https://icode.blog.csdn.net")
.version("1.0")
.build();
}
}
第四步:啟動類配置
Application.class 加上注解 @EnableSwagger2 表示開啟Swagger
package com.xpwi.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Date;
/**
* 描述:Spring Boot 多模塊測試項目
* @author Xiao Pengwei
* @since 2019-03-25
*/
@EnableSwagger2
@SpringBootApplication
@RestController
//掃描 main,test 模塊中的下的所有包
//在 pom 加載子模塊依賴才可以掃包
@ComponentScan({"com.xpwi.main","com.xpwi.test","com.xpwi.login"})
public class App {
public static void main(String[] args) {
//啟動 Web 容器
SpringApplication.run(App.class, args);
System.out.println("[啟動成功]"+new Date());
}
}
第五步:創建工具類
用於返回通用數據格式的工具類
CommonResult.java 源代碼:
package com.xpwi.main.util;
/**
* 描述:通用返回類型
* @author Xiao Pengwei
* @since 2019-03-27
*/
public class CommonResult {
private String status;
private Object result;
private Object message;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public Object getMessage() {
return message;
}
public void setMessage(Object message) {
this.message = message;
}
}
第六步:User 實例類
User 模擬對應數據庫字段的實體類
User.java 源代碼:
package com.xpwi.main.entity;
import java.util.Date;
/**
* 描述:User 實體類
* @author Xiao Pengwei
* @since 2019-03-27
*/
public class User {
private String id;
private String username;
private int age;
private Date ctm;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getCtm() {
return ctm;
}
public void setCtm(Date ctm) {
this.ctm = ctm;
}
}
第七步:!定義 restful 接口(Controller 層)
最重要的一步,也是開發中最常用的一步
創建 UserController.java 源代碼:
package com.xpwi.main.controller;
import com.xpwi.main.entity.User;
import com.xpwi.main.util.CommonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 描述:Controller 類
* @author Xiao Pengwei
* @since 2019-03-27
*/
@RestController
@Api(value = "用戶測試模塊")
public class UserController {
// 創建線程安全的Map
static Map<String, User> users = Collections.synchronizedMap(new HashMap<String, User>());
/**
* 根據ID查詢用戶
* @param id
* @return
*/
@ApiOperation(value="獲取用戶詳細信息", notes="根據url的id來獲取用戶詳細信息")
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "String", paramType = "path")
@RequestMapping(value = "user/{id}", method = RequestMethod.GET)
public ResponseEntity<CommonResult> getUserById (@PathVariable(value = "id") String id){
CommonResult commonResult = new CommonResult();
try {
User user = users.get(id);
commonResult.setResult(user);
commonResult.setStatus("ok");
} catch (Exception e) {
commonResult.setResult(e.getClass().getName() + ":" + e.getMessage());
commonResult.setStatus("error");
e.printStackTrace();
}
return ResponseEntity.ok(commonResult);
}
/**
* 查詢用戶列表
* @return
*/
@ApiOperation(value="獲取用戶列表", notes="獲取用戶列表")
@RequestMapping(value = "users", method = RequestMethod.GET)
public ResponseEntity<CommonResult> getUserList (){
CommonResult commonResult = new CommonResult();
try {
List<User> userList = new ArrayList<User>(users.values());
commonResult.setResult(userList);
commonResult.setStatus("ok");
} catch (Exception e) {
commonResult.setResult(e.getClass().getName() + ":" + e.getMessage());
commonResult.setStatus("error");
e.printStackTrace();
}
return ResponseEntity.ok(commonResult);
}
/**
* 添加用戶
* @param user
* @return
*/
@ApiOperation(value="創建用戶", notes="根據User對象創建用戶")
@ApiImplicitParam(name = "user", value = "用戶詳細實體user", required = true, dataType = "User")
@RequestMapping(value = "user", method = RequestMethod.POST)
public ResponseEntity<CommonResult> add (@RequestBody User user){
CommonResult commonResult = new CommonResult();
try {
users.put(user.getId(), user);
commonResult.setResult(user.getId());
commonResult.setStatus("ok");
} catch (Exception e) {
commonResult.setResult(e.getClass().getName() + ":" + e.getMessage());
commonResult.setStatus("error");
e.printStackTrace();
}
return ResponseEntity.ok(commonResult);
}
/**
* 根據id刪除用戶
* @param id
* @return
*/
@ApiOperation(value="刪除用戶", notes="根據url的id來指定刪除用戶")
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "String", paramType = "path")
@RequestMapping(value = "user/{id}", method = RequestMethod.DELETE)
public ResponseEntity<CommonResult> delete (@PathVariable(value = "id") String id){
CommonResult commonResult = new CommonResult();
try {
users.remove(id);
commonResult.setResult(id);
commonResult.setStatus("ok");
} catch (Exception e) {
commonResult.setResult(e.getClass().getName() + ":" + e.getMessage());
commonResult.setStatus("error");
e.printStackTrace();
}
return ResponseEntity.ok(commonResult);
}
/**
* 根據id修改用戶信息
* @param user
* @return
*/
@ApiOperation(value="更新信息", notes="根據url的id來指定更新用戶信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用戶ID", required = true, dataType = "String",paramType = "path"),
@ApiImplicitParam(name = "user", value = "用戶實體user", required = true, dataType = "User")
})
@RequestMapping(value = "user/{id}", method = RequestMethod.PUT)
public ResponseEntity<CommonResult> update (@PathVariable("id") String id, @RequestBody User user){
CommonResult commonResult = new CommonResult();
try {
User user1 = users.get(id);
user1.setUsername(user.getUsername());
user1.setAge(user.getAge());
users.put(id, user1);
commonResult.setResult(user1);
commonResult.setStatus("ok");
} catch (Exception e) {
commonResult.setResult(e.getClass().getName() + ":" + e.getMessage());
commonResult.setStatus("error");
e.printStackTrace();
}
return ResponseEntity.ok(commonResult);
}
@ApiIgnore//使用該注解忽略這個API
@RequestMapping(value = "/hi", method = RequestMethod.GET)
public String jsonTest() {
return " hi you!";
}
}
第八步:啟動 Spring Boot,打開瀏覽器
只需訪問:
http://localhost:8080/swagger-ui.html
swagger-ui.html 是默認的,不用擔心自己沒有創建這個文件,這個就是那個 UI 咯
第九步:常用注解
swagger 提供的常用的注解有:
- @Api:用在類上,說明該類的作用
- @ApiOperation:用在方法上,說明方法的作用,標注在具體請求上,value 和 notes 的作用差不多,都是對請求進行說明;tags 則是對請求進行分類的,比如你有好幾個 controller,分別屬於不同的功能模塊,那這里我們就可以使用 tags 來區分了。
- @ApiImplicitParams:用在方法上包含一組參數說明
- @ApiImplicitParam:用在 @ApiImplicitParams 注解中,指定一個請求參數的各個方面。
- @ApiResponses:用於表示一組響應
- @ApiResponse:用在 @ApiResponses 中,一般用於表達一個錯誤的響應信息
- @ApiModel:描述一個 Model 的信息(這種一般用在post創建的時候,使用
@RequestBody 這樣的場景,請求參數無法使用 @ApiImplicitParam 注解進行描述的時候)表明這是一個被 swagger 框架管理的 model,用於class上 - @ApiModelProperty: 這里顧名思義,描述一個 model 的屬性,就是標注在被標注了 @ApiModel 的class的屬性上,這里的 value 是對字段的描述,example 是取值例子,注意這里的 example很有用,對於前后端開發工程師理解文檔起到了關鍵的作用,因為會在 api 文檔頁面上顯示出這些取值來;這個注解還有一些字段取值,可以自己研究,舉例說一個:position,表明字段在 model 中的順序。
第十步:使用
一般 swagger 需要一下api的權限,需要在對應的模塊進行排除:
http://localhost:8080/swagger-resources/configuration/ui
http://localhost:8080/swagger-resources
http://localhost:8080/api-docs
http://localhost:8080/swagger-ui.html
http://localhost:8080/swagger-resources/configuration/security
如果項目上線並且需要關閉 swagger 接口,可以通過配置權限,或者再 SwaggerConfig 里面
return new Docket 的時候加多一個.enable(false)
技術朋友群
- 一鍵加群
- QQ群:621657432