Best practice guide for integrating Swagger to automatically generate interface documents for SpringBoot project

Recently, Swagger was introduced into the project to support automatic document generation. It was found that many articles only introduced how to access and use. However, for the actual engineering practice, the corresponding best practice scheme is not given. Therefore, I reorganized the relevant contents and documents to sort out a set of best practice guidelines.

Swagger and Springfox

Before the formal introduction, we should first understand the relationship between Swagger and Springfox. I believe that students who have used Swagger in the Spring project know that Swagger functions are integrated through Springfox in the Spring project.

What is Swagger

According to the introduction of the official website, Swagger is a series of tools for Restful API development. The open source parts include:

  • OpenAPI Specification: API specification, which specifies how to describe the API of a system
  • Swagger Codegen: used to generate server-side and client-side code through API specification
  • Swagger Editor: used to write API specifications
  • Swagger UI: used to present API specifications

In short, we can think that swagger mainly formulates and implements an API specification to describe the API interface of the system.

What is Springfox

In short, Springfox is actually a tool to generate API documents by scanning and extracting information from code. It supports various API document formats such as swagger, RAML, jsonapi and so on. Because we focus on swagger here, we can simply understand that Springfox is the middle layer integrating spring MVC and swagger to support automatic scanning of the interface of the Controller layer to generate description data (JSON format) in accordance with swagger API specification.

Through Springfox, you can integrate swagger and SpringBoot projects. There are a lot of integration articles on the Internet, so I won't repeat them here

knife4j introduction

Although SpringBoot can access Swagger directly through Springfox to generate interface documents. However, this approach has two disadvantages:

  1. The native interface document page display is not friendly enough.
  2. It may be cumbersome to use.

Therefore, knife4j is strongly recommended here. Knife4j is a general solution of Swagger interface document service, and its bottom layer is implemented based on Springfox. The two main features are as follows:

  1. Rewriting the front-end UI interface, which is more in line with the usage habits of Chinese people.
  2. It supports fast access and provides many practical enhancements.
  3. The document is friendly, and the access can be completed by directly referring to the documents on Knife4j official website.

The way that users can access at the lowest cost is the best way, and Knife4j does achieve very well. For more details, please refer to the official documents xiaoym.gitee.io/knife4j/doc....

Best practice guide

In fact, SpringBoot's Controller layer method already contains detailed information describing the interface. Of course, because we need to add Chinese explanations. Therefore, the most ideal situation is that the interface document can be automatically generated directly according to the method of the Controller layer. We can write a Chinese description for each parameter at most, that's all.

I think a fully self described interface is the most reasonable and simple. However, the ideal is good, but the reality is that spring fox does not support this very well. Therefore, we need to find a way to solve this problem in practice. Here are some solutions to common problems.

If you feel that your learning efficiency is low and you lack correct guidance, you can join the technology circle with rich resources and strong learning atmosphere to learn and communicate together!
[Java architecture group]
There are many technological giants from the front line in the group, as well as code farmers struggling in small factories or outsourcing companies. We are committed to building an equal and high-quality JAVA Communication circle, which may not make everyone's technology advance by leaps and bounds in the short term, but in the long run, vision, pattern and long-term development direction are the most important.

2.x and 3 How to select the X version

Knife4j's 2 Version x corresponds to 2.0 of Springfox X version, which adopts Swagger2 specification, corresponding to 3 X version uses OpenAPI3 specification. We don't need to know much about these two specifications. We just need to know that OpenAPI3 specification can describe the interface more accurately. For Springfox, 3 Another advantage of version x is that it has better support for Bean Validation and can parse more detailed interface information from the interface itself. Therefore, if conditions permit, it is strongly recommended that 3 X version! I even think if it's 2 X version, the value of access is not great. I always think that it is putting the cart before the horse to write various comments for documents on an interface that has been self described. Since it has been self described, the best solution is always to analyze the framework, rather than write it again manually!!!

Here is a 2 X and 3 Version x, for the interface document generated by the same interface, I believe you will have your own judgment after reading it!

2.x version:

3.x version:

Version 3.x can parse more interface information and describe it more accurately.

The input parameter support of the request body is not good enough

For Query parameters, Springfox 3.0 The X version supports very well. We can write the interface as before. However, for the request body parameters, the existing framework is not good enough. Among them, the most typical is that group verification is not supported. As a result, the fields and constraints of the whole DTO class will be displayed on any interface that uses the DTO receiving parameters. Obviously, this is unreasonable, because the purpose of packet verification is to make the constraints under the specified packet of the interface take effect only for this interface.

