> 技术文档 > 在 springboot3.x 使用 knife4j 以及常见报错汇总_springboot3 knife4j

在 springboot3.x 使用 knife4j 以及常见报错汇总_springboot3 knife4j

目录

引言: 

引入依赖: 

配置文件: 

过滤静态资源:

 增强模式:

便捷地址访问:

常见问题: 

注解使用实例: 


📄 ​文档参考地址​:
SpringBoot 3.x 结合 Swagger3 (Knife4j )踩坑实录 - 古渡蓝按 - 博客园 🔍

🏛️ ​官方文档地址​:
快速开始 | Knife4j📚

💡 ​背景来源​:
想在微服务项目使用 Knife4j,但是找了很多文档使用后访问地址无法显示 😵。经过实践和排查,终于解决了问题 ✅!

引言: 

首先,重点强调 Spring Boot 3.x 只支持 OpenAPI3 规范:

  • Knife4j提供的starter已经引用springdoc-openapi的jar,开发者需注意避免jar包冲突
  • JDK版本必须 >= 17
  • 详细Demo请参考knife4j-spring-boot3-demo

在 Spring Boot 3.x 项目中,如果你看到 swagger-annotations 依赖,通常意味着你正在使用 ​Springfox Swagger​(如 springfox-swagger2),而它 ​不兼容 Spring Boot 3.x​(因为 Spring Boot 3 迁移到了 Jakarta EE 9+,而 Springfox 仍依赖旧的 javax.servlet 包)。 

 io.springfox springfox-swagger2 2.10.5 io.springfox springfox-swagger-ui 2.10.5

SpringDoc 是 Spring Boot 3.x 的官方推荐替代方案,完全兼容 Jakarta EE 9+: 

Springfox (旧) SpringDoc (新) 作用 @Api @Tag 类级别的 API 描述 @ApiOperation @Operation 方法级别的 API 描述 @ApiParam @Parameter 参数描述 @ApiModel @Schema 模型描述

所以我们需要更换新的依赖,也就是Knife4j4.x,这样才能在 Spring Boot 3.x 项目中使用。

引入依赖: 

首先引入依赖:

 io.swagger.core.v3 swagger-core 2.2.20 com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter 4.4.0 org.springdoc springdoc-openapi-starter-webmvc-api 2.2.0 org.springframework.boot spring-boot-configuration-processor true com.fasterxml.jackson.module jackson-module-jakarta-xmlbind-annotations 2.13.3 javax.xml.bind jaxb-api 2.4.0-b180830.0359

配置文件: 

我们一共要引入三个配置类和一个配置文件:

引入配置文件,这里因为我在开发微服务,所以在bootstrap.yml进行配置,如果正常开发Springboot项目的话,在application.yml配置即可:

尽需改写文档扫描包路径即可,配置成自己项目的controller包路径。 

server: servlet: context-path: /content port: 63040# springdoc-openapi项目配置springdoc: swagger-ui: path: /swagger-ui.html tags-sorter: alpha operations-sorter: alpha api-docs: path: /v3/api-docs group-configs: - group: \'default\' paths-to-match: \'/**\' # 生成文档所需的扫包路径,一般为启动类目录 packages-to-scan: com.xuecheng.content.api# knife4j的增强配置,不需要增强可以不配knife4j: # 是否启用增强设置 enable: true # 是否启用登录认证 basic: enable: true username: admin password: 123456 setting: language: zh_cn enable-version: true enable-swagger-models: true swagger-model-name: 用户模块

过滤静态资源:

Spring MVC配置类,主要用于处理网站图标(favicon.ico)的请求

