springboot integrates Swagger2 (speed pass)

Table of Contents

  • 1 Overview
  • 2. Case 1
  • 3. Easy to use UI
  • 4. Simple configuration of Docket object
    • 1. Description of the configuration file
    • 2. Define packet scanning rules
  • 5. Specifies that the interface does not generate documentation
    • 1. Custom annotations
    • 2. Path matching
  • 6. Common annotations

1. Overview

Simple understanding – the framework for writing interface documents, which can be updated in real time following interface modifications.

Open API format: The description format of REST API, which can be written in YAML or JSON format. Description scope of Open API:

  • the type of each access address;
  • parameters for each operation;
  • authentication method;
  • Connection information, claims, usage teams and other information.

Swagger: A set of online automatic generation and functional testing APIs for a RESTful interface document built around the Open API specification. Store relevant information in the description file in YAML/JSON format, and then update the interface document through the description file. Its toolkit:

  • Swagger Editor: Based on a browser editor, you can write Open API specifications;
  • Swagger UI: present the Open API specification as an interactive API document, that is, a description file (commonly used);
  • Swagger Codegen: Generate HTML and cwiki-style interface documents from description files, which can generate client and server codes in multiple languages at the same time;
  • Swagger Inspector: Similar to Swagger UI, but contains more information, such as the actual parameter data of the request;
  • Swagger Hub: Integrate all the functions of the above tools, upload the description file to the Hub, and then complete all the work of the above tools.

Springfox: Swagger needs to change the description file when it encounters version iterations, but Springfox optimizes this process and generates documents in real time based on the code. Integrate Swagger into the code through annotations.

2. Case 1

rely:

  • web project

     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
  • springfox depends on, the following two should be imported at one time, and the version should be corresponding

     <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger2</artifactId>
                <version>2.9.2<</version>
            </dependency>
            <dependency>
                <groupId>io.springfox</groupId>
                <artifactId>springfox-swagger-ui</artifactId>
                <version>2.9.2<</version>
            </dependency>
    

annotation:

  • Start class annotations:

    @EnableSwagger2 // Enable swagger2 related technologies to scan annotations in the package where the current class is located and its sub-packages
    @SpringBootApplication
    
  • Control class:

    @RestController
    public class SwaggerController {<!-- -->
        @GetMapping("/get")
        public String getStr(String str) {<!-- -->
            return "SELECT " + str;
        }
    
        @PostMapping("/post")
        public String postStr(String str) {<!-- -->
            return "CREATE " + str;
        }
    
        @PutMapping("/put")
        public String putStr(String str) {<!-- -->
            return "UPDATE " + str;
        }
    
        @PatchMapping("/patch")
        public String patchStr(String str) {<!-- -->
            return "UPDATE " + str;
        }
        
        @DeleteMapping("/delete")
        public String deleteStr(String str) {<!-- -->
            return "DELETE " + str;
        }
    }
    
  • Run the code and visit http://127.0.0.1:8080/swagger-ui.html, you may encounter the following error:

    Starting the project encountered an error: java: warning: source release 17 requires target release 17
    Solution: https://blog.csdn.net/weixin_44299027/article/details/120848738

    Starting project encountered error: Class file has wrong version 61.0, should be 52.0
    Solution: starting from spring6.0, jdk requires 17 or above, either upgrade JDK, or lower the spring version.
    I choose to lower the spring version:

    • https://mvnrepository.com/ View the version number of spring-boot-starter-parent
    • Select a version number below 3 and modify Maven to depend on spring-boot-starter-parent

    An error was reported when starting the project: Failed to start bean ‘documentationPluginsBootstrapper’;
    Solution: After springboot is upgraded to 2.6.0, the swagger version is incompatible with springboot, either reduce the springboot version, or configure spring.mvc.pathmatch.matching-strategy=ant_path_matcher

    • A. Reduce the springboot version and do not go into details (it can be reduced to below 2.5 and there is absolutely no problem);
    • B. Configuration 1: ① Add annotations to the startup class @EnableWebMvc; ② Add spring.mvc.pathmatch.matching-strategy=ant_path_matcher to the configuration file;
    • C. Configuration 1 does not take effect: Reference: https://blog.csdn.net/weixin_39792935/article/details/122215625
    • D. When the above three solutions do not work, the ultimate solution I adopted: reduce the Springboot version (2.5.6), and adopt the configuration of the C scheme, and then visit http:/ /127.0.0.1:8080/swagger-ui.html

      Access page is empty:

      Solution: add annotation @EnableOpenApi to the startup class, and visit http://localhost:8080/swagger-ui/index.html

  • Solve the problem of inaccessibility:

    • Modify the configuration file application.properties

      spring.mvc.pathmatch.matching-strategy=ant_path_matcher
      
    • New configuration class:

      package com.chenjy.swagger.config;
      
      import org.springframework.context.annotation.Configuration;
      import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
      import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
      
      /**
       * @Desc Solve the problem that the higher version is not compatible with swagger2
       * After this configuration, you can access swagger-ui.html through http://127.0.0.1:8080/doc.html
       */
      @Configuration
      public class WebMvcConfigurer extends WebMvcConfigurationSupport {<!-- -->
      
          /**
           * Found that if WebMvcConfigurationSupport is inherited, the relevant content configured in yml will be invalid. Static resources need to be respecified
           */
          @Override
          public void addResourceHandlers(ResourceHandlerRegistry registry) {<!-- -->
              registry.addResourceHandler("/**").addResourceLocations(
                      "classpath:/static/");
              registry.addResourceHandler("swagger-ui.html", "doc.html").addResourceLocations(
                      "classpath:/META-INF/resources/");
              registry.addResourceHandler("/webjars/**").addResourceLocations(
                      "classpath:/META-INF/resources/webjars/");
              super. addResourceHandlers(registry);
          }
      
      }
      
    • Reduce the springboot version to 2.5.6

       <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>2.5.6</version>
              <relativePath/> <!-- lookup parent from repository -->
          </parent>
      
  • The access interface is as shown in the figure below, from which you can see the interface we wrote:

