Java效率工具之Swagger2

LiWenD正在掘金發表於2019-03-03

現代化的研發組織架構中,一個研發團隊基本包括了產品組、後端組、前端組、APP端研發、測試組、UI組等,各個細分組織人員各司其職,共同完成產品的全週期工作。如何進行組織架構內的有效高效溝通就顯得尤其重要。其中,如何構建一份合理高效的介面文件更顯重要。

介面文件橫貫各個端的研發人員,但是由於介面眾多,細節不一,有時候理解起來並不是那麼容易,引起‘內戰’也在所難免, 並且維護也是一大難題。

類似RAP文件管理系統,將介面文件進行線上維護,方便了前端和APP端人員檢視進行對接開發,但是還是存在以下幾點問題:

  • 文件是介面提供方手動匯入的,是靜態文件,沒有提供介面測試功能;
  • 維護的難度不小。

Swagger的出現可以完美解決以上傳統介面管理方式存在的痛點。本文介紹Spring Boot整合Swagger2的流程,連帶填坑。

使用流程如下:

1)引入相應的maven包:

<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>
複製程式碼
2)編寫Swagger2的配置類:

package com.trace.configuration;

import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Value;
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;

/**
* Created by Trace on 2018-05-16.<br/>
* Desc: swagger2配置類
*/
@SuppressWarnings({"unused"})
@Configuration @EnableSwagger2
public class Swagger2Config {
   @Value("${swagger2.enable}") private boolean enable;

   @Bean("UserApis")
   public Docket userApis() {
       return new Docket(DocumentationType.SWAGGER_2)
           .groupName("使用者模組")
           .select()
           .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
           .paths(PathSelectors.regex("/user.*"))
           .build()
           .apiInfo(apiInfo())
           .enable(enable);
   }

   @Bean("CustomApis")
   public Docket customApis() {
       return new Docket(DocumentationType.SWAGGER_2)
           .groupName("客戶模組")
           .select()
           .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
           .paths(PathSelectors.regex("/custom.*"))
           .build()
           .apiInfo(apiInfo())
           .enable(enable);
   }

   private ApiInfo apiInfo() {
       return new ApiInfoBuilder()
           .title("XXXXX系統平臺介面文件")
           .description("提供子模組1/子模組2/子模組3的文件, 更多請關注公眾號: 隨行享閱")
           .termsOfServiceUrl("https://xingtian.github.io/trace.github.io/")
           .version("1.0")
           .build();
   }
}複製程式碼

如上可見:

  • 通過註解@EnableSwagger2開啟swagger2,apiInfo是介面文件的基本說明資訊,包括標題、描述、服務網址、聯絡人、版本等資訊;
  • 在Docket建立中,通過groupName進行分組,paths屬性進行過濾,apis屬性可以設定掃描包,或者通過註解的方式標識;通過enable屬性,可以在application-{profile}.properties檔案中設定相應值,主要用於控制生產環境不生成介面文件。

3)controller層類和方法新增相關注解

package com.trace.controller;

import com.trace.bind.ResultModel;
import com.trace.entity.po.Area;
import com.trace.entity.po.User;
import com.trace.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;

/**
 * Created by Trace on 2017-12-01.<br/>
 * Desc: 使用者管理controller
 */
@SuppressWarnings("unused")
@RestController @RequestMapping("/user")
@Api(tags = "使用者管理")
public class UserController {
    @Resource private UserService userService;

    @GetMapping("/query/{id}")
    @ApiOperation("通過ID查詢")
    @ApiImplicitParam(name = "id", value = "使用者ID", required = true, dataType = "int", paramType = "path")
    public ResultModel<User> findById(@PathVariable int id) {
        User user = userService.findById(id);
        return ResultModel.success("id查詢成功", user);
    }


    @GetMapping("/query/ids")
    @ApiOperation("通過ID列表查詢")
    public ResultModel<List<User>> findByIdIn(int[] ids) {
        List<User> users = userService.findByIdIn(ids);
        return ResultModel.success("in查詢成功", users);
    }


    @GetMapping("/query/user")
    @ApiOperation("通過使用者實體查詢")
    public ResultModel<List<User>> findByUser(User user) {
        List<User> users = userService.findByUser(user);
        return ResultModel.success("通過實體查詢成功", users);
    }


    @GetMapping("/query/all")
    @ApiOperation("查詢所有使用者")
    public ResultModel<List<User>> findAll() {
        List<User> users = userService.findAll();
        return ResultModel.success("全體查詢成功", users);
    }


    @GetMapping("/query/username")
    @ApiOperation("通過使用者名稱稱模糊查詢")
    @ApiImplicitParam(name = "userName", value = "使用者名稱稱")
    public ResultModel<List<User>> findByUserName(String userName) {
        List<User> users = userService.findByUserName(userName);
        return ResultModel.success(users);
    }


    @PostMapping("/insert")
    @ApiOperation("新增預設使用者")
    public ResultModel<Integer> insert() {
        User user = new User();
        user.setUserName("zhongshiwen");
        user.setNickName("zsw");
        user.setRealName("鍾仕文");
        user.setPassword("zsw123456");
        user.setGender("男");
        Area area = new Area();
        area.setLevel((byte) 5);
        user.setArea(area);
        userService.save(user);
        return ResultModel.success("新增使用者成功", user.getId());
    }


    @PutMapping("/update")
    @ApiOperation("更新使用者資訊")
    public ResultModel<Integer> update(User user) {
        int row = userService.update(user);
        return ResultModel.success(row);
    }


