In the modern R & D organizational structure, a R & D team basically includes product group, back-end group, front-end group, APP SIDE R & D, test group, UI group, etc., with each subdivision of organization personnel performing their respective duties and working together to complete the full cycle of product work. How to carry out effective and efficient communication within the organization structure is particularly important. Among them, how to build a reasonable and efficient interface document is more important.

The interface document traverses the developers on all sides, but because of the large number of interfaces and different details, sometimes it is not so easy to understand, causing ‘civil war’ is inevitable, and maintenance is also a big problem.

Similar to RAP document management system, the interface documents are maintained online, which facilitates the front end and APP side personnel to view and develop the connection. However, there are still several problems as follows:

  • The document is manually imported by the interface provider. It is a static document and does not provide the interface test function.
  • Maintenance is difficult.

Swagger is the perfect solution to these traditional interface management pain points. This article introduces the process of Integrating Swagger2 with Spring Boot, including the pit filling.

The use process is as follows:

1) Import the corresponding Maven package:

< the 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> The < version > 2.7.0 < / version > < / dependency >Copy the code

2) Write a configuration class for 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/> * Created by Trace on 2018-05-16.<br/> * Created by Trace on 2018-05-16."unused"})
@Configuration @EnableSwagger2
public class Swagger2Config {
   @Value("${swagger2.enable}") private boolean enable;

   @Bean("UserApis")
   public Docket userApis() {
       return new Docket(DocumentationType.SWAGGER_2)
           .groupName("User Module")
           .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("Customer Module")
           .select()
           .apis(RequestHandlerSelectors.withClassAnnotation(Api.class))
           .paths(PathSelectors.regex("/custom.*"))
           .build()
           .apiInfo(apiInfo())
           .enable(enable);
   }

   private ApiInfo apiInfo() {
       return new ApiInfoBuilder()
           .title("XXXXX System Platform Interface Document")
           .description("Provide submodule 1/ submodule 2/ submodule 3 documentation, more please pay attention to the public number: accompanying to read")
           .termsOfServiceUrl("https://xingtian.github.io/trace.github.io/")
           .version("1.0") .build(); }}Copy the code

As can be seen above:

  • Note @enableswagger2 to open swagger2. The apiInfo is the basic description of the interface document, including the title, description, service url, contact, version, and so on.
  • In the Docket creation, groups are grouped by groupName, paths attribute is used to filter, apis attribute can be set to scan packets, or annotated to identify; With the enable attribute, you can set the corresponding value in the application-{profile}. Properties file to prevent the production environment from generating interface documents.

3) Add related annotations to controller layer classes and methods

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/> ** Created by Trace on 2017-12-01."unused")
@RestController @RequestMapping("/user")
@Api(tags = "User Management")
public class UserController {
    @Resource private UserService userService;

    @GetMapping("/query/{id}")
    @ApiOperation("Query by ID")
    @ApiImplicitParam(name = "id", value = "User ID", required = true, dataType = "int", paramType = "path")
    public ResultModel<User> findById(@PathVariable int id) {
        User user = userService.findById(id);
        return ResultModel.success("Id query succeeded", user);
    }


    @GetMapping("/query/ids")
    @ApiOperation("Query by ID list")
    public ResultModel<List<User>> findByIdIn(int[] ids) {
        List<User> users = userService.findByIdIn(ids);
        return ResultModel.success("In query succeeded", users);
    }


    @GetMapping("/query/user")
    @ApiOperation("Query by User Entity")
    public ResultModel<List<User>> findByUser(User user) {
        List<User> users = userService.findByUser(user);
        return ResultModel.success("Query by entity successful", users);
    }


    @GetMapping("/query/all")
    @ApiOperation("Query all users")
    public ResultModel<List<User>> findAll() {
        List<User> users = userService.findAll();
        return ResultModel.success("All search successful", users);
    }


    @GetMapping("/query/username")
    @ApiOperation("Fuzzy query by user name")
    @ApiImplicitParam(name = "userName", value = User Name)
    public ResultModel<List<User>> findByUserName(String userName) {
        List<User> users = userService.findByUserName(userName);
        return ResultModel.success(users);
    }


    @PostMapping("/insert")
    @ApiOperation("Add default user")
    public ResultModel<Integer> insert() {
        User user = new User();
        user.setUserName("zhongshiwen");
        user.setNickName("zsw");
        user.setRealName("Chung Shi-man");
        user.setPassword("zsw123456");
        user.setGender("Male");
        Area area = new Area();
        area.setLevel((byte) 5);
        user.setArea(area);
        userService.save(user);
        return ResultModel.success("New user successfully added", user.getId());
    }


