1. Local working environment
ide2021
jdk17
springboot3.0.11-SNAPSHOT
2. Reasons for using knife4j-openapi3
After writing a project using springboot3, I want to quickly generate an interface document for myself to watch. After surfing the Internet for a while, I found that it is more suitable to use Swagger documents to complete a complex document with a small number of annotations. Just go ahead and write a demo using the information on the Internet, but found that the project could not start normally. After reading the blog, I found that Swagger2 is temporarily unable to adapt to springboot3. Later, I found in other blogs that openapi can be used to be compatible with springboot3. At the same time, knife4j is a beautification of swagger, so knife4j-openapi3 is used.
3. Configure
The corresponding dependencies are as follows:
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.1.0</version> </dependency>
The configuration file is in yml format, so simply configure knife4j as follows in the configuration
# Online document configuration springdoc: swagger-ui: # Configure swagger-ui interface access path path: /swagger-ui.html #Packet scanning path packages-to-scan: com.pjx.sys.controller # Enable wend by default api-docs: enabled: true
The above packages-to-scan, which is the package scanning path, scans the control layer, which is your controller layer. Just scan to the outer layer and do not go deep into the interior. The path can be copied directly.
At this time, knife4j still needs to be configured before it can be used.
Create the SwaggerConfig class in your own project for configuration
import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SwaggerConfig { @Bean public OpenAPI springShopOpenAPI() { return new OpenAPI() .info(new Info().title("title") //Description .description("My API Documentation") //Version .version("v1") //Author information, set by yourself .contact(new Contact().name("Peng").email("11111").url("https://www.baidu.com")) //Set the license information of the interface document .license(new License().name("Apache 2.0").url("http://springdoc.org"))); } }
The basic configuration here is complete, let’s use a simple demo to demonstrate
The above is the corresponding structure, and the following are the control layer and pojo.
import com.example.test.pojo.Books; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Tag(name = "test", description = "description") @RestController @RequestMapping("/getBooks") public class BookController { @GetMapping @Operation(summary = "Test interface") public Books getBooks(){ Books books = new Books(); books.setId(1); return books; } }
import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Schema @Data public class Books { @Schema(name = "id",description = "user id",defaultValue = "12",example = "1") private Integer id; }
After the above is completed, a simple document is completed, and you can directly see the effect.
doc.html
swagger-ui
After the demo was completed and no problems were found, I started to import the configuration into my own project, and then a series of problems appeared.
4. Problems that arise in your own projects
4.1 can access swagger -ui but cannot access doc.html
I didn’t know what was going on at the time, and I was thinking, why can’t it be displayed? Why can swagger-ui be used? Why can demo be used? Programmers are confused for three consecutive times. . . Finally, after browsing a lot of blogs, I realized that I was out of my mind.
First of all, you need to know where these resources are. They are in the jar package of knife4j. Although you have imported the package, you do not tell spring boot about the resources. How can it find them? Looking for air? Secondly, swagger-ui can be used because it is configured in the yml file. The doc has no configuration and no configuration method. The demo can be used, but the one in the project cannot be used because the springboot version is too high and sometimes cannot be found. Resources, you need to tell it manually, which brings you back to question 1.
The corresponding resources are as follows:
4.1.1 Solution
Implement the WebMvcConfigurer interface in the WebConfig configuration class, override the addResourceHandlers method, and import the location of the resource.
@Component public class WebConfig implements WebMvcConfigurer { /** * Static resource mapping * * @param registry */ @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } }
In this way, the resources are found by springboot. Of course, if the interceptor is configured, some resources need to be ignored. You can implement the addInterceptors method in the WebMvcConfigurer interface, use addInterceptor internally to define your own interceptor, and use addPathPatterns to add interception paths and excludePatterns. Ignore the path, my ignore path is as follows
"/v3/api-docs/**", "/doc.html", "/webjars/**", "/swagger-resources", "/swagger- ui/**"
If you don’t know the specific resources to be ignored, you can directly use Shift + f5 in the browser’s Network to ignore those resources that report errors. In this way, doc.html can be accessed.
4.2 Regarding the problem of not being able to find the icon in doc.html
This problem is not big at all, but I don’t like seeing the browser error message very much. After checking the information on the Internet, I found that the icon may be infringing, and then it is not allowed to be used in the future.
4.2.1 Solution
Put a favicon.ico picture in the static resource folder by yourself. Put whatever you like, but the suffix name must be the same. Must be an ico file. Download one you like from the Internet and change the suffix yourself.
After putting it in, everything is not fine. You still need to let spring boot know about this icon, otherwise it will still be inaccessible. You also need to add static resource mapping. Add in method 4.1.1
registry.addResourceHandler("favicon.ico").addResourceLocations("classpath:/static/");
At the same time, add /favicon.ico to the ignore path, which means that this image is allowed so that the browser can find it.
Finally the solution is completed. Sprinkle flowers.
Just kidding.
5. Simple application in entity classes and control layers.
5.1 Entity Class
Just go to the code, okay.
import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Schema @Data public class User { //id @Schema(name = "id", description = "serial number", defaultValue = "1", example = "1") private Integer id; //username @Schema(name = "username", description = "username", defaultValue = "not null", example = "admin") private String username; //password @Schema(name = "password", description = "password", defaultValue = "not null", example = "******") private String password; //permission id @Schema(name = "roleId", description = "Permission id, determine whether you have this permission", defaultValue = "not null", example = "admin") private Integer roleId; //Whether it is default @Schema(name = "is_default", description = "0 is the default user, 1 is the normal user", defaultValue = "1", example = "1") private Integer is_default; //Permissions @Schema(hidden = true) private Role role; //token @Schema(name = "token", description = "storage front-end token", defaultValue = "not null", example = "dsafasdff341234123...") private String token; }
The @Schema annotation is used to describe the attributes of a class, description is a description, defaultValue is the default value, example is an example, and hidden is ignored.
5.2 Control Layer
import com.pjx.sys.service.UploadService; import com.pjx.sys.util.R; import com.pjx.sys.util.SYSCode; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.io.FileNotFoundException; @Tag(name = "Upload picture") @RestController @RequestMapping("/adminapi/upload") public class UploadController { //Import UploadService @Resource private UploadService uploadService; @Operation(method = "POST", summary = "Update background image", description = "Update the background image of the laboratory by passing in a picture with specified specifications") @PostMapping public R uploadBg(@Parameter(description = "picture object") @RequestParam("file") MultipartFile file) { try { uploadService.uploadBg(file); return new R(SYSCode.CODE_SUCCESS, "Upload successful"); } catch (FileNotFoundException e) { e.printStackTrace(); } return new R(SYSCode.CODE_ERROR, "Upload failed"); } }
@Tag is used to mark and group API interfaces.
@Operation is used to describe the detailed operation of API interface methods. method is the method, summary is the introduction, and description is the description.
@Parameter is used to specify the parameter list of the operation.
Other methods are incomplete, but are as follows for the time being: