Spring boot integrates knife4j and says goodbye to handwritten interface documents

Posted by Xu Wei Jie on Mon, 20 Dec 2021 12:53:49 +0100

About knife4j

Knife4j's predecessor is swagger bootstrap ui, which is a pure swagger ui UI ui skin project

At the beginning, the original intention of the project was to write an enhanced version of swagger's front-end Ui. However, with the development of the project, in the face of more and more personalized requirements, we had to write back-end Java code to meet new requirements. In 1.8.1 of swagger bootstrap Ui 5~1.9. Between versions 6, the back-end Java code and Ui are mixed in a jar package for developers to use Although this method is very convenient for integrating swagger and only needs to introduce jar packages, it seems a little bloated under the microservice architecture.

Therefore, the project is officially renamed knife4j. The name knife4j hopes that it can be as small, lightweight and powerful as a dagger. The renaming also hopes to make it a universal solution for Swagger interface document service, not only focusing on the front end Ui

All features of swagger bootstrap UI will be concentrated in the knife4j spring UI package, and more personalized needs of developers will be met in the future

The main change is that the relevant class package path of the project is changed to com github. xiaoymin. Knife4j prefix. When developers use enhanced annotations, they need to replace the package path

The back-end Java code and UI package are separated into jar packages of multiple modules to facilitate the use of enhanced document annotations under the current microservice architecture (using the SpringCloud microservice project, you only need to integrate the UI jar package at the gateway layer, so separate the front and back-end)

Knife4j follows the version number of swagger bootstrap UI, and the first version is from 1.9 6. Please refer to the document (excerpted from knife4j official introduction) for the use method.

Introduce knife4j

The basic versions of knife4j are as follows

editionexplain
1.9.6Blue skin style, began to change its name and add more back-end modules
2.0~2.0.5Ui rewrite, the spring fox Framework version that the underlying dependency is 2.9 two
2.0.6~2.10.2 spring fox Framework version upgrade 5. The OpenAPI specification is v2
3.0~Upgrade the bottom layer to 3.0.0 depending on the version of spring fox framework 3. The OpenAPI specification is v3

We introduced 3.0 3. Due to 3 X has only released one version, and there may be some problems with stability. If you want to be the most stable, you are recommended to use 2 x. Because I'm just a demo here, and I like the new version, I use 3.0 3. Help you guess the pit in advance.

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

be careful

  • knife4j has introduced spring fox, so there is no need to introduce it again when using it
    Spring fox, otherwise it may cause version conflict. If you aggregate in the gateway, you must disable the enhancement of knife4j.
  • Use knife4j2 0.6 and above, Spring Boot version must be greater than or equal to 2.2 x

Create Swagger configuration dependency

