☰
Spring Boot 3 下用 Knife4j 4.x 替代 Swagger2 的完整落地指南
2026/10/10 7:30:19 网站建设 项目流程

1. 为什么 Spring Boot 3 一升级,Swagger2 就得靠边站

先交代个背景:我参与过一次内部项目升级,从 Spring Boot 2.7 升到 3.x,最先把人搞崩的不是业务代码,而是 API 文档。pom 里还留着springfox-boot-starter 3.0.0的依赖,应用启动直接报类加载冲突。一开始我以为是版本号写错了,查了半天才发现根子不在这,真正的坑是 Spring 6 彻底淘汰了javax.servlet这一套 API。

Spring Boot 3 上来就是三个硬变化:JDK 17 起步、Spring Framework 6、原来一堆javax.*的包全换成jakarta.*。而 Springfox 这个项目最后稳定版基本停留在 2020 年,之后就没有实质性的跟进。它内部依赖的是老旧的javax.*和旧版 spring-plugin,在 Spring Boot 3 上运行属于先天残疾。网上有人通过替换依赖、改编译参数强行让 Springfox 跑起来,但 Spring 6 的 Servlet API 已经全部切到jakarta.servlet,类库内部反射、组件扫描照样会踩雷。为了一个文档工具逼着整个工程吃补丁,非常不值得。

1.1 单是 javax 换 jakarta,就够淘汰一批老库

把javax.servlet改成jakarta.servlet,表面上只是包名变了,实际上对类库生态是一次大清洗。老库在编译时写死了javax.servlet的 import,运行时如果找不到对应的类,直接抛出NoClassDefFoundError。更隐蔽的是,有些库不直接依赖 Servlet API,而是通过反射去加载javax.servlet.Filter、javax.servlet.http.HttpServletRequest这类类名,这类问题在编译期根本发现不了,只有请求打过来才炸。

Springfox 正好踩在两组问题上。它既要适应 Spring MVC 6 的 Handler 机制,又要处理 Jakarta Servlet 环境的类加载,而这两个改动都不是简单换个包名能糊弄过去的。就算你在 pom 里手动引入jakarta.servlet-api和对应的旧类桥接包,Springfox 里的springfox.documentation.spring.web那套组件依然会扫描到不兼容的类,导致启动时 Bean 创建失败。所以结论很直接:Spring Boot 3 上别再碰 Swagger2 的老链路。

1.2 Knife4j 4.x 掉头转向 OpenAPI 3,是顺势而为

Knife4j 在早期版本里一直依托 Springfox,所以很多老项目用 Knife4j 2.x 配 Swagger2 配得很爽。但到了 Spring Boot 3 时代,Springfox 自己已经不动了,Knife4j 只能换底座。4.x 版本开始,Knife4j 底层直接切换到 springdoc-openapi,注解体系从io.swagger.annotations换成io.swagger.v3.oas.annotations,文档规范也从 OpenAPI 2 升级到 OpenAPI 3。

这意味着如果你打算在 Spring Boot 3 上用 Knife4j,就不再是简单地把旧依赖换个坐标,而是要接受一套新的注解命名习惯。比如类上的@Api要改成@Tag,方法上的@ApiOperation要改成@Operation,参数上的@ApiParam要改成@Parameter。虽然这些改动很机械,但不少人就是卡在“只换了依赖、没换注解”这一步,启动是正常了,打开文档却什么都看不到,原因就是 springdoc 根本不扫描旧版 Swagger2 注解。这篇文章后面会专门讲这套迁移清单。

所以标题说“不带 Swagger2 玩”,不是口号,而是 Spring Boot 3 升级路上绕不开的选择。想继续用 Knife4j 的炫酷 UI,想获得 OpenAPI 3 的完整能力,就应该直接站到 Knife4j 4.x 的新链路上来。

2. 版本血缘理清楚,再动手填依赖

