SpringBoot integrates knife4j to implement Swagger interface documentation

Posted by Guffi on Wed, 05 Jan 2022 22:39:12 +0100

Foreword: If you are developing in the background and provide a restful interface to the front end, it is recommended that you use Swagger3 to provide restful interface documentation for automatic generation and online interface debugging. knife4j is a further encapsulation of Swagger, which optimizes the UI interface of the API document and is my most recommended method.

1. Introduction to Swagger

1.1,Swagger

Swagger is a canonical and complete framework for generating, describing, invoking, and visualizing RESTful-style Web services. Swagger has two major functions: automatic generation of interface documents and online debugging of interfaces. Swagger has many open source implementations and tools in different languages and platforms. It has many ways to implement them, is very convenient, and supports a very large number of languages.

(1) Swagger is an open source set of projects with the following main projects:

  • Swagger-tools: Provides tools for integrating and interacting with Swagger. Examples include schema validation, conversion of Swagger 1.2 documents to Swagger 2.0 documents, and so on.

  • Swagger-core: Swagger implementation for Java/Scala. With JAX-RS(Jersey, Resteasy, CXF...), Servlets and Play frameworks are integrated.

  • Swagger-js: Swagger implementation for JavaScript.

  • Swagger-node-express: Swagger module for node. Express web application framework for js.

  • Swagger-ui: An independent collection of HTML, JS, and CSS that dynamically generates elegant documents for Swagger-compatible API s.

  • Swagger-codegen: A template-driven engine that generates client code in various languages by analyzing user Swagger resource claims.

(2) springfox-swagger

Integrating Swagger in Spring uses springfox-swagger, which integrates the use of Spring and Wagger

springfox is a Java implementation of swagger. springfox was predecessor of swagger-springmvc and was used for the integration of springmvc and swagger. It automatically resolves the interfaces exposed by Controller in the Spring container and provides an interface for displaying or calling these API s.

Springfox is actually a tool for generating API documents by scanning code to extract information from code. In the Wagger tutorial, you'll find @Api, @ApiModel, @ApiOperation annotations, which are not actually Springfox's, but Swagger's. The springfox-swagger2 package relies on the swagger-core package, and these annotations are there. However, swagger-core is a package that only supports JAX-RS2 and does not support the commonly used Spring MVC. This is what springfox-swagger does by adapting the above annotations for JAX-RS2 to Spring MVC.

Spring project introduces dependencies:

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${springfox.swagger.version}</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${springfox.swagger.version}</version>
</dependency>

SpingBoot project introduces dependencies:

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
</dependency>

(3) Use of Swagger 3

Swagger2 (based on openApi2) has stopped maintenance for 17 years. Swagger3 (based on openApi3) has been replaced by Swagger3. There are fewer documents used by Swagger3 in China. Baidu has found obsolete use of Swagger2 (stopped maintenance for 17 years and renamed swagger3).

  • Open API: OpenApi is the industry's true api documentation standard maintained by Swagger and listed as an api standard by linux, making it an industry standard.

  • swagger Organization: swagger is an api document maintenance organization that has since become the main definer of Open API standards. The latest version is the 17-year-old version of swagger 3 (Open Api3).

  • The package name of swagger2 is io.swagger, and the package name of swagger3 is io.swagger.core.v3.

Swagger 3 related features:

  • Support for Spring 5, Webflux (only request mapping support, not yet support feature endpoints), Spring Integration

  • Supplementary official auto-assembly of springfox-boot-starter after spring boot can directly depend on a dependency

  • Better specification compatibility with 2.0

  • Support for OpenApi 3.0.3

  • Light dependency on spring-plugin, swagger-core

  • Existing swagger2 annotations will continue to be effective and enrich the open API 3.0 specification

1.2,springfox-swagger-ui

If you use springfox-swagger-ui, the api document access path after starting the project: http://localhost:8080/swagger-ui.html

 1.3,swagger-bootstrap-ui

swagger-bootstrap-ui swagger-bootstrap-ui is an enhanced UI implementation of springfox-swagger, with clearer api documentation structure and easy online debugging

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>${swagger.bootstrap.ui.version}</version>
</dependency>

The url accessed is http://localhost:8080/doc.html

1.4, swagger-bootstrap-ui upgrade Knife4j

Knife4j was named swagger-bootstrap-ui before it was renamed. These are two different styles of UI displays that turn blue into cool black mode. Knife4j looks better than traditional springfox-swagger-ui and swagger-bootstrap-ui. Knife4j is my preferred method.

  • Knifej is written in the style of knife4j-spring-boot-starter and can write configuration items in the configuration file, which provide many enhancements to better integrate spring boot and springcloud.

  • Knifej performs updates and swagger-bootstrap-ui has been stopped for smoother progress;

1.5, SpringDoc (optional)

