接口文档的滞后会直接影响前后端协作效率。Swagger 通过读取 Spring MVC 的路由映射和方法签名自动生成 API 描述,配合 Swagger UI 提供在线调试能力,相当于让代码本身成为了一直保持更新的文档源。Java 项目集成 Swagger 并不是简单加一个依赖就能结束,选型、注解、安全策略都会影响最终使用体验。下面围绕 Spring Boot 生态,整理一套可直接落地的接入方案。

一、先分清Swagger、OpenAPI和Springfox
很多人把 Swagger 当作一个工具,其实它最初既包含规范也包含工具集。后来规范部分捐赠给了 OpenAPI Initiative,成为 OpenAPI Specification,工具部分继续保留 Swagger 名称。日常所说的 Swagger 文档,现在通常指基于 OpenAPI 3 生成的 API 描述以及 Swagger UI 页面。
Java 生态里有两个常见实现。Springfox 早期使用最广,但它基于旧的 Swagger 2 规范,且维护节奏已经基本停滞,对较新的 Spring Boot 版本兼容性较差。springdoc-openapi 则是面向 OpenAPI 3 的实现,更新活跃,支持 Spring Boot 2 和 3,也能自动读取 Bean Validation 注解。新项目建议直接选择 springdoc-openapi,老项目如果已经在用 Springfox,可以后续逐步迁移。
下面的对照表可以帮助判断:
| 对比项 | Springfox | springdoc-openapi |
|---|---|---|
| 规范版本 | Swagger 2 | OpenAPI 3 |
| 维护状态 | 基本停更 | 活跃更新 |
| Spring Boot 3 | 不兼容 | 兼容 |
| 集成复杂度 | 需要配置类 | 极少配置即可生效 |
二、在Spring Boot中完成依赖与基础配置
以 Maven 项目为例,Spring Boot 3 需要引入 springdoc-openapi-starter-webmvc-ui。依赖声明要放在 pom.xml 的 <dependencies> 节点内,注意 artifactId 不是 springfox。代码如下:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.6.0</version>
</dependency>
如果你的项目仍然运行在 Spring Boot 2.x,artifactId 应该是 springdoc-openapi-ui,版本使用 1.x 系列,例如 1.7.0。两者 API 用法基本一致,但导入包都来自 io.swagger.v3.oas.annotations,不会让上层代码被绑定到具体实现。
接下来在 application.yml 中增加文档基础信息。这里可以自定义标题、描述、版本号,以及 Swagger UI 的访问路径。配置内容并不复杂:
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: method
启动应用后,访问 http://localhost:8080/swagger-ui.html 或 http://localhost:8080/swagger-ui/index.html 就能看到自动生成的接口列表。如果项目配置了 context-path,记得把上下文路径加在前面。JSON 格式的 OpenAPI 描述则在 /v3/api-docs 地址暴露,适合工具链消费。
这一步不需要在启动类上加任何额外注解。springdoc-openapi 会自动扫描所有带有 @RestController 的类,并根据 @RequestMapping、@GetMapping、@PostMapping 等注解生成路径和方法描述。这也是它比 Springfox 更易用的一个重要原因。
三、用注解让API文档具备业务语义
自动生成的文档只有路径和参数名,缺少业务含义。要让前端和测试一眼看懂,需要在 Controller 和实体类上补充注解。springdoc-openapi 使用的注解来自 io.swagger.v3.oas.annotations 包,而不是旧的 swagger.annotations。常用注解包括 @Tag、@Operation、@ApiResponses、@Parameter。
下面是一个用户模块的简单示例,同时包含了 GET 和 POST 两种请求:
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.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/users")
@Tag(name = "用户管理", description = "用户相关接口")
public class UserController {
@Operation(summary = "根据ID查询用户", description = "返回单个用户信息")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "查询成功"),
@ApiResponse(responseCode = "404", description = "用户不存在")
})
@GetMapping("/{id}")
public User getUserById(
@Parameter(description = "用户ID", required = true, example = "1001")
@PathVariable Long id) {
return new User(id, "张三", "zhangsan@ipipp.com");
}
@Operation(summary = "创建用户", description = "新增一个用户记录")
@PostMapping
public User createUser(@RequestBody User user) {
return user;
}
}
实体字段的描述依靠 @Schema 注解。例如 User 类可以这样写:
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "用户信息")
public class User {
@Schema(description = "用户ID", example = "1001")
private Long id;
@Schema(description = "姓名", example = "张三")
private String name;
@Schema(description = "邮箱", example = "zhangsan@ipipp.com")
private String email;
public User(Long id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
这样的注解组合下来,Swagger UI 中会显示接口摘要、详细说明、参数是否必填、示例值以及不同状态码的响应含义。对于复杂返回结构,还可以使用 @Content 和 @ExampleObject 提供响应示例,不过日常项目通常先保证基础注解不缺失即可。
四、安全控制与踩坑排查
Swagger UI 非常方便,但它会把接口清单暴露给访问者。生产环境一般不建议直接开放文档页面,可以通过配置开关关闭:
springdoc:
api-docs:
enabled: false
swagger-ui:
enabled: false
更合理的做法是按 Profile 隔离。日常开发使用 dev 配置开启文档,生产配置使用上面的关闭项。如果项目接入了 Spring Security,还需要放行文档相关地址,包括 /v3/api-docs/**、/swagger-ui/** 和 /swagger-ui.html,否则接口列表页会出现空白或 403。
集成过程中最常见的几个问题比较集中。访问 404 时先检查依赖是否与 Spring Boot 大版本匹配,以及是否受 context-path 影响;注解不生效时确认 import 的包是否来自 io.swagger.v3.oas.annotations,并且是否同时残留了 Springfox 的依赖;参数列表为空时检查参数是否添加了 @Parameter,对象字段是否使用 @Schema;如果接口数量较多,还可以用 GroupedOpenApi 按模块拆分文档分组,避免单个 JSON 过大。
- 访问404:检查依赖版本和 context-path
- 注解不生效:避免 springdoc 与 Springfox 混用
- 参数不显示:为参数和字段补充注解
- 生产安全:按 Profile 动态关闭文档
从实际效果看,Swagger 集成最大的价值不是花哨的页面,而是让接口契约可以从代码自动生成,减少文档失配。只要选对实现并规范使用注解,团队协作效率会有明显提升。