1. 程式人生 > >Spring boot 多模塊項目 + Swagger 讓你的API可視化

Spring boot 多模塊項目 + Swagger 讓你的API可視化

log false 說明 部分 數據庫字段 implicit 分類 ack 用戶id

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

成功截圖:
技術分享圖片
技術分享圖片

第一步:構建多模塊項目(可選步驟)

如果想使用多模塊,請先構建項目(建議):

  • Spring Boot 多模塊結構項目構建與測試(詳細圖文教程)IDEA 版

如果不想使用多模塊(下面模塊請根據自己項目修改)

  • Spring Boot 創建項目(IDEA 版)

所有涉及到的文件結構:
技術分享圖片

第二步: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

Spring boot 多模塊項目 + Swagger 讓你的API可視化