SpringDoc is also an unofficial Spring Community Maintenance project that helps users integrate swagger3 into Spring. It is also used to help developers generate documents in Spring and can be easily used in SpringBoot. SpringDoc is based on swagger and has done more compatibility with the various frameworks of the Spring series. It has the same usage as Swagger3, has more configurations of its own, is more useful and supports better than Swagger3.

Migrating from spring-fox to springdoc Migrating from spring-fox to springdoc requires dependent changes: pom. Remove the dependencies of springfox or swagger from the XML and add springdoc-openapi-ui.

   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-ui</artifactId>
      <version>1.3.1</version>
   </dependency>

SpringDoc replaces swagger2 with the swagger3 annotation:

This step is optional because the changes are so large that springfox handles compatibility with older swaggers. However, it is not known if it will be incompatible in the future. Here is how to replace swagger 2 with swagger 3 annotations. Note that the package path to modify swagger 3 annotations is io.swagger.v3.oas.annotations.

Swagger 2's annotation naming starts with ease of use and starts with Api. After developing a user's habit of relying on annotations, Swagger 3 standardizes and engineers annotation names:

If you are interested, you can refer to: SpringBoot in conjunction with SpringDo

2. Knife4j implements Swagger3 instead of springfox-boot-starter

Swagger is used to automatically generate API interface documentation and debug it online. Knife4j is a further encapsulation of Swagger, which optimizes the UI interface of API documents. Knife4j, predecessor of swagger-bootstrap-ui, was named knife4j in the hope that she would be as small, lightweight and powerful as a dagger, and that she would be a universal solution for serving Swagger interface documents, not just focusing on the front-end of the UI.


2.1. Importing Knife4j dependencies

  • SpringFox is a support fusion for Swagger's SpringMVC and Knife4 is a further encapsulation of Swagger, which optimizes the interface of api documents

  • Before Knife4j was renamed, its original name was swagger-bootstrap-ui. Knife4j's underlying dependency on springfox eliminates the need to introduce a specific version of springfox separately

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

2.2, Create Knife4jConfig Configuration Class

import com.hs.notice.entity.EmailNotice;
import com.hs.notice.entity.SmsNotice;
import com.hs.notice.entity.WeChatNotice;
import com.fasterxml.classmate.TypeResolver;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * Role: Automatically generate API documentation and online interface debugging tools
 */

@Configuration
//This comment is a Swagger comment provided by the Springfox-swagger framework and must be added
@EnableSwagger2
//Enhanced scan annotations provided by knife4j, Ui provides enhancements such as dynamic parameters, parameter filtering, interface ordering
@EnableKnife4j
public class Knife4jConfig {

    /**
     *     Creating a Docket object is equivalent to an instance of swagger: opening Swagger in a configuration development and testing environment and closing it when production is released
     *
     *     RequestHandlerSelectors,Configure how to scan interfaces
     *     basePackage: Specify the package path to scan
     *     any: Scan All
     *     none: Do not scan all
     *     withClassAnnotation:Scan annotations on classes, such as RestController
     *     withMethodAnnotation:Annotations on scanning methods, such as GetMapping
     *
     * @return
     */
    @Autowired
    TypeResolver typeResolver;
    @Bean
    public Docket createRestApi(Environment environment)
    {
        //Set up the displayed swagger environment information to determine if you are in the environment you have set up and do not open Swagger for safe production
        Profiles profiles=Profiles.of("dev","test");
        boolean flag=environment.acceptsProfiles(profiles);
        //Creating a Docket object is equivalent to an instance of swagger
        return new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .groupName("1.x Edition")
                .apiInfo(apiInfo())
                //The swaggerAPI documentation function is only enabled when the springboot configuration file is in the dev or test environment
                .enable(flag)
                .select()
                // Here you specify the Controller scan package path: Set the interface class to scan, generally the Controller class
                .apis(RequestHandlerSelectors.basePackage("com.hs.notice.controller"))  //This uses package scanning to determine which interfaces to display
//                .apis (RequestHandlerSelectors.withMethodAnnotation (ApiOperation.class)//Use annotations here to determine which interfaces to display
                // Configure which to filter and set the corresponding path to get
                .paths(PathSelectors.any())
                .build()
                //Prevent Swagger Models pages from being scanned because there are no entity classes in the parameters in Controller or the return value is not an entity class
                .additionalModels(typeResolver.resolve(EmailNotice.class))
                .additionalModels(typeResolver.resolve(SmsNotice.class))
                .additionalModels(typeResolver.resolve(WeChatNotice.class));
    }

    ///Configure relevant api information
    private ApiInfo apiInfo()
    {
        return new ApiInfoBuilder()
                .description("API Debugging Documentation")
                //Author Information
                .contact(new Contact("Hogo", "http://ip address: 8086/doc. HTML "," 110@qq.com ")"
                .version("v1.0")
                .title("Message Notification Service API File")
                //Service Url
                .termsOfServiceUrl("")
                .build();
    }

}

As shown in the code above, let Spring load this type of configuration with the @Configuration annotation.