import jakarta.servlet.http.HttpServletRequest;import jakarta.servlet.http.HttpServletResponse;import org.springframework.boot.SpringBootConfiguration;import org.springframework.http.HttpStatus;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/** * @Classname FaviconConfiguration * @Description 添加配置文件,处理favicon.ico请求 * @Version 1.0.0 * @Date 2025/5/26 13:39 * @Created by Administrator */@SpringBootConfigurationpublic class FaviconConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new HandlerInterceptor() { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (!\"GET\".equalsIgnoreCase(request.getMethod()) || !request.getRequestURI().toString().equals(\"/favicon.ico\")) {  return true; } response.setStatus(HttpStatus.NO_CONTENT.value()); // 设置状态码为204 No Content return false; } }).addPathPatterns(\"/**\"); }}

 增强模式:

自定义生成的Swagger/OpenAPI文档的展示信息,提供一些项目信息或者个人的信息。

import io.swagger.v3.oas.models.OpenAPI;import io.swagger.v3.oas.models.ExternalDocumentation;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;import java.util.ArrayList;import java.util.List;/** * Swagger2配置信息 * 这里分了两组显示 * 第一组是api,当作用户端接口 * 第二组是admin,当作后台管理接口 * 也可以根据实际情况来减少或者增加组 * * @author eleven_lxs * @date 2025-05-26 22:17 */@Configurationpublic class SwaggerConfig { @Bean public OpenAPI swaggerOpenAPI(){ return new OpenAPI() .info(new Info().title(\"标题\") // 信息 .contact(new Contact().name(\"作者\").email(\"邮箱\").url(\"地址\")) // 简介 .description(\"我的API文档\") // 版本 .version(\"v1\") // 许可证 .license(new License().name(\"Apache 2.0\").url(\"http://springdoc.org\"))) .externalDocs(new ExternalDocumentation() .description(\"外部文档\") .url(\"https://springshop.wiki.github.org/docs\")); }}

便捷地址访问:

 而为了方便直接通过点击地址直接访问,我们编写配置类帮助我们直接访问:

import io.micrometer.common.util.StringUtils;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.context.event.ApplicationReadyEvent;import org.springframework.context.ApplicationListener;import org.springframework.context.annotation.Configuration;import org.springframework.core.env.Environment;import java.net.InetAddress;import java.net.UnknownHostException;import java.util.Arrays;import java.util.Optional;/** * @Classname DocumentationConfig * @Description TODO * @Version 1.0.0 * @Date 2025/5/26 15:28 * @Created by Administrator */@Configuration@Slf4jpublic class DocumentationConfig implements ApplicationListener { @Autowired private Environment env; @Override public void onApplicationEvent(ApplicationReadyEvent event) { String protocol = env.getProperty(\"server.ssl.key-store\") != null ? \"https\" : \"http\"; System.out.println(env); // 获取端口(添加默认值8080) String serverPort = env.getProperty(\"server.port\", \"8000\"); // 处理contextPath(避免null拼接) String contextPath = Optional.ofNullable(env.getProperty(\"server.servlet.context-path\")) .orElse(\"\"); String docPath = contextPath + \"/doc.html\"; // 获取主机地址 String hostAddress; try { hostAddress = InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { hostAddress = \"localhost\"; log.warn(\"无法获取主机IP,使用默认地址: localhost\"); } log.info(\"\"\" ---------------------------------------------------------- \\t应用程序 \"{}\" 已启动 \\t文档访问地址: \\t本地: \\t{}://localhost:{}{} \\t外部: \\t{}://{}:{}{} \\t激活配置: \\t{} ----------------------------------------------------------\"\"\", env.getProperty(\"spring.application.name\", \"默认应用\"), protocol, serverPort, docPath, protocol, hostAddress, serverPort, docPath, Arrays.toString(env.getActiveProfiles())); }}

常见问题: 

如果是开发微服务,这里可能会出现 http://localhost:63040/doc.html ,这里我的问题是出自在bootstrap.yml是Spring Cloud的配置文件,但在普通Spring Boot应用中不会自动加载,如果想使用,要添加spring-cloud-starter-bootstrap依赖才能生效:

 org.springframework.cloud spring-cloud-starter-bootstrap 4.1.5 

随后在启动类下面可以添加代码进行测试:

@SpringBootApplicationpublic class ContentApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(ContentApplication.class, args); printEnvInfo(context); } private static void printEnvInfo(ConfigurableApplicationContext context) { Environment env = context.getEnvironment(); System.out.println(\"\\n=== 应用配置信息 ===\"); System.out.println(\"应用名称: \" + env.getProperty(\"spring.application.name\")); System.out.println(\"服务端口: \" + env.getProperty(\"server.port\")); System.out.println(\"上下文路径: \" + env.getProperty(\"server.servlet.context-path\")); System.out.println(\"激活Profile: \" + Arrays.toString(env.getActiveProfiles())); System.out.println(\"数据库URL: \" + env.getProperty(\"spring.datasource.url\")); System.out.println(\"Swagger路径: \" + env.getProperty(\"springdoc.swagger-ui.path\")); }}

 而我为了方便,我直接配置了一个新的application.yml,发现一样好使:

server: port: 63040

另外如果还是没有显示,那么去检查你的 SecurityConfig 配置,确保 SecurityConfig 放行所有文档路径:

@Configurationpublic class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers(  \"/content/swagger-ui/​**​\",  \"/content/v3/api-docs/​**​\",  \"/content/doc.html\",  \"/content/webjars/​**​\" ).permitAll() .anyRequest().authenticated() ); return http.build(); }}

注解使用实例: 

import com.xuecheng.base.model.PageParams;import com.xuecheng.base.model.PageResult;import com.xuecheng.content.model.dto.QueryCourseParamsDto;import com.xuecheng.content.model.po.CourseBase;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.Parameter;import io.swagger.v3.oas.annotations.tags.Tag;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;import java.time.LocalDateTime;import java.util.ArrayList;import java.util.List;@Tag(name = \"课程信息管理接口\", description = \"课程信息管理接口\") // 替代 @Api@RestControllerpublic class CourseBaseInfoController { @Operation(summary = \"课程查询接口\") // 替代 @ApiOperation @PostMapping(\"/course/list\") public PageResult list( @Parameter(description = \"分页参数\") PageParams pageParams, // 替代 @ApiParam @Parameter(description = \"查询条件\") @RequestBody(required = false) QueryCourseParamsDto queryCourseParamsDto ) { CourseBase courseBase = new CourseBase(); courseBase.setName(\"测试名称\"); courseBase.setCreateDate(LocalDateTime.now()); List courseBases = new ArrayList(); courseBases.add(courseBase); return new PageResult(courseBases, 10, 1, 10); }}
import lombok.Data;import lombok.ToString;import io.swagger.v3.oas.annotations.media.Schema;@Data@ToString@Schema(name = \"PageParams\", description = \"分页查询参数\") // 类级别描述(可选)public class PageParams { @Schema(description = \"页码\", example = \"1\", defaultValue = \"1\") private Long pageNo = 1L; @Schema(description = \"每页记录数\", example = \"30\", defaultValue = \"30\") private Long pageSize = 30L; public PageParams() { } public PageParams(Long pageNo, Long pageSize) { this.pageNo = pageNo; this.pageSize = pageSize; }}