1. 引言
在前后端分离的开发模式下,接口文档的维护一直是个痛点。传统方式下,接口文档往往以 Word 或 Markdown 文件形式存在,由后端开发手动维护,很容易出现文档与代码不同步、接口变更后文档未及时更新的问题。Swagger UI 的出现,让接口文档能够直接从代码注释中自动生成,并提供一个可视化的在线调试页面,大大降低了文档维护成本。
本文将从 Swagger 的核心概念讲起,结合 Spring Boot 项目,演示如何通过 Swagger UI 自动生成接口文档,并介绍文档发布到内网、接入权限控制以及多环境切换的实践方案。
2. Swagger 与 OpenAPI 核心概念
在开始编码之前,先厘清几个容易混淆的概念:Swagger、OpenAPI 和 Swagger UI。
- OpenAPI Specification(OAS):一套描述 RESTful API 的开放规范,定义了接口路径、请求参数、响应结构、认证方式等元数据的标准格式,目前主流版本为 OpenAPI 3.0。
- Swagger:围绕 OpenAPI 规范衍生出的一套工具集,包括 Swagger Editor、Swagger UI、Swagger Codegen 等。
- Swagger UI:一个基于 HTML、CSS 和 JavaScript 的交互式文档页面,能够读取 OpenAPI 规范的 JSON/YAML 文件,并将其渲染为可浏览、可调试的在线文档。
三者之间的关系可以这样理解:OpenAPI 是“标准”,Swagger 是“工具家族”,而 Swagger UI 是这个家族中负责“展示与调试”的成员。Spring Boot 项目通常通过 springfox 或 springdoc 这两个库,在应用启动时扫描接口注解,自动生成 OpenAPI 描述文件,再由 Swagger UI 渲染成文档页面。
3. 环境准备与依赖引入
本文以 Spring Boot 2.7 + springdoc-openapi 为例进行演示。之所以选择 springdoc 而非 springfox,是因为 springdoc 原生支持 OpenAPI 3.0,且对 Spring Boot 2.6 之后的路径匹配策略兼容性更好。
首先,在 pom.xml 中引入依赖:
<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.7.0</version> </dependency>引入依赖后,启动应用,访问http://localhost:8080/swagger-ui.html,即可看到默认的 Swagger UI 页面。此时页面中还没有任何接口信息,因为项目里还没有编写带注解的接口。
4. 编写带 Swagger 注解的接口
下面创建一个用户管理模块,演示如何通过注解为接口补充文档信息。先定义一个用户实体类:
import io.swagger.v3.oas.annotations.media.Schema; public class User { @Schema(description = "用户ID", example = "1") private Long id; @Schema(description = "用户名", example = "zhangsan") private String username; @Schema(description = "邮箱", example = "zhangsan@example.com") private String email; // 省略 getter 和 setter }接着编写控制器。通过@Tag描述接口分组,通过@Operation描述单个接口的用途,通过@Parameter描述路径参数:
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.*; import java.util.ArrayList; import java.util.List; @Tag(name = "用户管理", description = "用户信息的增删改查接口") @RestController @RequestMapping("/api/users") public class UserController { private final List<User> userStore = new ArrayList<>(); @Operation(summary = "查询用户列表", description = "返回系统中所有用户的基本信息") @GetMapping public List<User> listUsers() { return userStore; } @Operation(summary = "根据ID查询用户", description = "根据路径参数 id 查询单个用户") @GetMapping("/{id}") public User getUser( @Parameter(description = "用户ID", example = "1") @PathVariable Long id) { return userStore.stream() .filter(u -> u.getId().equals(id)) .findFirst() .orElse(null); } @Operation(summary = "新增用户", description = "创建一个新用户并返回创建后的用户信息") @PostMapping public User createUser(@RequestBody User user) { user.setId((long) (userStore.size() + 1)); userStore.add(user); return user; } }重启应用后再次访问 Swagger UI,可以看到“用户管理”分组下出现了三个接口,每个接口都带有我们在注解中填写的描述信息。点击任意接口,可以展开查看请求参数、响应结构,并直接点击“Try it out”按钮在线调用。
5. 自定义文档信息与全局配置
默认的文档标题是“OpenAPI definition”,页面顶部展示的信息比较简陋。通过一个配置类,可以自定义文档的标题、版本、描述和联系人信息:
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 文档") .version("1.0.0") .description("用户服务对外提供的 RESTful 接口说明文档") .contact(new Contact() .name("后端开发组") .email("backend@example.com"))); } }配置完成后,Swagger UI 页面顶部的标题、描述和联系方式都会随之更新。此外,还可以通过 application.yml 配置文档的访问路径和开关状态:
springdoc: swagger-ui: path: /swagger-ui.html tags-sorter: alpha operations-sorter: method api-docs: path: /v3/api-docs其中tags-sorter和operations-sorter分别控制分组和接口的排序方式,可按字母序或方法类型排序,便于在接口数量较多时快速定位。
6. 为接口添加认证信息
实际项目中,很多接口需要登录后才能访问。Swagger UI 支持在文档页面中配置全局认证,调试时自动携带 Token。以常见的 Bearer Token 为例,在配置类中补充安全方案:
import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityScheme; @Bean public OpenAPI customOpenAPI() { final String securitySchemeName = "bearerAuth"; return new OpenAPI() .info(new Info() .title("用户服务 API 文档") .version("1.0.0") .description("用户服务对外提供的 RESTful 接口说明文档")) .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) .components(new Components() .addSecuritySchemes(securitySchemeName, new SecurityScheme() .name(securitySchemeName) .type(SecurityScheme.Type.HTTP) .scheme("bearer") .bearerFormat("JWT"))); }配置完成后,Swagger UI 页面右上角会出现一个“Authorize”按钮。点击后输入 Token,后续调试接口时,请求头会自动带上Authorization: Bearer <token>,无需手动拼接。
7. 文档发布到内网
Swagger UI 默认随应用一起运行,适合开发环境联调。但生产环境通常不希望暴露接口文档,因此需要区分环境发布。推荐的做法是:开发环境开启 Swagger,生产环境关闭。
在 application.yml 中通过配置项控制开关:
springdoc: api-docs: enabled: true swagger-ui: enabled: true然后在 application-prod.yml 中关闭:
springdoc: api-docs: enabled: false swagger-ui: enabled: false启动时通过--spring.profiles.active=prod指定生产环境,即可实现文档的按环境发布。如果希望将文档独立部署到内网服务器,也可以把生成的/v3/api-docsJSON 文件导出,配合静态版 Swagger UI 部署到 Nginx 上,实现文档与业务应用解耦。
8. 常见问题与注意事项
在实际使用中,有几个容易踩坑的地方值得注意。
第一,Spring Boot 2.6 及以上版本默认的路径匹配策略从 AntPathMatcher 改为了 PathPatternParser,旧版 springfox 会因此启动报错。如果项目必须使用 springfox,需要手动将路径匹配策略改回 AntPathMatcher;如果是从零开始的新项目,建议直接使用 springdoc。
第二,接口文档中如果出现大量重复的模型描述,可以通过@Schema注解统一维护字段说明,避免在多个接口中重复书写。对于通用返回结构,建议封装统一的响应体,并在文档中只描述业务数据部分。
第三,Swagger UI 页面在部分内网环境下无法加载,通常是因为静态资源被拦截或 CDN 资源不可达。此时可以将 Swagger UI 的静态资源打包到应用内,或通过 Nginx 反向代理解决。
9. 总结
Swagger UI 将接口文档从“人工维护”转变为“代码生成”,让文档始终与代码保持同步。通过 springdoc 与 Spring Boot 的整合,开发者只需在接口上补充少量注解,即可获得一份结构清晰、支持在线调试的文档页面。结合环境配置和权限控制,文档可以安全地发布到开发、测试乃至内网生产环境,成为团队协作中可靠的技术资产。
后续可以进一步探索 Swagger Codegen 根据文档自动生成客户端代码,以及结合 OpenAPI 规范做接口契约测试,让文档的价值从“查看”延伸到“驱动开发”。