目录

引言: 

引入依赖: 

配置文件: 

过滤静态资源:

 增强模式:

便捷地址访问:

常见问题: 

注解使用实例: 


📄 ​文档参考地址​:
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 包)。 

<!-- 删除这些 Springfox 依赖 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.10.5</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.10.5</version>
</dependency>

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 项目中使用。

引入依赖: 

首先引入依赖:

<!--   添加swagger核心依赖-->
<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-core</artifactId>
    <version>2.2.20</version>
</dependency>
<!--添加knife4j依赖-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.4.0</version>
</dependency>
<!--添加Springdoc依赖-->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
<!--仅添加上述依赖,仍有可能报错,需补充以下依赖-->
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
    <version>2.13.3</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.4.0-b180830.0359</version>
</dependency>

配置文件: 

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

引入配置文件,这里因为我在开发微服务,所以在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
 */
@SpringBootConfiguration
public 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
 */
@Configuration
public 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
@Slf4j
public class DocumentationConfig implements ApplicationListener<ApplicationReadyEvent> {


    @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依赖才能生效:

<!-- 使bootstrap.yml生效 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-bootstrap</artifactId>
    <version>4.1.5</version> <!-- 与Spring Boot版本匹配 -->
</dependency>

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

@SpringBootApplication
public 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 放行所有文档路径:

@Configuration
public 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
@RestController
public class CourseBaseInfoController {

    @Operation(summary = "课程查询接口")  // 替代 @ApiOperation
    @PostMapping("/course/list")
    public PageResult<CourseBase> list(
            @Parameter(description = "分页参数") PageParams pageParams,  // 替代 @ApiParam
            @Parameter(description = "查询条件") @RequestBody(required = false) QueryCourseParamsDto queryCourseParamsDto
    ) {
        CourseBase courseBase = new CourseBase();
        courseBase.setName("测试名称");
        courseBase.setCreateDate(LocalDateTime.now());
        List<CourseBase> 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;
    }
}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