package com.ymy.notes.config.kinfe4j;

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.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Knife4jConfiguration {

    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        String groupName="3.X edition";
        Docket docket=new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("This is knife4j API ")
                        .description("# The input parameters, output parameters and other information of all interfaces of the server are recorded here ")
                        .termsOfServiceUrl("http://yaomaoyang.com")
                        .contact(new Contact("Inverse meteor","http://yaomaoyang.com","361426201@qq.com"))
                        .version("3.0")
                        .build())
                //Group name
                .groupName(groupName)
                .select()
                //The Controller scan package path is specified here
                .apis(RequestHandlerSelectors.basePackage("com.ymy.notes.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

}

One thing to note here is that if you use 2 x. Then you need to replace @ EnableSwagger2 with @ EnableSwagger2WebMvc, because @ EnableSwagger2 is in 3 X, and set @ EnableSwagger2WebMvc as not recommended.

Configuration item name and port information

server:
  port: 8818
spring:
  application:
    name: notes

Create a simple RESTful interface

package com.ymy.notes.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/test")
@Api(tags = "test swagger")
public class Knife4jTestController {

    @GetMapping(value = "/hello")
    @ApiImplicitParam(name = "name",value = "full name",required = true)
    @ApiOperation("Test interface")
    public String test(@RequestParam("name") String name){
        return "hello "+name+", I am  meimei han";
    }

}

Start project

If you throw it when starting the project: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException

Don't panic. It's because your springboot version is too high. It should be 2.6 x. Because the path matching used by spring fox is based on AntPathMatcher, spring boot 2.6 X uses the PathPatternMatcher, so change the path matching rule of MVC to AntPathMatcher, and add the following parameters to the configuration file (if there is no error, you can skip this step)

spring:
  mvc:
    pathmatch:
      # The path matching used by spring fox is based on AntPathMatcher, while spring boot 2.6 X uses a PathPatternMatcher
      # Therefore, this parameter needs to be configured
      matching-strategy: ant_path_matcher

After successful startup, access in the browser: http://127.0.0.1:8818/doc.html (ip + port + / doc.html).
If you see the following screen, it indicates that knife4j has been configured successfully.



So far, knife4j has been running perfectly. The back-end personnel no longer need to use postman during self-test, nor do they need to write interface documents for the front-end separately. All of a sudden, they increase their fishing time and enjoy themselves.

knife4j enhancements

What are the enhancements to knife4j? What we saw earlier is only the most basic use of knife4j. Knife4j still has many powerful functions that have not been shown, such as i18n internationalization, interface adding responsibilities, custom documents, access permission control, interface sorting, offline documents everywhere, filtering request parameters, etc. These are all enhancements of knife4j, How to turn on the enhancement of knife4j?

Knife4j from 2.0 Starting from version 6, some personalized configurations in the Ui interface will be stripped. Developers can configure them on the back end, and the knife4j spring boot strater component provided will be loaded automatically. Developers can determine the functions to be enabled in the configuration file.

The complete parameters of knife4j in springboot are as follows:

knife4j:
  enable: true
  documents:
    -
      group: 2.X edition
      name: Interface signature
      locations: classpath:sign/*
  setting:
    language: zh-CN
    enableSwaggerModels: true
    enableDocumentManage: true
    swaggerModelName: Entity class list
    enableVersion: false
    enableReloadCacheParameter: false
    enableAfterScript: true
    enableFilterMultipartApiMethodType: POST
    enableFilterMultipartApis: false
    enableRequestCache: true
    enableHost: false
    enableHostText: 192.168.0.193:8000
    enableHomeCustom: true
    homeCustomLocation: classpath:markdown/home.md
    enableSearch: false
    enableFooter: false
    enableFooterCustom: true
    footerCustomContent: Apache License 2.0 | Copyright  2019-[Zhejiang Bayi kitchen knife Co., Ltd](https://gitee.com/xiaoym/knife4j)
    enableDynamicParameter: false
    enableDebug: true
    enableOpenApi: false
    enableGroup: true
  cors: false
  production: false
  basic:
    enable: false
    username: test
    password: 12313

The enhancement function of knife4j needs to be turned on. It is turned off by default. It is also very simple to turn on. In previous versions, developers need to manually use @ EnableKnife4j in the configuration file to use the enhancement. Since 2.0 After version 6, you only need to configure knife4j Enable = true to stop using annotations
Note: to use the enhancements provided by Knife4j, Knife4j Enable = true must be on. This parameter needs to be set, including all the enhancements explained later.

Let me introduce what the above attribute values mean

attributeDefault valueexplain
knife4j.enablefalseEnable Knife4j enhanced mode
knife4j.corsfalseWhether to enable a default cross domain configuration, which is used in conjunction with a custom Host
knife4j.productionfalseWhether to open the production environment protection strategy. Refer to the document for details
knife4j.basic Provide BasicHttp verification for resources provided by Knife4j to protect documents
knife4j.basic.enablefalseTurn off BasicHttp function
knife4j.basic.username basic user name
knife4j.basic.password basic password
knife4j.documents Custom document collection. This property is an array
knife4j.documents.group Group
knife4j.documents.name Similar to the tag in the interface, for the grouping of custom documents
knife4j.documents.locations The markdown file path can be a folder (classpath:markdowns / *) or a single file (classpath:md/sign.md)
knife4j.setting Personalized configuration properties of front end Ui
knife4j.setting.enableAfterScripttrueDebug whether the Tab displays the AfterScript function. It is enabled by default
knife4j.setting.languagezh-CNUi has two default display languages: Chinese (zh CN) and English (EN US)
knife4j.setting.enableSwaggerModelstrueWhether to display the SwaggerModel function in the interface
knife4j.setting.swaggerModelNameSwagger ModelsRename SwaggerModel name, default
knife4j.setting.enableDocumentManagetrueDisplay the "document management" function in the interface
knife4j.setting.enableReloadCacheParameterfalseWhether to display the refresh variable button after each Debug debugging bar. It is not displayed by default
knife4j.setting.enableVersionfalseWhether to enable version control of an interface in the interface. If it is enabled, there will be small blue dots on the Ui interface after the backend changes
knife4j.setting.enableRequestCachetrueWhether to enable request parameter cache
knife4j.setting.enableFilterMultipartApisfalseFor the interface request type of RequestMapping, if the parameter type is not specified, seven types of interface address parameters will be displayed by default. If this configuration is enabled, one Post type interface address will be displayed by default
knife4j.setting.enableFilterMultipartApiMethodTypePOSTFilter type of specific interface
knife4j.setting.enableHostfalseEnable Host
knife4j.setting.enableHomeCustomfalseOpen custom homepage content
knife4j.setting.homeCustomLocation Home page content Markdown file path
knife4j.setting.enableSearchfalseDisable search box in Ui interface
knife4j.setting.enableFootertrueShow Footer
knife4j.setting.enableFooterCustomfalseOpen custom Footer
knife4j.setting.footerCustomContentfalseCustomize Footer content
knife4j.setting.enableDynamicParameterfalseWhether to enable dynamic parameter debugging function
knife4j.setting.enableDebugtrueEnable debugging
knife4j.setting.enableOpenApitrueDisplay OpenAPI specification
knife4j.setting.enableGrouptrueShow service groups

The following enhancements are required

Interface add author

Li Lei at the front end found that there was a problem with the interface when he docked the interface, but he didn't know who was in charge of the interface. Through layers of searching, he finally found that Han Meimei was in charge, which greatly hindered the efficiency of development. Therefore, marking the corresponding development on the interface at this time can make it very accurate to find people and carry the pot.

Usage: add annotation @ ApiOperationSupport(author = "007")

@GetMapping(value = "/hello")
    @ApiImplicitParam(name = "name",value = "full name",required = true)
    @ApiOperation("Test interface")
    @ApiOperationSupport(author = "Inverse meteor 007")
    public String test(@RequestParam("name") String name){
        return "hello "+name+", I am  meimei han";
    }


However, for the back-end, adding this annotation to each interface is a bit of a waste of time, so knife4j after receiving the feedback, he decided to add an annotation to the Controller class, indicating that all interfaces under the current interface class are developed by the author.
So at 2.0 The @ ApiSupport annotation has been added in version 3. The annotation currently has two attributes: author and order
Note: if the @ ApiSuppor annotation is added to the controller class and the @ ApiOperationSupport annotation is also added to an interface, the author on the interface will override the author on the controller class

@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "Inverse meteor 007-controller")
@Api(tags = "test swagger")
public class Knife4jTestController

@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "Inverse meteor 007-controller")
@Api(tags = "test swagger")
public class Knife4jTestController {

    @GetMapping(value = "/hello")
    @ApiImplicitParam(name = "name",value = "full name",required = true)
    @ApiOperation("Test interface")
    @ApiOperationSupport(author = "Counter current star counter meteor 007-test")
    public String test(@RequestParam("name") String name){
        return "hello "+name+", I am  meimei han";
    }

}

Access control

Although knife4j provides us with convenient online interface documents, as the saying goes, everything has two sides, which is beneficial and harmful. That is, interface documents will also be displayed in the raw tea environment, which is a very dangerous thing. The problems are as follows:

  • When the system is deployed in the production environment, we want to shield the document function of Swagger, whether it is an interface or html document
  • Usually, we sometimes need Swagger's document debugging function to assist developers in debugging after the deployment of the production environment, but there are security risks and there is no filtering of Swagger's resource interface

Knife4j provides Filter function based on Servlet system. If developers use Spring Boot development framework for development, they only need to Properties or application Configuring the relevant attributes in the YML configuration file can easily solve the above problems without deleting the jar package of springfox swagger or deleting the relevant code, so as to improve the development experience.

Resource shielding

At present, the resource interfaces provided by springfox swagger and Knife4j include the following

resourcesexplain
/doc.htmlDocument access address provided by Knife4j
/v2/api-docs-extEnhanced interface address provided by Knife4j, from 2.0 Delete after version 6
/swagger-resourcesGrouping interface provided by springfox swagger
/v2/api-docsGroup instance details interface provided by springfox swagger
/swagger-ui.htmlDocument access address provided by springfox swagger
/swagger-resources/configuration/uiProvided by springfox swagger
/swagger-resources/configuration/securityProvided by springfox swagger

After the project is released to the production environment, we need to shield the resources related to swagger. Because Knife4j provides the Filter function based on the Servlet system, we don't need to build wheels. We can use them directly.

Spring boot only needs to make the following modifications in the configuration file

knife4j:
  # Turn on enhanced configuration 
  enable: true
 # Turn on production environment shielding
  production: true

Then restart the project

If you see the following information, it means that the resource has been shielded successfully, but you don't want to shield the swagger resource in the production environment. You can only use it for some people. You can add permission verification.

Access page weighting control

For Swagger's resource interface, Knife4j provides a simple Basic authentication function

Simply put, specify a user name and password. To access Swagger documents, you need to verify the login name and password. You can access them normally only after passing the verification.

knife4 allows developers to add a set of user names and passwords to the configuration file (application.yml/properties).

knife4j:
  # Turn on enhanced configuration 
  enable: true
 # Enable the Basic authentication function of Swagger. The default is false
  basic:
      enable: true
      # Basic authentication user name
      username: test
      # Basic authentication password
      password: 123

If the user turns on the basic (knife4j.basic.enable = true) authentication function, but does not specify username and password, knife4j provides a set of default user names and passwords

admin/123321

Configure the application After the YML file, we restart the project again (at this time, we need to remove the previously set resource screen)

Interface sorting

In our development, there are often many interfaces in a controller, so we will become very distressed when looking for documents, so knife4j added the order field in the @ ApiOperationSupport annotation for interface sorting.

Enhancements need to be turned on before using this annotation.

package com.ymy.notes.controller;

import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "Inverse meteor 007-controller")
@Api(tags = "test swagger")
public class Knife4jTestController {

    @GetMapping(value = "/hello1")
    @ApiImplicitParam(name = "name",value = "full name",required = true)
    @ApiOperation("Test interface 01")
    @ApiOperationSupport(author = "Counter current star counter meteor 007-test",order = 1)
    public String test01(@RequestParam("name") String name){
        return "hello "+name+", I am  meimei han";
    }

    @GetMapping(value = "/hello3")
    @ApiImplicitParam(name = "name",value = "full name",required = true)
    @ApiOperation("Test interface 03")
    @ApiOperationSupport(author = "Counter current star counter meteor 007-test",order = 3)
    public String test03(@RequestParam("name") String name){
        return "hello "+name+", I am  meimei han";
    }

    @GetMapping(value = "/hello2")
    @ApiImplicitParam(name = "name",value = "full name",required = true)
    @ApiOperation("Test interface 02")
    @ApiOperationSupport(author = "Counter current star counter meteor 007-test",order = 2)
    public String test02(@RequestParam("name") String name){
        return "hello "+name+", I am  meimei han";
    }
}


Grouping sorting

Grouping, as the name suggests, is the sorting of multiple controllers. Developers can sort each controller through annotations. There are three annotations to realize this function, as follows:

  • @ApiSupport
  • @ApiSort
  • @Api

These three annotations have priority, that is, when used at the same time, only one annotation will take effect, so you need to pay special attention when using. The priority rules are as follows:

@ApiSupport > @ApiSort > @Api

The sorting rules between controller s are in descending order, and the larger ones are ranked higher, but the minimum sorting value must be greater than 0.

@ApiSupport

@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "Inverse meteor 007-controller",order = 999)
@Api(tags = "test swagger")
public class Knife4jTestController 

@ApiSort

@RestController
@RequestMapping(value = "/test")
@ApiSort(value = 999)
@Api(tags = "test swagger")
public class Knife4jTestController 

@Api

@RestController
@RequestMapping(value = "/test")
@Api(tags = "test swagger",position = 999)
public class Knife4jTestController

Although the position field in @ Api can also sort among controller s, it has been knife4j marked as not recommended, so the first sorting method (@ ApiSupport) is recommended.

Request parameter cache

When we debug the interface, some interfaces will have many parameters. When we finally fill in all the parameters, because we accidentally close the page, we find that we need to input the parameters again during the next debugging, and the mentality will explode. Therefore, knife4j added an option in document management: turn on the request parameter cache.

After checking this option, the parameters you fill in will be knife4j cached and the page will not be lost when you close it. Is it very human?

Write code and prepare data

 @PostMapping(value = "/saveUser")
    @ApiOperation("Save user information")
    @ApiOperationSupport(author = "Counter current star counter meteor 007")
    public String saveUser(@RequestBody UserDTO userDTO){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "save success";
    }
package com.ymy.notes.dto;

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

@ApiModel("User information")
@Getter
@Setter
@ToString
public class UserDTO {

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

    @ApiModelProperty(value = "Gender")
    private String gender;

    @ApiModelProperty(value = "phone number")
    private String phone;
}

However, you can't be happy too early, and the cache will not necessarily take effect. In these two cases I know, the cache will fail. You should pay attention to it when using it.

  • If you add the example (example value of the property) property in the @ ApiModelProperty annotation of the field, knife4j will not use the cache, but the example specified by the back end.
public class UserDTO {

    @ApiModelProperty(value = "user name",example = "Li Lei")
    private String username;

    @ApiModelProperty(value = "Gender",example = "male")
    private String gender;

    @ApiModelProperty(value = "phone number",example = "18888888888")
    private String phone;
}
  • When the domain name changes, all caches will be invalidated.

Dynamic request parameters

As a developer, I don't know whether you have done this operation. The interface parameters are not received by entity objects, but by maps. Although I haven't done this, I've seen others write this. How will the Swagger ui display when the back-end programmer uses Map to receive parameters? Let's simulate it.

Define an interface to receive parameters in Map

@PostMapping(value = "/saveUserForMap")
    @ApiOperation("Add user information-map")
    @ApiOperationSupport(author = "Inverse meteor 007")
    private String saveUserForMap(Map<String,Object> userDTO ){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "save success";
    }

Let's see how the Swagger ui shows the parameters of this Map type

This..... If the front-end sees such interface documents, it starts to greet the back-end family. How to solve this problem? In fact, it's very simple. knife4j has already thought of a solution for us. We can solve this problem by calling document management - personalized setting and checking enable dynamic request parameters.

Now let's take a look at the effect after checking the enable dynamic request parameter

After a parameter is entered, a new line will be automatically added to the parameter list, but the key of the parameter needs to be filled in by the front-end personnel. The front-end may not know the key of the parameter, so you still need to find the back-end developer. Although the dynamic parameter is enabled to increase the number of parameters, there is no way to solve the problem of parameter value, How to solve this problem? This is another enhancement: adding document comments to dynamic request parameters

Filter request parameters

In the development process, we often encounter such a problem: adding and modifying interfaces. The modified interface needs to pass the modified record id, but it is not required for adding. The back end often sets the modified and newly added parameter object as an object, so there must be an id field in the object, which will mislead the addition, and the front end may be confused, How should I pass the new id? It's impossible to steal one.

Therefore, knife4j supports the filtering (ignoring) of request parameters. The implementation method is also very simple. The parameters to be displayed can be forcibly ignored by using the ignoreParameters property in the user-defined enhanced annotation ApiOperationSupport.

Before using field ignore, we need to understand the rules of field ignore:

  • 1. For example, when adding an interface, an entity class does not need to display Id, so you can use this attribute to ignore the parameter ignoreParameters={"id"}
  • 2. If there are multiple levels of parameter filtering, use the name For example, ignoreParameters={"uptModel.id","uptModel.uptPo.id"}, where uptModel is the parameter name of the entity object, id is its attribute, and uptPo is the entity class as the attribute name of the uptModel class
  • 3. If the parameter level is only one level and the parameter is an entity class, the parameter name does not need to be set, and the attribute value name can be given directly
  • 4. If the entity class attribute adopts the array method of List, the filtering rules will be different. A subscript [0] needs to be added after the attribute, and ignoreParameters={"uptModel.uptPo[0].id"}

To achieve this function, you need to turn on the enhancement.

The format of form submission is different from that of JSON submission, so we need to explain it separately. Let's first look at how form submission ignores field properties.

Precondition: we first create two DTO s to receive the two-point parameters passed by the front end

package com.ymy.notes.dto;

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

@ApiModel("User information")
@Getter
@Setter
@ToString
public class UserDTO {

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

    @ApiModelProperty(value = "user name",example = "Li Lei")
    private String username;

    @ApiModelProperty(value = "Gender",example = "male")
    private String gender;

    @ApiModelProperty(value = "phone number",example = "18888888888")
    private String phone;

    @ApiModelProperty(value = "User receiving address information")
    private UserAddressDTO userAddressDTO;
}
package com.ymy.notes.dto;

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

@Getter
@Setter
@ToString
public class UserAddressDTO {

    @ApiModelProperty(value = "Record of harvest address id")
    private Long id;
    
    @ApiModelProperty(value = "province")
    private String province;

    @ApiModelProperty(value = "city")
    private String city;

    @ApiModelProperty(value = "area")
    private String district;

    @ApiModelProperty(value = "Detailed address")
    private String addr;
}

Form submission

Create a new interface and modify an interface, and you want to filter out the id field in UserDTO and the id field in UserAddressDTO when adding, because there is no id information when adding a user and harvesting an address, and the id field will exist only after adding.

  @ApiOperationSupport(author = "Inverse meteor 007",ignoreParameters = {"id","userAddressDTO.id"})
    @PostMapping(value = "/saveUser")
    @ApiOperation("Add user information-form ")
    @ApiOperationSupport(author = "Inverse meteor 007",ignoreParameters = {"id","userAddressDTO.id"})
    public String saveUser( UserDTO userDTO){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "save success";
    }


    @PostMapping(value = "/updateUser")
    @ApiOperation("Edit user information")
    @ApiOperationSupport(author = "Inverse meteor 007")
    public String updateUser( UserDTO userDTO){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "edit success";
    }

When filtering fields, we only need to fill in the attribute name in the object in the first layer, but if we need to filter the second layer, according to the second rule in the ignore rule, we introduce the useraddressdto object into the UserDTO object: private UserAddressDTO userAddressDTO; We also need to ignore the id attribute in the useraddressdto object, so we need to fill in useraddressdto id, where useraddressdto should be consistent with the useraddressdto property name in the UserDTO object.

The code is written. Let's see the effect.

Add interface

Here, we can't see the id in UserDTO and UserAddressDTO. Ignore success.

Modify interface

Since we did not ignore these two fields when modifying, it can be displayed normally, which is no problem.

JSON submission

There are some differences between the format of form submission and json submission, so there are also some differences in the format of ignoring parameters. We change the parameter receiving method of the original modification and modification interface to json format and maintain the same ignoring format as form submission (to see more obvious effects, I am ignoring one more field: "username").

@ApiOperationSupport(author = "Inverse meteor 007",ignoreParameters = {"id","userAddressDTO.id"})
 @PostMapping(value = "/saveUser")
    @ApiOperation("Add user information")
    @ApiOperationSupport(author = "Inverse meteor 007",ignoreParameters = {"id","userAddressDTO.id"})
    public String saveUser(@RequestBody UserDTO userDTO){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "save success";
    }


    @PostMapping(value = "/updateUser")
    @ApiOperation("Edit user information")
    @ApiOperationSupport(author = "Inverse meteor 007")
    public String updateUser(@RequestBody UserDTO userDTO){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "save success";
    }

Let's see what the effect will be like first? Can you successfully ignore it?

New interface

Oh, roar, it's successful to ignore it. Lying in the slot, it's too fast. I ignored a field in UserDTO: id, UserAddressDTO object. I ignored the id field. We checked the ui interface and found that it was successful. What's the matter? I don't know exactly why. It may be 3 X has been upgraded, and the ignore method is consistent with the form, maybe 3 X is unstable and strange bugs appear, which leads to the neglect of json format. Although this can also ignore success, I'm not sure whether it's due to the optimization of the higher version without updating the document or strange bugs. I'll continue to introduce the neglect format of json format parameters. Maybe students can't use it like this, I recommend the following format.

How can json format be ignored?

The professional saying is: instance name Attribute name. Taking the new user as an example, we need to filter the user id, so the writing method is: userDTO id, where userDTO is the parameter name of saveUser().

Now let's transform our code

@PostMapping(value = "/saveUser")
    @ApiOperation("Add user information")
    @ApiOperationSupport(author = "Counter current star counter meteor 007",ignoreParameters = {"userDTO.id","userDTO.userAddressDTO.id"})
    public String saveUser(@RequestBody UserDTO userDTO){
        System.out.println("User information transmitted by the front end:"+ userDTO);
        return "save success";
    }

Let's see the effect

There is another situation that needs to be noted here. If the fields you ignore are in the second layer of the object, you will not see the completed sample code in the request example, and you will lose weight. Maybe 3 X bug, so I stated at the beginning, 3 X may not be stable enough at present. Students who upgrade or use it still need to be careful.

Search API interface

In the upper right corner of the document, Knife4j provides the function of document retrieval

What keywords does this search box support?

  • Interface address.
  • Interface name.
  • Interface description.

The above three searches are fuzzy searches. However, it should be noted that the current search function is only valid for the loaded interfaces in the current group. For the interfaces in the group, it cannot be searched without loading. In other words, the search function is not a global search, but only searches the overall list of all interfaces you see.

Version requirements: knife4j version > 2.0 1 use this rule.

Global parameters

Knife4j provides the function of temporarily setting global parameters based on UI, such as background global token parameters This function is mainly provided to facilitate developers to debug

At present, the global parameter function mainly provides two parameter types: query (form) and header (request header)

If the backend Swagger is configured with global parameters, this function can be ignored

Function Directory: document management - > global parameter setting

Customize home page content

I don't know if you think swagger's home page has a very ugly feeling? Don't you really want to see it? Well, the next enhancement is your benefit. knife4j supports developers to replace the home page, but currently only supports md format.

Enhancements need to be turned on.

Knife4j from 2.0 Starting from version 8, developers can provide a Markdown file to define the display content of the Home home page, which can be started by configuring yml. The configuration file is as follows

knife4j:
  enable: true
  setting:
    enableHomeCustom: true
    homeCustomLocation: classpath:markdown/home.md

Attribute description:

  • enableHomeCustom: this property is a Boolean value. The default value is false. If the developer wants to customize the content of the home page, this option is set to true
  • homeCustomLocation: provides a Markdown file location for the home page

We first create a markdown directory under the resources directory, and then create home under the markdown directory md

<center><h1>Inverse meteor 007</h1></center>

Nickname: inverse meteor 007

occupation: java Development Engineering

Open source blog address: http://yaomaoyang.com   https://blog.csdn.net/qq_33220089

Contact email: 361426201@qq.com

It's home Next, let's restart the project and see the effect together

Well, why hasn't it changed? Obviously, it has been modified. Don't worry. We forgot the core step, so it was not replaced successfully. The developer needs to assign the extension attribute through the tool object OpenApiExtensionResolver provided by Knife4j when creating the Docket logical grouping object.

package com.ymy.notes.config.kinfe4j;

import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import org.springframework.beans.factory.annotation.Autowired;
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.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Knife4jConfiguration {

    private final OpenApiExtensionResolver openApiExtensionResolver;

    @Autowired
    public Knife4jConfiguration(OpenApiExtensionResolver openApiExtensionResolver) {
        this.openApiExtensionResolver = openApiExtensionResolver;
    }

    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        String groupName="3.X edition";
        Docket docket=new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("This is knife4j API ")
                        .description("# The input parameters, output parameters and other information of all interfaces of the server are recorded here ")
                        .termsOfServiceUrl("http://yaomaoyang.com")
                        .contact(new Contact("Inverse meteor","http://yaomaoyang.com","361426201@qq.com"))
                        .version("3.0")
                        .build())
                //Group name
                .groupName(groupName)
                .select()
                //The Controller scan package path is specified here
                .apis(RequestHandlerSelectors.basePackage("com.ymy.notes.controller"))
                .paths(PathSelectors.any())
                .build()
                .extensions(openApiExtensionResolver.buildSettingExtensions());
        return docket;
    }

}

Through the above example code, the main steps are as follows:

1. The @ Autowired annotation introduces the Bean object OpenApiExtensionResolver injected by Knife4j into the Spring container

2. Finally, after the Dcoket object is built, the plug-in assignment is performed by calling the extensions method of the Docket object

3. For plug-in assignment, you need to call the buildSettingExtensions method provided by OpenApiExtensionResolver to obtain the enhanced property of x-settings

In this way, we can see the effect.

Disable debugging

In previous versions, if developers wanted to disable the debugging function, they disabled the debugging of some interfaces by creating the entity Bean object of UiConfiguration on the server and configuring supportMethod. Since 2.0 After version 8, this attribute is discarded

This function can be used only when enhanced mode is turned on

If the developer needs to disable the debugging function, he only needs to operate in the configuration file

knife4j:
  enable: true
  setting:
    enableDebug: false

Attribute description:

  • enableDebug: this attribute is a Boolean value, which indicates whether debugging is enabled. The default value is true (which means debugging is enabled). If debugging is to be disabled, this value is set to false

Similarly, this operation also requires the developer to assign the extension attribute through the tool object OpenApiExtensionResolver provided by Knife4j when creating the Docket logical grouping object.

package com.ymy.notes.config.kinfe4j;

import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import org.springframework.beans.factory.annotation.Autowired;
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.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Knife4jConfiguration {

    private final OpenApiExtensionResolver openApiExtensionResolver;

    @Autowired
    public Knife4jConfiguration(OpenApiExtensionResolver openApiExtensionResolver) {
        this.openApiExtensionResolver = openApiExtensionResolver;
    }

    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        String groupName="3.X edition";
        Docket docket=new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("This is knife4j API ")
                        .description("# The input parameters, output parameters and other information of all interfaces of the server are recorded here ")
                        .termsOfServiceUrl("http://yaomaoyang.com")
                        .contact(new Contact("Inverse meteor","http://yaomaoyang.com","361426201@qq.com"))
                        .version("3.0")
                        .build())
                //Group name
                .groupName(groupName)
                .select()
                //The Controller scan package path is specified here
                .apis(RequestHandlerSelectors.basePackage("com.ymy.notes.controller"))
                .paths(PathSelectors.any())
                .build()
                .extensions(openApiExtensionResolver.buildSettingExtensions());
        return docket;
    }

}

After all operations are completed, restart the project to see the effect

The debug and open buttons are gone.

Disable search box

If the sender wants to disable the search function in the Ui interface, it needs to be configured through the enhanced attribute. This function needs to enable the enhanced function.

knife4j:
  enable: true
  setting:
    enableSearch: false

Attribute description:

  • enableSearch: this property is a Boolean value, which represents whether to enable the search function. The default value is true (which means to enable the search). If you want to disable the search, this value is set to false

Similarly, this operation also requires the developer to assign the extension attribute through the tool object OpenApiExtensionResolver provided by Knife4j when creating the Docket logical grouping object. For specific code implementation, please refer to disabling debugging and customizing the home page. I won't repeat it here.

Restart the project to see the effect

Well, this is the end of the introduction of knife4j. There are some advanced functions that you need to explore slowly. Most of this article refers to the official documents of knife4j and the demo you wrote. If you think it is helpful to you, I hope to leave you a valuable praise.

Topics: Java swagger