整合 Knife4j 这类组件,第一件事不是抄依赖,而是先确认版本血缘。被 Spring Boot 3 坑过的人都知道,光把 spring-boot-starter-parent 版本从 2.7 改成 3.2,工程里一大堆 starter 都可能失效。Knife4j 也一样,接口工程选错依赖坐标,后面全是连锁反应。

2.1 JDK 17 不是推荐,是底线

Spring Boot 3 官方要求 JDK 17 以上,Knife4j 4.x 的 Jakarta 版本也按这个基线编译。如果你还在 JDK 8 或 JDK 11 上做测试,编译阶段大概率会报UnsupportedClassVersionError或invalid target release这类错误。这一步没太多技巧,就是老老实实把项目 JDK 版本切换到 17 或 21,Maven 的java.version属性也同步改掉。

我建议在 pom 里直接这样写,避免 IDE 和命令行行为不一致:

<properties> <java.version>17</java.version> <spring-boot.version>3.2.5</spring-boot.version> </properties>

Spring Boot 3.2 之后的版本对springdoc-openapi的要求也更高了,后面我会专门提这一点。

2.2 Spring Boot 2.x 和 3.x 的 Knife4j starter 不是同一个

Knife4j 4.x 为了适配两代生态,准备了两个官方 starter:

项目环境依赖坐标
Spring Boot 2.4 ~ 2.7knife4j-openapi3-spring-boot-starter
Spring Boot 3.xknife4j-openapi3-jakarta-spring-boot-starter

光看名字就知道,Spring Boot 3 对应的版本专门带了 “jakarta” 标识。很多同学直接把老项目里的knife4j-openapi3-spring-boot-starter复制到 Spring Boot 3 工程里,结果就是各种类冲突或文档页面白屏。Spring Boot 3 工程请认准这个坐标:

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

另外要注意,这个 starter 会传递依赖springdoc-openapi-starter-webmvc-ui,所以一般情况下不需要你再手动引入 springdoc。如果你项目中已经有 springdoc,尽量让版本跟着 Knife4j 传递进来的版本走,不要自己固定一个老的 springdoc 1.x,否则会出现接口扫描不到、OpenAPI 版本不匹配等问题。

2.3 Spring Boot 3.0 / 3.1 / 3.2 之后,版本选择有细微差别

Knife4j 4.3.0 在 Spring Boot 3.0、3.1 上跑得挺稳,但到了 Spring Boot 3.2 之后,Spring Framework 对静态资源的处理逻辑有变化,继续用太旧的 Knife4j 可能会遇到静态资源映射异常。我实际碰到过的情况是:控制器和接口列表都正常,但/doc.html打不开,控制台报NoResourceFoundException,最后排查下来是 Knife4j 版本停留在 4.3.0,传递依赖的 springdoc 版本偏老,升级到 4.4.0 之后问题消失。

所以我的建议很简单:Spring Boot 3.2 及以上版本,Knife4j 直接上 4.4.0 或 4.5.0;Spring Boot 3.0/3.1 用 4.3.0 问题也不大,但为了减少以后升级的麻烦,直接用 4.5.0 更省心。版本选对了,后面 90% 的兼容问题都不会出现。

3. 最小可运行工程:两个配置文件加一段注解

下面这套配置是我个人比较喜欢的最小结构。它不含任何多余插件,就是把 Spring Boot 3 Web 工程和 Knife4j 串起来,跑通后你再去加分组、认证这些增强功能。

3.1 pom.xml 里真正必需的依赖

除了基础的 spring-boot-starter-web,核心就是 Knife4j 官方 starter。lombok 看个人习惯,不影响 Knife4j。

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>

这里要强调一个容易踩的坑:如果工程里还有残留的springfox-boot-starter,最好用 Maven 依赖树确认后移除。两个文档组件一起存在时,io.swagger.annotations和io.swagger.v3.oas.annotations的类名非常相似,但包不同,IDE 里可能看不出大问题,实际运行时注解扫描结果会一团糟。我在合作项目里见过 pom 里同时引了 Springfox 和 Knife4j,结果文档页面能打开,但所有接口都被识别成 “default”,分组和描述全部丢失。查了半天,就是依赖冲突。