3. Simple use of UI

Scan the @GetMapping/@RequestMapping(method = {RequestMethod.GET}) series in all controllers (controllers by default) in the project (in the same level directory as the startup class and its subdirectories) Annotate, and then analyze the mapping address corresponding to the annotation and the request method constrained by the annotation (GET, POST, DELET…, the default is GET). Click on the specific method to view detailed request information:

You can click Try it out to test:

4. Simple configuration of Docket object

1. Description of the configuration file

package com.chenjy.swagger.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SwaggerConfigurer {<!-- -->

    /**
     * @return Docket - the global configuration object in Swagger
     */
    @Bean
    public Docket docket() {<!-- -->
        // DocumentationType.SWAGGER_2 tells Springfox that the current Swagger version is Swagger2
        Docket docket = new Docket(DocumentationType. SWAGGER_2);
        // Description of the API help documentation
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("Swagger Documentation")// document title
                .description("Swagger: A set of RESTful interface documents built around the Open API specification for online automatic generation and functional testing API.")//Description information
                .version("1.0.1")// version number
                .contact(
                        // name url email
                        new Contact("364.99°Document", // Document publisher name
                                "https://blog.csdn.net/m0_54355172", // Website address of the document publisher
                                "[email protected]" // Email of the document publisher
                        )
                )
                // builder pattern
                .build();
        // Configure the API description information for the docket context
        docket.apiInfo(apiInfo);
        return dock;
    }
}

2. Define package scanning rules

Add the following configuration in the docket method:

 dock
                .select() // Get the selector in the docket, such as: which package to scan for annotations
                .apis(RequestHandlerSelectors.basePackage("com.chenjy.swagger.controller")); // Define rules - package scanning rules

5. The specified interface does not generate documentation

1. Custom annotation

How to customize an annotation

Define an annotation to mark the current interface without generating a Swagger document:

package com.chenjy.swagger.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({<!-- -->ElementType.METHOD, ElementType.TYPE}) // This annotation is used to describe methods and classes
@Retention(RetentionPolicy.RUNTIME)// annotation information will be valid at runtime
public @interface NoSwagger {<!-- -->
    // Custom annotation attribute @NoSwagger(value="")
    String value() default "";
}

The configuration class enables the annotation rules to take effect:

package com.chenjy.swagger.config;

import com.chenjy.swagger.annotation.NoSwagger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
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 static com.google.common.base.Predicates.not;
import static springfox.documentation.builders.RequestHandlerSelectors.withMethodAnnotation;

@Configuration
public class SwaggerConfigurer {<!-- -->

    /**
     * @return Docket - the global configuration object in Swagger
     */
    @Bean
    public Docket docket() {<!-- -->
        // DocumentationType.SWAGGER_2 tells Springfox that the current Swagger version is Swagger2
        Docket docket = new Docket(DocumentationType. SWAGGER_2);
        // Description of the API help documentation
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("Swagger Documentation")// document title
                .description("Swagger: A set of RESTful interface documents built around the Open API specification for online automatic generation and functional testing API.")//Description information
                .version("1.0.1")// version number
                .contact(
                        // name url email
                        new Contact("364.99°Document", // Document publisher name
                                "https://blog.csdn.net/m0_54355172", // Website address of the document publisher
                                "[email protected]" // Email of the document publisher
                        )
                )
                // builder pattern
                .build();
        // Configure the API description information for the docket context
        docket.apiInfo(apiInfo);
        Docket build = docket
                .select() // Get the selector in the docket, such as: which package to scan for annotations
                .apis(
                        not( // negate
                                withMethodAnnotation(NoSwagger.class) // returns true when there are annotations on the method
                        )
                )
                .apis(RequestHandlerSelectors.basePackage("com.chenjy.swagger.controller")) // Define rules - package scanning rules
                .build();
        return build;
    }
}