Is there any perfect solution to this problem? The answer is no, there is only one choice. If you attach great importance to the accuracy of interface documents, you can only avoid using grouping verification. This means that the request body of each interface should be received with different DTO classes to prevent mutual interference. If you don't pay special attention, it's still written according to group verification, which is simpler to implement. At present, our project is ready to choose the first way.

If you don't know about parameter verification, you can stamp here: Spring Validation best practice and its implementation principle. Parameter verification is not so simple! . For parameter verification, this annotation method is strongly recommended. Because only annotation can truly achieve the self description of the interface.

Access and use examples

Introduce dependency

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.2</version>
</dependency> 

Write interface

Just add an additional Chinese description for each field!

@RestController
@RequestMapping("/api/person")
@Validated
@Api(tags = "Person Administration")
public class PersonController {


    @ApiOperation("Save user")
    @PostMapping("savePerson")
    public Result<PersonVO> savePerson(@RequestBody @Valid SavePersonDTO person) {
        PersonVO personVO = new PersonVO().setAge(10).setEmail("xxxxx").setId(1L).setName("ha-ha");
        return Result.ok(personVO);
    }

    @ApiOperation("Update user")
    @PostMapping("updatePerson")
    public Result<PersonVO> updatePerson(@RequestBody @Valid UpdatePersonDTO person) {
        PersonVO personVO = new PersonVO().setAge(10).setEmail("xxxxx").setId(1L).setName("ha-ha");
        return Result.ok(personVO);
    }


    @ApiOperation("query person")
    @GetMapping("queryPerson")
    public Result<List<PersonVO>> queryPerson(
            @ApiParam("user id") @Min(1000) @Max(10000000) Long id,
            @ApiParam("full name") @NotNull @Size(min = 2, max = 10) String name,
            @ApiParam("Age") @NotNull @Max(200) Integer age,
            @ApiParam("mailbox") @Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$") String email) {
        List<PersonVO> list = new ArrayList<>();
        list.add(new PersonVO().setAge(10).setEmail("xxxxx").setId(1L).setName("ha-ha"));
        return Result.ok(list);
    }

}

@Data
@Accessors(chain = true)
@ApiModel("Save user DTO class")
public class SavePersonDTO {

    @ApiModelProperty("full name")
    @NotNull
    @Size(min = 2, max = 10)
    private String name;

    @ApiModelProperty("Age")
    @NotNull
    @Max(200)
    private Integer age;

    @ApiModelProperty("mailbox")
    @Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
    private String email;
}

@Data
@Accessors(chain = true)
@ApiModel("Update user DTO class")
public class UpdatePersonDTO {


    @ApiModelProperty("user id")
    @NotNull
    private Long id;

    @ApiModelProperty("full name")
    @Size(min = 2, max = 10)
    private String name;

    @ApiModelProperty("Age")
    @Max(200)
    private Integer age;

    @ApiModelProperty("mailbox")
    @Pattern(regexp = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$")
    private String email;
}

@Data
@Accessors(chain = true)
@ApiModel("user VO class")
public class PersonVO {

    @ApiModelProperty("user id")
    private Long id;

    @ApiModelProperty("full name")
    private String name;

    @ApiModelProperty("Age")
    private Integer age;

    @ApiModelProperty("mailbox")
    private String email;
} 

Generally speaking, the production environment does not need to open the interface document function, but only needs to add the following configuration in the production environment:

springfox:
  documentation:
    enabled: false 

Common document notes

The purpose of using document annotation is only to add Chinese instructions, that's all!

annotationexplainExamples
@ApiIt is marked on the Controller to add Chinese description to the Controller@Api(tags = "Person management")
@ApiOperationIt is marked on the method to add Chinese description to the request@ApiOperation("save user")
@ApiParamIt is marked on the method parameter and used to add Chinese description to the request parameter@ApiParam("user id")
@ApiModelIt is marked on the DTO entity class and used to add Chinese description to the request body@ApiModel("save user DTO class")
@ApiModelPropertyIt is marked on the field of DTO entity class and used to add Chinese description to the request body field@ApiModelProperty("name")

Sample screenshot

last

Bald brother will share with you an immortal document of Java high concurrency core programming compiled by front-line development Daniel, which mainly contains knowledge points: multithreading, thread pool, built-in lock, JMM, CAS, JUC, high concurrency design mode, Java asynchronous callback, completable future class, etc.

Document address: A divine article explains java multithreading, lock, JMM, JUC and high concurrency design pattern clearly

Code words are not easy. If you think this article is useful to you, please give me one button three times! Pay attention to the author, there will be more dry goods to share in the future, please continue to pay attention!

Keywords: Java Programming Big Data Spring Boot AI

Added by Bailz on Sat, 29 Jan 2022 05:29:29 +0200