3.2 application.yml 的关键配置

Knife4j 4.x 的配置项其实不多,下面是常用的一段:

springdoc: packages-to-scan: com.example.demo.controller paths-to-match: /** api-docs: enabled: true path: /v3/api-docs swagger-ui: path: /swagger-ui.html knife4j: enable: true setting: language: zh_cn

springdoc.packages-to-scan用于告诉 springdoc 扫描哪个包下面的 Controller,默认会从启动类所在包往下扫。如果你的 Controller 不在启动类包路径下,就一定要显式写出来,不然后面打开文档会发现接口列表是空的。这里的坑非常多,下一节我会专门展开。

knife4j.enable负责开启 Knife4j 的增强功能,setting.language则让 UI 显示中文。这两个配置对最终体验影响很大,建议保留。

3.3 OpenAPI 信息配置类

接下来写一个配置类,主要目的是设置文档标题、描述、版本号。有人嫌这一步多余,但实际团队协作中,版本号写清楚能让前端和测试一眼看出当前环境用的是哪版接口定义。

package com.example.demo.config; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class OpenApiConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title("用户服务 API 文档") .description("面向小程序端、管理后台开放的接口定义") .version("v1.0.0") .contact(new Contact() .name("后端组") .email("backend@example.com"))); } }

注意这里的OpenAPI类是io.swagger.v3.oas.models.OpenAPI,不是老版本里那个不存在的东西。引入包名错了,编译直接失败,这个最容易一眼看出来,但有些人会顺手改成别的类导致后续 bean 注入不了。

3.4 Controller 里放一套标准注解

Controller 本身不复杂,关键是注解要放到正确位置。我写了一个用户查询接口做演示:

package com.example.demo.controller; import com.example.demo.common.Result; 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.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("/api/users") @Tag(name = "用户管理", description = "用户模块的查询与管理接口") public class UserController { @GetMapping("/{id}") @Operation(summary = "根据ID查询用户", description = "返回用户基本信息,不包含敏感字段") public Result<UserVO> getUser( @Parameter(description = "用户ID", example = "10001") @PathVariable("id") Long id) { return Result.success(new UserVO(id, "测试用户")); } @GetMapping @Operation(summary = "查询用户列表") public Result<List<UserVO>> listUsers() { return Result.success(List.of()); } }

@Tag写在类上,@Operation写在方法上,@Parameter写在参数上。这套注解跟 Swagger2 时代习惯完全不同,但结构很清晰:一个类对应一个模块,一个方法对应一个接口。只要 Controller 被正常扫描,Knife4j 就能自动把接口信息渲染到页面上。

3.5 启动后先看哪个地址

跑起来以后,有几个地址需要熟悉:

地址作用
/doc.htmlKnife4j 增强版 UI,日常主要看这个
/v3/api-docs原始 OpenAPI JSON 数据
/swagger-ui/index.htmlspringdoc 自带的原生 Swagger UI 页面

我先看的永远是/v3/api-docs。这个页面返回的是 JSON 纯数据,如果这里的paths里有接口,说明扫描正常;如果/doc.html打不开,问题出在 UI 层;如果 JSON 里paths是空的,说明 Controller 扫描配置有问题。这个排查顺序能帮你省下大量时间。

4. 文档打不开或接口空列表,按这个次序排查

项目跑起来后,真正麻烦的往往不是配置过程,而是启动成功但文档页面表现不正常。我把自己碰过的几种典型情况汇总一下,每类问题后面都会给排查方向和解决办法。

4.1 先把问题定位到 UI 层还是数据层

出现异常时,先别盯着/doc.html的报错猜原因。按我的习惯,第一步就是打开/v3/api-docs,看它能不能正常返回 JSON。这一步能把问题切成两大块:JSON 正常,说明后端接口扫描没问题,UI 加载不出来多半是静态资源被拦截;JSON 本身返回空paths,那就是扫描范围或路径匹配的锅。

我还见过一种情况是/v3/api-docs返回了 401,这就直接说明安全策略把文档接口拦了,跟 Knife4j 本身的配置毫无关系。先去调 Spring Security 或网关白名单,再回来检查 UI。

4.2 Spring Security 拦住了静态资源

这是最常见的一类问题。Spring Boot 3 里的 Spring Security 6 写法变了,安全过滤链如果不放行文档相关路径,那/doc.html要么直接 401,要么页面能出来但里面的 CSS/JS 被拦,导致样式全丢。

下面是一个最精简的安全放行配置片段:

@Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth .requestMatchers( "/doc.html", "/webjars/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/favicon.ico" ).permitAll() .anyRequest().authenticated() ); return http.build(); }

Spring Security 6 里,.antMatchers已经被更直白的.requestMatchers取代。如果你还沿用老写法,编译或启动阶段可能就直接报错。放行路径别偷懒,/webjars/**漏掉的话,Knife4j UI 会白屏得非常彻底。

4.3 包扫描和路径匹配把接口藏起来了

如果/v3/api-docs返回正常,但paths是空对象,绝大多数情况是springdoc.packages-to-scan配错了。比如 Controller 在com.example.demo.controller,你写成了com.example.demo,有的版本也能扫到,但如果你项目结构更复杂,包路径差一级就可能漏掉整个模块。

还有paths-to-match,这东西更像是一道闸门。假设你配的是/api/admin/**,而接口实际在/api/user/**,那即使 Controller 被扫描到了,openapi 数据里也不会展示这些接口。我建议没有特殊需求时先写成/**,把闸门放开,确认所有接口都能看到后,再按模块去收敛。

这里有个实用技巧:如果你想快速验证扫描规则,直接把springdoc.packages-to-scan改大,扫到启动类所在的根包,通常不会有遗漏。如果接口多到需要分类,再考虑用分组,而不是把扫描范围抠得太细。

4.4 MVC 拦截器对 webjars 开火

很多项目会自定义 WebMvc 拦截器,用来做登录态校验、操作日志记录。Knife4j 的静态资源很多来自/webjars/**路径,如果拦截器的排除名单里没加这些路径,页面就会出现 CSS 加载不了、控制台一堆 404。

排除路径参照下面这样写,放在WebMvcConfigurer里:

registry.addInterceptor(loginInterceptor) .addPathPatterns("/**") .excludePathPatterns( "/doc.html", "/webjars/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/favicon.ico" );

拦截器跟 Spring Security 是两个层面的东西,有人配好了 Security 放行但没配拦截器,一样打不开页面。检查的时候记得两层都看一眼。

4.5 context-path、网关前缀和资源相对路径

如果应用配置了server.servlet.context-path,比如/app,那 Knife4j 页面访问地址就是/app/doc.html。正常情况下 Knife4j 会自动基于上下文生成资源引用路径,问题大多出在网关或 nginx 二次改写前缀的场景。

举个例子,网关把请求从/gateway/app/doc.html改写成/app/doc.html再转发到后端,前端 JS 在做资源拼接时可能认为当前上下文是/gateway/app,于是去请求/gateway/app/webjars/**,而后端根本没有这个路径,页面就崩了。经验是:网关层尽量透传原始路径,不要层层剥离前缀;如果实在有特殊需求,建议先检查页面最终的静态资源 URL 和后端实际暴露路径是否对齐。

4.6 Spring Boot 3.2+ 和旧版本 Knife4j 的兼容问题

我遇到过 Spring Boot 从 3.1 升到 3.2 后,Knife4j 页面打不开,控制台出现NoResourceFoundException,指向静态资源处理器。排查下来不是代码问题,而是 Knife4j 4.3.0 携带的 springdoc 版本对 Spring Boot 3.2 的静态资源匹配逻辑兼容性不够。

解决方案就是升级 Knife4j 到 4.4.0 以上。升级之后还是同样的代码和配置,/doc.html直接恢复。这也再次验证了我前面的观点:Spring Boot 3.2 及以上版本,不要在 Knife4j 版本上太保守。

4.7 一个典型问题速查表

现象可能原因处理方向
/doc.html白屏Security 或拦截器拦截/webjars/**放行静态资源路径
JSON 正常但 UI 空静态资源 404检查拦截器和反向代理前缀
JSON 的 paths 空包扫描或路径匹配不对调整packages-to-scan和paths-to-match
启动报类冲突同时存在 Springfox 和 Knife4j移除 Springfox 依赖
Boot 3.2+ 静态资源报错Knife4j 版本太老升级到 4.4.0 以上

5. 三个高频进阶功能:Bearer 认证、分组、生产开关

基础跑通之后,绝大多数项目还需要解决三个问题:接口文档里带 Token 调试、按模块拆分组、生产环境控制文档能不能看。这三个功能属于“不一定当场需要,但用到时能大大提升效率”的类型。

5.1 在 Knife4j 里注入全局 Bearer Token

现在很多后端接口用 JWT 做认证,前端在 Knife4j 页面调试时,如果不能让每个请求自动带上Authorization: Bearer xxx,体验非常割裂。Knife4j 4.x 支持 OpenAPI 3 的 Security Scheme,只需要在配置类里声明一下。

修改前面的OpenApiConfig:

@Configuration public class OpenApiConfig { @Bean public OpenAPI customOpenAPI() { String schemeName = "bearerAuth"; return new OpenAPI() .components(new Components() .addSecuritySchemes(schemeName, new SecurityScheme() .type(SecurityScheme.Type.HTTP) .scheme("bearer") .bearerFormat("JWT"))) .addSecurityItem(new SecurityRequirement().addList(schemeName)) .info(new Info() .title("用户服务 API 文档") .version("v1.0.0")); } }

配置完之后,Knife4j 页面右上角会多出一个 Authorize 按钮,点进去把 Token 填好,后面请求就能自动带认证头。这个配置对没有安全需求的项目是多余的,但如果你的接口统一走 JWT,建议从第一天就加上。

5.2 给文档站本身再加一道 Basic 登录

有些团队不希望文档完全公开,但又不想为了文档单独接一套权限系统。Knife4j 提供了内置的 Basic 认证开关,配置非常简单:

knife4j: basic: enable: true username: api-docs password: ${DOC_PASSWORD}

注意,这里的密码如果直接写在 yaml 里,会进入版本库,团队内部还好,对外开放的项目建议通过环境变量注入。打开/doc.html时浏览器会先弹出一个登录框,认证通过后才能看到文档内容。这个方案适合做内部测试环境的轻量保护,不适合当生产环境的安全边界。

5.3 按模块拆分组,避免文档变成一个巨型列表

当接口数量上来以后,所有 Controller 挤在一个文档里会非常难用。拆分组有两种常见方式,你可以按取向选择。

一种是用 yaml 配置快速拆分:

springdoc: group-configs: - group: 用户端 packages-to-scan: com.example.demo.controller.user - group: 管理端 packages-to-scan: com.example.demo.controller.admin

另一种是用 Java Bean 做更灵活的路径匹配:

@Bean public GroupedOpenApi userApi() { return GroupedOpenApi.builder() .group("用户端") .pathsToMatch("/api/user/**") .packagesToScan("com.example.demo.controller.user") .build(); } @Bean public GroupedOpenApi adminApi() { return GroupedOpenApi.builder() .group("管理端") .pathsToMatch("/api/admin/**") .packagesToScan("com.example.demo.controller.admin") .build(); }

拆分之后,Knife4j 页面左侧会出现分组下拉选择。这样前端可以直接切到自己关心的模块,不用在几百个接口里反复搜索。需要提醒的是,分组和springdoc.packages-to-scan的配置最好不要同时写得太复杂,确定一种主方式,否则会出现同一个接口被重复扫描进多个分组的情况。

5.4 生产环境一键关闭文档

文档工具是双刃剑,开发环境可以开,生产环境最好关。Knife4j 本身提供了两个开关:

knife4j: production: true springdoc: api-docs: enabled: false

knife4j.production设置为 true 后,文档访问入口会关闭;springdoc.api-docs.enabled设置为 false 后,/v3/api-docs这个数据接口也会失效。两者一起配置,基本可以达到生产环境不出文档的效果。

如果你的生产环境希望保留文档,但只对特定运维人员开放,那就别用这个全局开关,改用 5.2 里的 Basic 认证更合适。这个取舍取决于团队的管理风格,没有绝对标准。

6. 从 Springfox 老注解迁到 OpenAPI 3 的机械清单

最后说一件很多人到了真正迁移时才发现的事:Knife4j 4.x 和 Spring Boot 3 配套注解体系,已经不是原来那套 Swagger2 注解了。项目越大,这种替换越容易出错。

6.1 注解对应表,直接照着改

我整理了一张最常见的对应关系,绝大多数项目迁移时只需要做这些替换:

Springfox / Swagger2OpenAPI 3 / Knife4j
@Api@Tag
@ApiOperation@Operation
@ApiParam@Parameter
@ApiModel@Schema
@ApiModelProperty@Schema(description = "...")
@ApiImplicitParam@Parameter
@ApiImplicitParams@Parameters
@ApiResponse@ApiResponse(包名变了)

@ApiResponse是最容易迷惑的地方,因为注解短名没变,但 import 包从io.swagger.annotations.ApiResponse换成了io.swagger.v3.oas.annotations.responses.ApiResponse。如果只改注解不换包,启动不报错,文档里却永远看不到响应说明。

6.2 更新 import 是重点,不是细节

Springdoc 只认io.swagger.v3.oas.annotations下的注解,这一点决定了你必须把每个 Controller 和 DTO 类上的 import 全部换掉。我见过一个项目从旧框架迁移过来,第一轮只改了依赖坐标,启动一切正常,结果打开文档发现所有接口都没有描述,连接口名都是空白的。查下来才发现代码里还在用io.swagger.annotations.@ApiOperation,这相当于把 Windows 的快捷键带到了 Mac 上用,看着熟悉,实际无效。

需要经常用到的 import 大概这些:

import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses;

6.3 DTO 字段上的 @Schema 写法

老项目里@ApiModelProperty的写法是这样的:

@ApiModelProperty(value = "手机号", example = "13800000000") private String mobile;

迁移到 OpenAPI 3 后,只要把注解换成@Schema,几乎可以平替:

@Schema(description = "手机号", example = "13800000000") private String mobile;

如果字段是必填项,可以用requiredMode = Schema.RequiredMode.REQUIRED,比老版本的required = true语义更明确。对于使用Result<T>这类统一响应体的项目,建议把泛型里的 T 落到具体 VO 类,而不是用 Map 返回,否则 springdoc 无法准确推导字段结构,文档里只会看到Map两个字母,完全没有字段信息。

6.4 统一响应体的泛型推导,值得花半小时检查

很多团队的 Controller 返回结构都是统一的,比如Result<UserVO>、PageResult<OrderVO>。springdoc 对泛型推导是支持的,但前提是泛型参数在返回值类型里明确出现。如果你偷懒把方法返回类型写成Result,不带尖括号,或者用Map<String, Object>拼数据,那文档里的 response schema 会非常难看。

我在项目里处理过一个接口,返回类型是Result<Map<String, Object>>,Knife4j 页面渲染出来就是一个光秃秃的Map,没有任何字段说明。后来把接口改成真正的 VO 类,文档立刻清晰很多。这件事不算 Knife4j 的配置问题,而是规范问题,值得在代码评审时统一要求。

最后分享一个我自己养成的习惯:每次升级依赖后,第一件事不是打开doc.html看 UI,而是先请求/v3/api-docs,确认paths里的数据是否齐全。只要这层数据是对的,UI 层的问题通常几分钟就能定位;如果数据本身缺接口,那就回到扫描配置和注解检查。另一件顺手做掉的小事,是给每个@Operation的 description 写一句话业务语义,而不是只填“接口描述”四个字。短时间内看不出差别,等项目过几千行接口描述以后,你会感谢当初那个没偷懒的自己。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询