    @PutMapping("/update/status")
    @ApiOperation("更新單個使用者狀態")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "使用者ID", required = true),
            @ApiImplicitParam(name = "status", value = "狀態", required = true)
    })
    public ResultModel<User> updateStatus(int id, byte status) {
        User user = userService.updateStatus(id, status);
        return ResultModel.success(user);
    }


    @DeleteMapping("/delete")
    @ApiOperation("刪除單個使用者")
    @ApiImplicitParam(value = "使用者ID", required = true)
    public ResultModel<Integer> delete(int id) {
        return ResultModel.success(userService.delete(id));
    }
}複製程式碼


4)返回物件ResultModel

package com.trace.bind;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;

/**
* Created by Trace on 2017-12-01.<br/>
* Desc:  介面返回結果物件
*/
@SuppressWarnings("unused")
@Getter @Setter @ApiModel(description = "返回結果")
public final class ResultModel<T> {
    @ApiModelProperty("是否成功: true or false")
    private boolean result;
    @ApiModelProperty("描述性原因")
    private String message;
    @ApiModelProperty("業務資料")
    private T data;

    private ResultModel(boolean result, String message, T data) {
        this.result = result;
        this.message = message;
        this.data = data;
    }

    public static<T> ResultModel<T> success(T data) {
        return new ResultModel<>(true, "SUCCESS", data);
    }


    public static<T> ResultModel<T> success(String message, T data) {
        return new ResultModel<>(true, message, data);
    }


    public static ResultModel failure() {
        return new ResultModel<>(false, "FAILURE", null);
    }


    public static ResultModel failure(String message) {
        return new ResultModel<>(false, message, null);
    }
}
複製程式碼


5)ApiModel屬性物件 -- User實體

package com.trace.entity.po;

import com.trace.mapper.base.NotPersistent;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * Created by Trace on 2017-12-01.<br/>
 * Desc: 使用者表tb_user
 */
@SuppressWarnings("unused")
@Data @NoArgsConstructor @AllArgsConstructor
@ApiModel
public class User {
    @ApiModelProperty("使用者ID") private Integer id;
    @ApiModelProperty("賬戶名") private String userName;
    @ApiModelProperty("使用者暱稱") private String nickName;
    @ApiModelProperty("真實姓名") private String realName;
    @ApiModelProperty("身份證號碼") private String identityCard;
    @ApiModelProperty("性別") private String gender;
    @ApiModelProperty("出生日期") private LocalDate birth;
    @ApiModelProperty("手機號碼") private String phone;
    @ApiModelProperty("郵箱") private String email;
    @ApiModelProperty("密碼") private String password;
    @ApiModelProperty("使用者頭像地址") private String logo;
    @ApiModelProperty("賬戶狀態 0:正常; 1:凍結; 2:登出") private Byte status;
    @ApiModelProperty("個性簽名") private String summary;
    @ApiModelProperty("使用者所在區域碼") private String areaCode;
    @ApiModelProperty("註冊時間") private LocalDateTime registerTime;
    @ApiModelProperty("最近登入時間") private LocalDateTime lastLoginTime;

    @NotPersistent @ApiModelProperty(hidden = true)
    private transient Area area; //使用者所在地區

    @NotPersistent @ApiModelProperty(hidden = true)
    private transient List<Role> roles; //使用者角色列表
}
複製程式碼

簡單說下Swagger2幾個重要註解:

@Api:用在請求的類上,表示對類的說明  

  • tags "說明該類的作用,可以在UI介面上看到的註解" 
  • value "該引數沒什麼意義,在UI介面上也看到,所以不需要配置" 

@ApiOperation:用在請求的方法上,說明方法的用途、作用 

  • value="說明方法的用途、作用" 
  • notes="方法的備註說明" 

@ApiImplicitParams:用在請求的方法上,表示一組引數說明 

@ApiImplicitParam:用在@ApiImplicitParams註解中,指定一個請求引數的各個方面

  • value:引數的漢字說明、解釋 
  • required:引數是否必須傳 
  • paramType:引數放在哪個地方 
    1. header --> 請求引數的獲取:@RequestHeader 
    2. query --> 請求引數的獲取:@RequestParam 
    3. path(用於restful介面)--> 請求引數的獲取:@PathVariable 
    4. body(不常用) 
    5. form(不常用) 
  • dataType:引數型別,預設String,其它值dataType="Integer" 
  • defaultValue:引數的預設值 

@ApiResponses:用在請求的方法上,表示一組響應 

@ApiResponse:用在@ApiResponses中,一般用於表達一個錯誤的響應資訊 

  • code:數字,例如400 
  • message:資訊,例如"請求引數沒填好" 
  • response:丟擲異常的類 

@ApiModel:主要有兩種用途:

  • 用於響應類上,表示一個返回響應資料的資訊 
  • 入參實體:使用@RequestBody這樣的場景, 請求引數無法使用@ApiImplicitParam註解進行描述的時候

@ApiModelProperty:用在屬性上,描述響應類的屬性


最終呈現結果:

如前所述:通過maven匯入了swagger-ui:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-swagger-ui</artifactId>
  <version>2.7.0</version>
</dependency>
複製程式碼

那麼,啟動應用後,會自動生成http://{root-path}/swagger-ui.html頁面,訪問後,效果如下所示:

Java效率工具之Swagger2

可以線上測試介面,如通過ID查詢的介面/user/query/{id}

Java效率工具之Swagger2

Java效率工具之Swagger2

全文完!

下一篇:Java效率工具之Lombok


相關文章