Note: Here you need to re-build the Docket, and then return to the docket after the re-build, otherwise it will not take effect.

Annotated on the interface method:

 @NoSwagger
    @PatchMapping("/patch")
    public String patchStr(String str) {<!-- -->
        return "UPDATE " + str;
    }

To restart the project, visit:

Optimized writing:

 Docket build = docket
                .select() // Get the selector in the docket, such as: which package to scan for annotations
                .apis(
                        and(
                                not( // negate
                                        withMethodAnnotation(NoSwagger.class) // returns true when there are annotations on the method
                                ),
                                RequestHandlerSelectors.basePackage("com.chenjy.swagger.controller")
                        )
                )
                .build();
        return build;

Note:

  • Both and and not are static methods in com.google.common.base.Predicates;
  • withMethodAnnotation is a static method in springfox.documentation.builders.RequestHandlerSelectors.

2. Path matching

springfox.documentation.builders.PathSelectors

Only interface methods whose paths are prefixed with /test will generate documentation.

 Docket build = docket
                .select() // Get the selector in the docket, such as: which package to scan for annotations
                .paths(
                        PathSelectors.regex("/test/.*") // Use regular expressions . Any character * 0 or more
                )
                .build();
        return build;

Multiple path matching rules at the same time: Predicates.or

.paths(
                        Predicates.or(
                                PathSelectors.regex("/test/.*"),
                                PathSelectors.regex("/.*")
                        )
                )

→ Regular Expression Syntax ←

6. Commonly used annotations

@Api(tags = {"test interface API"})

  • Class annotations, describing the information of the current type to generate help documents;
  • tags defines the controller alias, which can have multiple values, there are several aliases, and there are several controller directories in the document.

@ApiOperation(value = "get method, execute query operation", notes = "a small demo")

  • Class and method annotations are often used to describe methods.

@ApiParam()

  • Parameters, methods, and attribute annotations are often used to describe parameters;

    @PostMapping("/post")
    public String postStr(
            @ApiParam(name = "string", value = "string used to output", required = true) String str,
            @ApiParam(name = "Serial Number", required = false) @RequestParam(defaultValue = "001", required = false)String num
    ) {<!-- -->
        return "CREATE " + str + num;
    }
    

@ApiIgnore

  • Method, attribute annotation, so that the method or type described by this annotation does not generate API documentation.

     @ApiIgnore
        @PutMapping("/put")
        public String putStr(String str) {<!-- -->
            return "UPDATE " + str;
        }
    

@ApiImplicitParam

  • To describe method parameters on a method, only one parameter can be described.

     @ApiImplicitParam(
                name = "str", value = "a string", required = true, paramType = "java.lang.String", dataType = "any string"
        )
        @DeleteMapping("/delete")
        public String deleteStr(String str, Integer num) {<!-- -->
            return "DELETE " + str;
        }
    

ApiImplicitParams

  • Parameters are described on the method, and multiple parameters can be described.
     @ApiImplicitParams(value = {<!-- -->
               @ApiImplicitParam( name = "str", value = "a string", required = true, paramType = "java.lang.String", dataType = "any string" ),
               @ApiImplicitParam( name = "num", value = "an integer")
        })
        @DeleteMapping("/delete")
        public String deleteStr(String str, Integer num) {<!-- -->
            return "DELETE " + str;
        }
    

@ApiModel

  • Describes the entity class. When this entity class is used as the return type in the interface method in the API help document, this annotation is parsed.

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel( value = "an entity class", description = "store data and return")
    public class TestDto {<!-- -->
        private String name;
        private Integer num;
    }
    
     @PatchMapping("/patch")
        public TestDto patchStr(String str, Integer num) {<!-- -->
            return new TestDto(str, num);
        }
    

@ApiModelProperty

  • Describe the attributes of the entity class, to be used with @ApiModel.

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @ApiModel( value = "an entity class", description = "store data and return")
    public class TestDto {<!-- -->
        @ApiModelProperty( value = "Name", example = "Zhang San", hidden = false)
        private String name;
        @ApiModelProperty( value = "serial number")
        private Integer num;
    }
    


Note:

  • GET: @requestBody cannot be used;
  • POST: You can use @requestBody (configuration for parameter conversion must be unified) and @requestParam .