嘿,朋友,是不是有时候写了上百个接口,却要手动维护一份API文档?更惨的是,代码改了,文档没改,前端同学找上门来骂街……今天咱不聊虚的,直接把这套”Swagger + Jenkins”的自动化方案给你讲透,让你从此告别文档焦虑症。
咱们先聊聊:为什么需要这套组合拳
你可能听过Swagger,也知道它能把代码里的注解变成漂亮的在线文档。但你有没有想过:
- 你更新了某个接口的参数,是不是还得手动去Swagger UI里验证?
- 新功能上线了,文档是不是还得手动更新再部署?
- 换台机器、重新拉代码,文档环境是不是又要重新搭一遍?
这些问题,单靠Swagger解决不了。Jenkins的存在,就是为了把这些重复、机械的活儿全自动化掉。 你的目标应该是:代码提交,文档自动生成并更新,无需任何人工干预。
第一步:在Spring Boot项目里”预埋”Swagger
别急,咱不是要写复杂的配置,而是用最简洁、最稳定的方式集成。我推荐的方案是基于 Springfox 和 SpringDoc(Spring Boot 2.6+ 推荐用SpringDoc,因为Springfox已停止维护)。咱们两个都说说,你按项目版本选。
方案A:SpringDoc(Spring Boot 2.6+ 首选)
在 pom.xml 里加依赖:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.7.0</version>
</dependency>
注意:如果你用了 Spring Boot 3.x,版本要换成 2.3.0 以上,且依赖名称略有不同:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
然后在 application.yml 里配置基础信息:
springdoc:
api-docs:
enabled: true
path: /v3/api-docs
swagger-ui:
enabled: true
path: /swagger-ui.html
info:
title: 用户服务API文档
description: 包含用户注册、登录、信息管理等功能接口
version: 1.0.0
contact:
name: 开发团队
email: dev@yourcompany.com
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
最关键的是在 Controller 里加上注解,这是Swagger能识别你接口的核心:
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.*;
@RestController
@RequestMapping("/api/users")
@Tag(name = "用户管理", description = "用户相关的CRUD操作")
public class UserController {
@Operation(
summary = "获取用户信息",
description = "根据用户ID查询详细信息,包含昵称、邮箱、注册时间等"
)
@Parameter(name = "userId", description = "用户唯一标识", required = true)
@GetMapping("/{userId}")
public UserDTO getUserById(@PathVariable Long userId) {
// 业务逻辑...
return userService.findById(userId);
}
@Operation(
summary = "创建新用户",
description = "注册新用户,返回用户ID和初始信息"
)
@PostMapping
public UserDTO createUser(@RequestBody @Valid CreateUserRequest request) {
// 业务逻辑...
return userService.create(request);
}
}
看到没?这些注解不只是给Swagger看的,它们直接写在了代码里,代码即文档。你改代码,文档自然跟着变。
方案B:Springfox(老项目适用)
如果你的项目还是 Spring Boot 2.5 及以下,用Springfox:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
配置类长这样:
@Configuration
@EnableOpenApi
public class SwaggerConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("用户服务API")
.version("1.0")
.description("用户管理相关接口文档")
.contact(new Contact()
.name("开发团队")
.email("dev@yourcompany.com"))
);
}
}
注解写法类似,只是包名不同:io.swagger.annotations.*。
小贴士:不管用哪个方案,记得在本地启动后访问 http://localhost:8080/swagger-ui.html 或 /v3/api-docs,确认文档能正常生成。这一步别省,Jenkins跑起来之前,本地得先验通。
第二步:准备一个能”导出”文档的构建目标
Jenkins需要知道怎么拿这个文档。有两种主流做法:
做法1:直接打JAR包,Swagger内置(推荐)
这是最简单的方案。你的Spring Boot应用本身就自带了Swagger UI。Jenkins构建后,部署这个JAR,Swagger文档就自动有了。
但问题来了:如果只想单独拿一份静态的HTML文档(比如导出成离线文档、或者部署到Nginx静态服务器),你就需要额外一步。
做法2:用 swagger-maven-plugin 生成静态文档
在 pom.xml 里加上这个插件:
<build>
<plugins>
<!-- 其他插件... -->
<plugin>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>2.2.15</version>
<configuration>
<outputFormats>JSON,YAML</outputFormats>
<outputDirectory>${project.build.directory}/swagger-docs</outputDirectory>
<scan>true</scan>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>resolve</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 如果想生成HTML,可以用这个插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>copy-swagger-ui</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/swagger-html</outputDirectory>
<resources>
<resource>
<directory>src/main/resources/static/swagger-ui</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
注意:如果你用SpringDoc,它本身就支持输出JSON/YAML。你不需要额外插件,直接在Jenkins里调 /v3/api-docs 接口拿就行。
第三步:Jenkins Pipeline 的编写
这是核心。我用 Jenkinsfile (Declarative Pipeline) 来写,清晰、版本可控、方便团队协作。
假设你的项目已经放在Git仓库里,Jenkins已经配置好Git插件。新建一个 Pipeline 任务,粘贴以下内容:
pipeline {
agent any
environment {
// 定义环境变量,方便统一修改
DOCKER_REGISTRY = 'registry.yourcompany.com'
APP_NAME = 'user-service'
SWAGGER_OUTPUT_DIR = "${env.WORKSPACE}/target/swagger-docs"
DOCS_DEPLOY_DIR = '/data/docs/user-service'
}
stages {
stage('拉取代码') {
steps {
checkout scm
echo "✅ 代码拉取完成,当前分支: ${env.BRANCH_NAME}"
}
}
stage('编译构建') {
steps {
// 使用 Maven 包装器,确保构建环境一致
sh 'mvn clean package -DskipTests'
echo "✅ Maven 构建完成"
}
}
stage('生成Swagger文档') {
steps {
// 如果是SpringDoc,启动应用并获取文档
sh '''
# 临时启动应用获取v3/api-docs
nohup java -jar target/*.jar --server.port=8888 > /tmp/app.log 2>&1 &
APP_PID=$!
# 等待应用启动
sleep 15
# 下载JSON文档
curl -s http://localhost:8888/v3/api-docs > ${SWAGGER_OUTPUT_DIR}/api-docs.json
# 停止应用
kill $APP_PID
wait $APP_PID 2>/dev/null
echo "📄 Swagger JSON 已生成: ${SWAGGER_OUTPUT_DIR}/api-docs.json"
'''
}
}
stage('转换并部署文档') {
steps {
sh '''
# 使用 swagger-ui-dist 生成静态HTML
npm install -g swagger-ui-dist
npx swagger-ui-dist ${SWAGGER_OUTPUT_DIR}/api-docs.json --output ${SWAGGER_OUTPUT_DIR}/html
# 复制部署
mkdir -p ${DOCS_DEPLOY_DIR}
cp -r ${SWAGGER_OUTPUT_DIR}/html/* ${DOCS_DEPLOY_DIR}/
# 清理临时文件
rm -rf ${SWAGGER_OUTPUT_DIR}
echo "🚀 文档已部署到: ${DOCS_DEPLOY_DIR}"
'''
}
}
stage('触发下游通知') {
steps {
// 通知团队文档已更新
sh '''
curl -X POST "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK" \
-H 'Content-Type: application/json' \
-d '{"text":"📚 API文档已更新: user-service v1.0"}'
'''
}
}
}
post {
success {
echo "🎉 Pipeline 成功完成!Swagger文档已自动更新。"
}
failure {
echo "❌ Pipeline 失败,请检查构建日志。"
// 可以发邮件、钉钉等通知
}
always {
cleanWs()
echo "🧹 工作区已清理"
}
}
}
这段代码的关键点:
mvn clean package -DskipTests:跳过测试加速构建。如果你需要跑测试,把-DskipTests去掉。- 临时启动应用获取文档:这是最可靠的方式。有些项目配置了
@Profile或环境差异,直接在编译阶段拿文档可能不完整。 swagger-ui-dist:NPM包,能把JSON转换成可浏览的HTML。如果你不需要HTML,只想保留JSON供其他工具使用,可以跳过这步。post块:成功、失败、总是执行三种回调,别漏了清理工作区,否则磁盘迟早爆满。
第四步:让文档在Nginx上优雅地展示
光有Jenkins还不够,你得有个地方让人看文档。Nginx是最常见的选择。
Nginx配置示例
server {
listen 80;
server_name docs.yourcompany.com;
# 用户服务文档
location /user-service/ {
alias /data/docs/user-service/;
index index.html;
try_files $uri $uri/ /index.html;
}
# 订单服务文档(多项目可以都放在这里)
location /order-service/ {
alias /data/docs/order-service/;
index index.html;
try_files $uri $uri/ /index.html;
}
# 健康检查
location /health {
return 200 'OK';
add_header Content-Type text/plain;
}
}
为什么用 alias 而不是 root? alias 更灵活,路径映射更直观,适合这种多项目共用一台文档服务器的场景。
前端访问地址
- 用户服务文档:
http://docs.yourcompany.com/user-service/ - 订单服务文档:
http://docs.yourcompany.com/order-service/
第五步:进阶技巧——让文档更”人性化”
技巧1:按模块拆分文档
如果你的项目很大,一个 api-docs.json 可能几MB,加载慢。可以用SpringDoc的分组功能:
@Bean
public GroupedOpenApi userApi() {
return GroupedOpenApi.builder()
.group("用户管理")
.pathsToMatch("/api/users/**")
.build();
}
@Bean
public GroupedOpenApi orderApi() {
return GroupedOpenApi.builder()
.group("订单管理")
.pathsToMatch("/api/orders/**")
.build();
}
这样生成的文档会有左侧导航菜单,点击分组跳转,体验好很多。
技巧2:隐藏测试接口
正式环境文档里出现一堆 /test、/debug 接口很尴尬。在配置里加:
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()...)
.components(new Components()
.addSecuritySchemes("bearer-key",
new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")))
.security(List.of(new SecurityRequirement().addList("bearer-key")));
}
然后在Controller里用 @Hidden 注解隐藏不需要展示的接口:
@Hidden
@GetMapping("/internal/debug")
public String debug() {
return "debug info";
}
技巧3:版本化管理
在Jenkins里,每次构建生成带时间戳或版本的目录:
stage('部署文档') {
steps {
def version = new Date().format('yyyyMMdd-HHmmss')
sh "mkdir -p ${DOCS_DEPLOY_DIR}/${version}"
sh "cp -r ${SWAGGER_OUTPUT_DIR}/html/* ${DOCS_DEPLOY_DIR}/${version}/"
sh "ln -sfn ${version} ${DOCS_DEPLOY_DIR}/latest"
}
}
这样你可以随时回溯历史版本的文档,不会怕”改坏了没法看”。
常见问题与避坑指南
问题1:Jenkins构建时Swagger文档为空
原因:应用启动太慢,curl 拿到的是空响应。
解决:
- 增加等待时间,或者用循环重试:
for i in {1..10}; do
if curl -s http://localhost:8888/v3/api-docs | grep -q "openapi"; then
curl -s http://localhost:8888/v3/api-docs > api-docs.json
break
fi
sleep 3
done
问题2:Spring Boot 3.x 和 Swagger 兼容性
Spring Boot 3.x 用了 Jakarta EE,包名从 javax.* 变成了 jakarta.*。Springfox 不支持,必须用 SpringDoc 2.x+。检查你的依赖版本:
<springdoc.version>2.3.0</springdoc.version>
问题3:Jenkins节点磁盘空间不足
cleanWs() 有时候清不干净。可以在Pipeline里加:
post {
always {
cleanWs(deleteDirs: true)
sh 'rm -rf ${WORKSPACE}/*'
}
}
问题4:多模块Maven项目只扫描了父模块
确保在包含Controller的子模块里配置Swagger,或者在父模块的 pom.xml 里用 <modules> 扫描所有子模块。SpringDoc默认会扫描整个classpath,所以通常没问题,但如果用了 @ComponentScan 限制了包路径,要检查是否包含了Controller所在的包。
整套流程的终极形态
理想情况下,你的开发流程应该是:
- 开发者写代码,加Swagger注解
- 提交代码到Git(触发Jenkins)
- Jenkins自动构建、测试、生成文档
- 文档自动部署到Nginx服务器
- 团队收到Slack/钉钉通知
- 前端同学直接访问
docs.yourcompany.com看最新文档
整个过程,开发者不需要做一件额外的事。
最后的小建议
别一开始就想搞完美。先从最简单的开始:
- 本地先把Swagger跑通
- 写一个最简的Jenkinsfile,只完成”构建+生成JSON”
- 验证文档能正常访问
- 再逐步加静态HTML转换、Nginx部署、通知机制
每一步都验证,出了问题好排查。别一上来就写100行Pipeline,调试起来要命。
这套方案我在好几个项目里验证过,关键是细节:比如等待时间、路径配置、版本管理。希望这篇长文能帮你把”API文档维护”从负担变成习惯。有问题随时问,咱们一起把这件事做漂亮。