  • @ EnableSwagger2 supports SpringFox support for Swagger 2.
  • DocumentationType.SWAGGER_2 Tell Docketbean that we are using version 2 of the Swagger specification.

  • The apiInfo() is used to create the basic information for the Api, which is displayed on the document page.

  • select() creates a builder that defines which controllers and methods should be included in the generated document.

  • apis() defines the classes (controller and model classes) to be included. We include all of these here, but you can limit them through base packages, class annotations, and so on. SpringFox detects it as a source of document generation. Controller and Model classes. You can easily configure it in the Docket configuration. We can use it. apis (RequestHandlerSelectors.any; to include all classes; of course, we can also shrink to our base package.

  • paths() allows you to define which controller should be included based on the path mapping. We now include all of this, but you can limit it by using regular expressions, and so on. Code above. paths(PathSelectors.any()) represent matching all URL s.

2.3, Create User Entity Class

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(value = "User Entities")
public class User {

    @ApiModelProperty(value = "id")
    private Integer id;

    @ApiModelProperty(value = "User name")
    private  String username;

    @ApiModelProperty(value = "Gender, 0 males, 1 females")
    private Integer sex;
}

2.4, Create UserController interface

package com.example.demo.controller;

import com.example.demo.User;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

@RestController
@Api(tags = "User Interface")//Information describing UserController
public class UserController {
 
    @ApiOperation(value = "Query Users",notes = "according to id Query Users")
    @ApiImplicitParam(paramType = "path",name="id",value = "user id",required = true)
    @GetMapping("/user/query/{id}")
    public String getUserById(@PathVariable Integer id) {
        return "/user/"+id;
    }

    @ApiResponses({
            @ApiResponse(code=200,message="Delete succeeded"),
            @ApiResponse(code=500,message="Delete failed")})
    @ApiOperation(value = "delete user",notes = "according to id delete user")
    @DeleteMapping("/user/delete/{id}")
    public Integer deleteUserById(@PathVariable Integer id) {
        return id;
    }

    @ApiOperation(value = "Add User",notes = "Add a user, pass in user name and gender")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query",name="username",value = "User name",required = true,defaultValue = "Zhang San"),
            @ApiImplicitParam(paramType = "query",name="sex",value = "Gender",required = true,defaultValue = "female")
    })
    @PostMapping("/user")
    public String addUser(@RequestParam String username,@RequestParam String sex){
        return username+","+sex;
    }

    @ApiOperation(value="Modify User",notes = "Modify users based on incoming user information")
    @PutMapping("/user")
    public String updateUser(@RequestBody User user){
        return user.toString();
    }

    @GetMapping("/ignore")
    @ApiIgnore
    public void ignoreMethod(){}

}

2.4. Accessing Swagger documents

Start the project and enter it in the browser http://localhost:8080/doc.html You can see the information of the interface, expand the interface, and you can see all the interface details.

Once expanded, individual requests can be tested. After selecting the interface, click Debug, enter relevant parameters and click Send button. (

The page is simple and refreshing. It is very convenient to export interface documents. Try it now

3. Swagger's Common Notes

4. The following describes the more practical use in enterprise projects

4.1. Ignore interfaces that do not want to generate documents

Some Controller s do not need interfaces to generate API documents and can be ignored by @ApiIgnore

4.2. Development environment opens Swagger, production environment closes

Although swagger is a good thing, it is a security issue that should not be ignored in use. In a dev environment, you can open swagger for front-end or testing, but if your swagger ui is accidentally put into production, it's a terrible thing to do. It's a pot-end thing to remember.

    @Value("${swagger.switch}")
    private boolean swaggerSwitch;

    @Bean
    public Docket api() {
        Docket docket = new Docket(DocumentationType.SWAGGER_2);
        if (swaggerSwitch) {
            docket.enable(true);
        } else {
            docket.enable(false);
        }

        docket.apiInfo(apiInfo()).select().paths(PathSelectors.any()).build();

        return docket;
    }

4.3. model entity class in Swagger UI does not show solution

Mode 1: As long as there is an entity class in the return value in the interface, it will be scanned into swagger

  @PostMapping("/account")
    public Account user(){
        return new Account();
    }

Mode 2: Use the @RequestBody comment in the controller


@ApiOperation(value = Add User, notes = Add New User)
    @PostMapping("/add")
    public Map addUser( @RequestBody Account account){
        return userService.createUser(account);
    }
 

Reference link:

knife4j website

SpringBoot Integration knife4j

swagger2 commentary description (@ApiImplicitParams)

knife4j and some api notes

Summary of SpringBoot project integration knife4j 2.0

SpringBoot integration Swagger3.0

Topics: knife4j