一、背景与痛点
目前项目现状:老平台基于 Freemarker 传统架构,新业务模块采用 Spring Boot 3 + Vue 前后端分离模式,前端开发总吐槽接口不清晰。
以往团队一直用 Apipost、Torna 维护接口文档,踩坑无数:
- 接口字段、必填项标注混乱,前后端对接经常扯皮;
- 第三方文档工具无法在线调试,还要手动复制参数;
- 跨域、Token 校验问题频发,前端总以 “文档不准” 甩锅后端;
- 文档和代码不同步,代码改了文档忘改,久而久之形同虚设。
实际诉求很简单:一套和代码强同步、支持在线调试、有权限拦截、能复用老平台登录态的一体化 API 文档方案。
二、技术选型对比
Spring Boot 3 已全面弃用 Springfox,传统 Swagger2 直接兼容不了,先做方案对比:
表格
| 技术方案 | 优点 | 缺点 | 选型 |
|---|---|---|---|
| Swagger2 + Springfox | 生态老牌、使用习惯成熟 | 早已停更,不兼容 Spring Boot3、Jakarta 规范 | ❌ 放弃 |
| Torna 接口文档 | 代码无强侵入、集中管理 | 依赖额外部署、跨域问题多、前端适配一般 | ❌ 放弃 |
| SpringDoc + Knife4j | 兼容 OpenAPI3、适配 Boot3、界面美观、支持分组、权限易控 | 需要少量注解规范 | ✅ 最终选用 |
最终敲定:SpringDoc + Knife4j 4.5.0,适配 Spring Boot3,一站式解决 API 文档、在线调试、登录态复用三大问题。
三、实战完整落地步骤
3.1 引入 Maven 依赖
Spring Boot 3.x 必须引入jakarta版本,不要引旧的 javax 包:
xml
<!-- Knife4j 整合SpringDoc 适配SpringBoot3 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> </dependency>3.2 全局配置类(分组 + 文档基础信息)
支持按模块、按接口路径做多文档分组,方便前后端按业务查看:
java
运行
import io.swagger.v3.oas.annotations.info.Contact; import io.swagger.v3.oas.annotations.info.Info; import io.swagger.v3.oas.models.OpenAPI; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import springdoc.group.GroupedOpenApi; @Configuration public class Knife4jConfig implements WebMvcConfigurer { /** * 系统管理模块接口分组 */ @Bean public GroupedOpenApi adminApi() { return GroupedOpenApi.builder() .group("系统管理模块") .packagesToScan("com.xxx.system.controller") .pathsToMatch("/admin/**") .build(); } /** * 业务模块接口分组 */ @Bean public GroupedOpenApi bizApi() { return GroupedOpenApi.builder() .group("业务业务模块") .packagesToScan("com.xxx.biz.controller") .pathsToMatch("/biz/**") .build(); } /** * 文档全局基础信息 */ @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title("项目统一API接口文档") .version("V1.0") .contact(new Contact().name("后端研发")) .description("基于SpringBoot3 + Knife4j 自动生成接口文档")); } }3.3 标准注解使用规范
控制器层注解
java
运行
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; @RestController @RequestMapping("/admin/user") @Tag(name = "系统用户管理") public class UserController { @Operation(summary = "用户分页列表查询") @GetMapping("/list") public Result<PageResult<UserVO>> listUser(UserQuery query) { // 业务逻辑省略 } }实体类参数注解
用@Schema描述字段、示例值、是否必填:
java
运行
import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @Data @Schema(description = "用户查询条件") public class UserQuery { @Schema(description = "用户姓名-模糊查询", example = "张三") private String userName; @Schema(description = "账号状态 0-禁用 1-正常", allowableValues = {"0","1"}, example = "1") private Integer status; @Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13800138000") private String phone; }requiredMode = REQUIRED:标记接口必填字段,文档自动标红;example:给调试提供默认示例值,前端直接可用。
3.4 隐藏内部接口避坑
很多人直接用@Hidden注解,容易出现整个 Controller 接口全部消失的 BUG。
推荐标准写法:只隐藏单个接口,不影响其他接口展示
java
运行
@Operation(summary = "内部回调接口,文档隐藏", hidden = true) @PostMapping("/inner/callback") public Result callback() { // 内部逻辑 }3.5 权限控制:未登录禁止访问文档
常规做法是在 Spring Security 放行文档路径,任何人都能看,不安全。
改造思路:取消文档路径匿名放行删除 SecurityConfig 中如下配置:
java
运行
// 删掉这段匿名放行 // .requestMatchers("/doc.html","/v3/api-docs/**","/swagger-ui/**").permitAll()效果验证:浏览器无痕模式直接访问项目地址/doc.html,自动 302 重定向到登录页,必须登录后才能查看接口文档。
3.6 集成老平台,复用已有登录态
老平台基于 Freemarker 模板,直接在顶部菜单 / 个人下拉菜单中加入文档入口:
html
预览
<a class="dropdown-item" href="/doc.html" target="_blank"> <i class="fas fa-file-alt"></i> 接口文档 </a>原理:从老平台菜单点击跳转,自动携带当前登录 Cookie,无需二次登录,直接进入文档页面,完美复用现有登录体系。
配置完成并部署上线后,即可直接访问接口文档首页,分组管理、接口统计、必填字段标注全部生效,支持在线调试,且已接入权限控制,复用老平台登录态,无需额外登录即可查看文档:
四、实战踩坑记录汇总
@Hidden 导致整个控制器接口消失解决:弃用类上 @Hidden,改用
@Operation(hidden = true)只隐藏单个接口。配置分组后接口不显示解决:核对
packagesToScan包路径 和pathsToMatch接口前缀必须严格对应。访问文档 401 不跳转登录页解决:登录接口、静态资源务必在 Security 中正常放行,配置登录跳转规则。
文档在线调试跨域 / 无权限解决:必须保持登录状态,携带登录 Cookie 再调试,和业务接口鉴权逻辑统一。
五、总结
- Spring Boot3 不要再用老旧 Swagger2,SpringDoc + Knife4j 是最优解;
- 隐藏接口优先用
@Operation(hidden = true),避开全局隐藏坑; - 接口文档一定要做登录拦截,不能公开匿名访问;
- 嵌入老平台菜单复用登录态,省去单独做文档登录模块,极简高效;
- 代码注解即文档,一改全改,彻底告别手动维护 API 文档、前后端扯皮的问题。
一套规范的自动 API 文档,不光是方便前端,更是规范接口、划清责任、减少后期维护成本,把重复体力活交给框架,自己专注核心业务和架构沉淀。
本文是《技术底稿》系列第 28 篇,记录 Spring Boot3 整合 Knife4j+SpringDoc 完整实战,包含依赖引入、分组配置、注解规范、接口隐藏避坑、权限拦截及老平台登录态复用全流程,落地可直接复用到现有项目,解决手写 API 文档、前后端对接扯皮的日常痛点。