    @PutMapping("/update")
    @ApiOperation("Update user information")
    public ResultModel<Integer> update(User user) {
        int row = userService.update(user);
        return ResultModel.success(row);
    }


    @PutMapping("/update/status")
    @ApiOperation("Update individual user status")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "User ID", required = true),
            @ApiImplicitParam(name = "status", value = "State", required = true)
    })
    public ResultModel<User> updateStatus(int id, byte status) {
        User user = userService.updateStatus(id, status);
        return ResultModel.success(user);
    }


    @DeleteMapping("/delete")
    @ApiOperation("Delete a single user")
    @ApiImplicitParam(value = "User ID", required = true)
    public ResultModel<Integer> delete(int id) {
        returnResultModel.success(userService.delete(id)); }}Copy the code



4) Return object 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: Created by Trace on 2017-12-01."unused")
@Getter @Setter @ApiModel(description = "Return result")
public final class ResultModel<T> {
    @ApiModelProperty("Success or not: True or false")
    private boolean result;
    @ApiModelProperty("Descriptive cause")
    private String message;
    @ApiModelProperty("Business Data")
    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); }}Copy the code



5) ApiModel attribute object — User entity

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: Created by Trace on 2017-12-01.<br/>"unused")
@Data @NoArgsConstructor @AllArgsConstructor
@ApiModel
public class User {
    @ApiModelProperty("User ID") private Integer id;
    @ApiModelProperty("Account name") private String userName;
    @ApiModelProperty("User nickname") private String nickName;
    @ApiModelProperty("Real name") private String realName;
    @ApiModelProperty("Identity Card Number") private String identityCard;
    @ApiModelProperty("Gender") private String gender;
    @ApiModelProperty("Date of Birth") private LocalDate birth;
    @ApiModelProperty("Cell phone number") private String phone;
    @ApiModelProperty("Email") private String email;
    @ApiModelProperty("Password") private String password;
    @ApiModelProperty("User Profile Picture Address") private String logo;
    @ApiModelProperty("Account status 0: Normal. 1: freeze. 2: the logout") private Byte status;
    @ApiModelProperty("Personal signature") private String summary;
    @ApiModelProperty("User area Code") private String areaCode;
    @ApiModelProperty("Registration Time") private LocalDateTime registerTime;
    @ApiModelProperty("Last Login Time") private LocalDateTime lastLoginTime;

    @NotPersistent @ApiModelProperty(hidden = true) private transient Area area; // User area @notpersistent@apiModelProperty (hidden =true) private transient List<Role> roles; // User role list}Copy the code

A few important notes about Swagger2:

@API: Used on the requested class to indicate the description of the class

  • Tags “tags that explain what this class does, annotations that you can see in the UI.”
  • “Value,” this parameter doesn’t make any sense, you see it on the UI, so you don’t need to set it.”

ApiOperation: Used on the requested method, stating the purpose and function of the method

  • Value =” describe the purpose of the method”
  • Notes =” Notes for methods”

ApiImplicitParams: Used on requested methods to represent a set of parameter descriptions

ApiImplicitParam: Used in the @ApiImplICITParams annotation to specify aspects of a request parameter

  • Value: parameter description in Chinese characters
  • Required: Indicates whether the parameter must be passed
  • ParamType: Where does the parameter go
    1. Header –> Get the request parameter: @requestheader
    2. Query –> Obtain the request parameter: @requestparam
    3. Path (for restful interfaces) –> Get the request parameter: @pathVariable
    4. Body (not often used)
    5. Form (not commonly used)
  • DataType: Parameter type, default String, other values dataType=”Integer”
  • DefaultValue: indicates the defaultValue of the parameter

ApiResponses: Used in a request method to indicate a set of responses

@apiResponse: Used in @apiResponses, typically to express an incorrect response message

  • Code: indicates a number, for example, 400
  • 41. message: message, e.g. “Request parameters are not completed”
  • Response: The class that throws the exception

ApiModel: Two main uses:

  • Used on a response class to represent a message that returns response data
  • Incoming parameter entities: Use scenarios such as @requestBody when the request parameters cannot be described using the @ApiImplicitParam annotation

ApiModelProperty: Used on properties to describe the properties of the response class


Final results:

As mentioned earlier: Import swagger-UI via Maven:

< the dependency > < groupId > IO. Springfox < / groupId > < artifactId > springfox swagger - UI < / artifactId > < version > 2.7.0 < / version > </dependency>Copy the code

Then, after starting the application, the http://{root-path}/swagger-ui.html page will be automatically generated. After visiting, the effect is as follows:



You can test the interface online, such as the interface queried by ID /user/query/{ID}





Finish the full!

Next up:Lombok, the Java efficiency tool