SpringBoot Swagger
前言:在SpringBoot前后端分离开发体系中,接口文档混乱、前后端对接扯皮、接口更新不同步、手动写文档效率低是开发高频痛点。Swagger是Java生态最主流的自动接口文档生成工具。同时,Swagger + AOP是企业高阶实战组合,可实现接口文档自动生成、接口请求日志统一记录、接口权限校验、操作日志留存、接口脱敏等高级能力。
一、Swagger 技术简介
Swagger是一套基于OpenAPI规范的开源RESTful接口文档自动生成框架,专为SpringBoot Web项目设计,可自动扫描项目中所有Controller接口、注解、参数、返回值,动态生成可视化、可在线调试的接口文档,彻底替代手动编写Word、Markdown接口文档的传统方式。
目前主流演进版本:原生Swagger2 →SpringDoc OpenAPI(新版替代方案),本文同时兼容经典Swagger2用法与新版规范,适配新旧项目。
核心定位:前后端分离项目接口标准化、可视化、自动化的核心工具,是企业项目开发标配组件。
二、Swagger 核心使用场景
前后端接口对接:自动生成标准化接口文档,统一前后端认知,杜绝接口参数、请求方式、返回格式沟通偏差。
在线接口调试:无需Postman、无需Mock工具,直接在Swagger页面发起GET/POST/PUT/DELETE请求,快速调试接口。
项目接口梳理归档:自动汇总项目所有接口、分类展示、标注用途,适合项目交接、新人快速熟悉项目接口体系。
接口版本迭代管理:代码更新自动同步文档更新,解决文档滞后、文档和代码不一致问题。
配合AOP实现高阶管控:结合AOP切面编程,实现接口日志统一记录、操作审计、权限拦截、参数脱敏、接口访问统计。
测试与联调辅助:配合MockMvc完成接口测试对照,快速校验接口参数定义、返回结构是否规范。
三、Swagger 核心特点
代码即文档、自动同步:通过代码注解定义接口说明,代码修改文档实时更新,杜绝文档滞后。
可视化在线文档:页面直观展示接口路径、请求方式、参数类型、必填项、返回示例、错误码。
支持在线调试:内置请求客户端,无需第三方工具,直接在线发起请求、查看响应结果。
注解轻量化、侵入性低:通过简单注解即可完成接口描述,不影响业务代码逻辑。
支持接口分组、版本管理:可按模块、版本、开发者分组展示接口,适配大型项目架构。
扩展性极强:支持自定义文档信息、全局参数、Token鉴权、响应格式、结合AOP二次开发。
生态成熟、全网通用:几乎所有Java前后端分离项目标配,社区教程丰富、排查问题成本低。
四、Swagger 完整优缺点
4.1 核心优点
极大提升开发效率:彻底解放手动写文档、改文档的重复工作,专注业务代码开发。
保证代码与文档一致性:注解绑定代码,代码变更文档自动更新,从根源解决文档过期问题。
降低团队沟通成本:标准化接口文档,前后端、测试、产品统一对接标准,减少扯皮沟通。
自带调试能力:轻量化接口自测,小型开发场景可替代Postman快速调试。
拓展能力极强:可结合AOP、拦截器、全局异常、权限框架实现整套接口管控体系。
适配所有SpringBoot版本:新旧项目均可兼容,迁移成本极低。
4.2 核心缺点
增加项目冗余注解:大量接口、实体类需要添加注解,轻微增加代码量。
生产环境存在安全隐患:开启后可查看所有接口并在线调用,未做权限拦截易暴露业务接口。
原生Swagger2停止更新:旧版swagger2不再维护,存在少量兼容BUG,新版推荐SpringDoc。
项目启动轻微变慢:项目启动时需要扫描所有注解、生成接口文档,大型项目启动耗时略有增加。
无法自动生成业务说明:仅能根据注解生成文档,无法自动识别接口业务逻辑,依赖人工注解补充。
五、Swagger 环境配置(SpringBoot2.x/3.x 通用企业配置)
5.1 核心依赖(Swagger2 经典版)
<!-- Swagger2 核心依赖 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>5.2 企业全局配置类(开启文档+基础信息+扫描规则)
import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @EnableSwagger2 // 开启Swagger文档功能 public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) // 项目基础文档信息 .apiInfo(apiInfo()) // 开启接口扫描 .select() // 指定扫描Controller包路径 .apis(RequestHandlerSelectors.basePackage("com.example.controller")) // 扫描所有路径 .paths(PathSelectors.any()) .build(); } // 文档描述信息 private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("SpringBoot接口文档") .description("前后端分离项目统一接口文档,支持在线调试") .version("1.0.0") .build(); } }访问地址:启动项目后访问http://localhost:8080/swagger-ui.html
六、Swagger 核心注解全解
6.1 全局&启动核心注解(官网必备)
@EnableSwagger2
官网定义:Swagger2 核心启动注解,用于开启项目 OpenAPI2.0 文档自动生成能力,注册 Swagger 内置Bean、开启接口扫描、启用UI文档渲染。
核心属性:无自定义属性,仅作标识启用
官方规范场景:必须标注在 Swagger 配置类上,项目启用Swagger的唯一入口注解
注意事项:SpringBoot3.x 彻底废弃该注解,仅适配 SpringBoot2.x 版本;新版 SpringDoc 无需该注解
6.2 控制器类级别注解(官方标准)
@Api(官网核心类注解)
官网定义:用于标记 Controller 控制器类,对整个模块所有接口进行分组归类、模块描述,是接口文档模块化展示的核心注解。
官方核心属性(补齐全量属性):
tags:必填,模块分组名称,UI页面展示的模块标题,支持多标签分组
value:模块简要描述,官网标注为兼容旧版本,UI页面不展示,仅做备注
description:模块详细功能描述
produces:指定模块统一响应Content-Type,如 application/json
consumes:指定模块统一请求Content-Type
hidden:布尔值,是否隐藏当前模块所有接口,true则不生成文档
// 官网标准完整写法 @Api( tags = "用户管理模块", value = "用户业务接口", description = "包含用户新增、查询、修改、删除、登录等全部用户相关接口", produces = "application/json;charset=UTF-8" ) @RestController @RequestMapping("/user") public class UserController {}✅ 官方优点:标准化模块分组,文档结构层级清晰,支持批量隐藏模块接口
❌ 局限:仅作用于类级别,无法单独定义单接口的特殊规则
🎯 官方适用场景:所有业务Controller必须添加,用于接口模块化归类管理
作用:标记Controller类,描述模块功能、接口分类
@Api(tags = "用户管理模块", description = "用户新增、查询、修改、删除接口") @RestController @RequestMapping("/user") public class UserController {}✅ 优点:接口分类清晰,文档结构规整
❌ 缺点:仅作用于类,无法细化单接口描述
🎯 场景:所有业务Controller统一添加
6.3 接口方法级别注解(官网全量覆盖)
@ApiOperation(单接口标准描述注解)
官网定义:用于描述单个接口的功能、业务用途、版本、权限、备注信息,是接口详情文档的核心注解。
官方全量核心属性(扩展补齐):
value:必填,接口简短功能描述(UI主展示名称)
notes:接口详细备注、业务说明、注意事项、异常场景说明
tags:接口单独分组,可脱离类标签单独归类
hidden:是否隐藏当前接口,true则不生成文档
httpMethod:限定接口请求方式
response:指定接口返回实体Class
code:接口默认成功状态码
// 官网完整规范写法 @GetMapping("/{id}") @ApiOperation( value = "根据ID查询用户详情", notes = "传入合法用户ID,返回用户基础信息;ID不存在返回空数据,不抛出异常", response = User.class, code = 200 ) public Result getUserById(@PathVariable Long id){}@ApiHidden(官网隐藏注解)
官网定义:专门用于隐藏接口/类,优先级高于 @Api、@ApiOperation 的hidden属性,常用于隐藏内部接口、测试接口、私密接口。
// 隐藏测试接口,不生成Swagger文档 @ApiHidden @GetMapping("/test") public String testApi(){}@ApiResponses + @ApiResponse(响应状态码注解|官网必备)
官网定义:用于定义接口多状态码响应说明,标准化200/400/401/404/500等异常返回信息,是企业规范文档必填注解。
属性说明:
code:HTTP响应状态码
message:状态码对应描述信息
response:对应返回实体类
@PostMapping("/add") @ApiOperation(value = "新增用户") @ApiResponses(value = { @ApiResponse(code = 200, message = "新增成功"), @ApiResponse(code = 400, message = "参数校验失败"), @ApiResponse(code = 500, message = "服务器内部异常") }) public Result addUser(@RequestBody User user){}@ApiOperation
作用:描述单个接口的功能、用途
@GetMapping("/{id}") @ApiOperation(value = "根据ID查询用户", notes = "传入用户ID,返回用户详细信息") public Result getUserById(@PathVariable Long id){}6.4 请求参数级别注解(官网标准|含路径/查询/请求体参数)
@ApiParam(单个参数描述注解)
官网定义:用于描述请求路径参数、查询参数的字段含义、必填性、示例值、参数约束,适配 GET/DELETE 等无请求体接口。
官网全量核心属性:
value:参数功能描述
required:是否为必填参数,默认false
example:参数示例值,UI调试自动填充
defaultValue:参数默认值
allowableValues:限定参数可选值,枚举约束
hidden:是否隐藏该参数
// 官网标准完整写法 public Result getUserById( @ApiParam( value = "用户唯一主键ID", required = true, example = "10001", allowableValues = "range[1,99999]" ) @PathVariable Long id ){}@ApiImplicitParams + @ApiImplicitParam(多参数统一注解)
官网定义:用于统一描述多个请求参数,适配参数较多、需要统一约束的接口,优先级高于 @ApiParam。
@GetMapping("/list") @ApiOperation("分页查询用户列表") @ApiImplicitParams({ @ApiImplicitParam(name = "pageNum", value = "页码", required = true, example = "1"), @ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"), @ApiImplicitParam(name = "username", value = "用户名模糊查询", required = false) }) public Result getUserList(Integer pageNum, Integer pageSize, String username){}@ApiParam
作用:描述请求参数含义、是否必填、示例值
public Result getUserById( @ApiParam(value = "用户唯一ID", required = true, example = "1") @PathVariable Long id ){}6.5 实体模型注解(官网核心|入参/出参标准化)
@ApiModel + @ApiModelProperty(模型标准注解)
官网定义:@ApiModel用于描述实体类、VO、DTO、请求体模型的整体功能;@ApiModelProperty用于描述实体字段的含义、约束、示例、是否必填,是接口返回/入参文档的核心注解。
@ApiModel 官网核心属性:
value:模型名称
description:模型详细描述
parent:指定父类模型,实现继承关联
@ApiModelProperty 官网全量核心属性:
value:字段功能描述(必填)
required:是否必填字段
example:字段示例值
hidden:是否隐藏该字段,不展示在文档
allowEmptyValue:是否允许空值
dataType:指定字段数据类型
// 官网标准完整实体注解写法 @ApiModel(value = "用户实体模型", description = "用户基础信息,用于接口入参和出参") public class User { @ApiModelProperty(value = "用户主键ID", required = true, example = "1", allowEmptyValue = false) private Long id; @ApiModelProperty(value = "登录用户名", required = true, example = "张三") private String username; @ApiModelProperty(value = "用户手机号", example = "13800138000", hidden = false) private String phone; @ApiModelProperty(value = "用户密码", hidden = true) // 隐藏敏感字段 private String password; }@ApiModel + @ApiModelProperty
作用:描述实体类、返回VO字段含义、数据类型、必填项,自动生成返回参数文档
6.6 官网拓展高阶注解(企业生产必备)
@ApiAuthorization(权限认证注解)
官网定义:用于标记当前接口需要权限/Token认证,配合Swagger全局Header配置,实现文档权限标识标准化。
@ApiIgnore(全局忽略注解)
官网定义:作用于类/方法/参数,全局忽略生成文档,优先级最高,常用于过滤工具类接口、内部接口、错误页面接口。
@ApiVersion(接口版本注解)
官网定义:用于多版本接口管理,标记接口所属版本,适配大型项目接口迭代版本管控。
6.7 官网注解废弃&替换规范(避坑重点)
官网明确废弃说明:
Swagger2 中@ApiField、@ApiModel为非官方非标注解,禁止使用
@ApiModel(value="")仅做展示,业务描述优先使用 description 属性
SpringBoot3.x 完全淘汰 Swagger2 全套注解,统一替换为 SpringDoc OpenAPI3 注解(@Schema、@Operation、@Parameter)
6.8 注解使用官网最佳规范
所有对外业务接口:必须补齐
@Api + @ApiOperation + @ApiResponses全套注解所有请求/返回实体:必须补齐
@ApiModel + @ApiModelProperty字段说明与示例值敏感字段(密码、密钥、身份证):通过
hidden=true隐藏,禁止暴露文档测试接口、内部接口:统一使用
@ApiHidden/@ApiIgnore隐藏参数必须标注
required必填属性,明确接口约束,杜绝对接歧义
七、核心重点:Swagger + AOP 结合实战(企业高阶用法)
核心原理:Swagger负责接口标准化定义、文档生成、参数注释,AOP切面负责拦截所有被Swagger标记的接口,统一实现增强逻辑,二者结合实现「接口标准化定义 + 统一切面管控」,是企业审计日志、接口监控、权限拦截的黄金组合。
核心价值:无需在每个接口写重复日志、权限、统计代码,通过AOP统一拦截所有Swagger业务接口,全局增强,代码零侵入。
7.1 结合场景(企业刚需)
自动记录所有业务接口操作日志、请求参数、响应结果、耗时、IP、操作者
统一拦截非法接口访问、未授权接口请求
接口参数统一校验、敏感数据自动脱敏
接口访问频次统计、异常接口监控告警
7.2 完整可落地代码实现
步骤1:自定义Swagger接口日志注解(标记需要切面拦截的业务接口)
import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ApiLog { // 接口业务描述 String value() default ""; }步骤2:改造Swagger接口,绑定自定义注解
@RestController @RequestMapping("/user") @Api(tags = "用户管理模块") public class UserController { @GetMapping("/{id}") @ApiOperation("根据ID查询用户") @ApiLog(value = "查询用户详情") // 标记切面拦截 public String getUser(@PathVariable Long id){ return "查询成功"; } }步骤3:AOP切面类(拦截所有Swagger业务接口,统一记录日志)
切面通过切入点匹配所有带有@ApiLog+ Swagger业务接口,实现全局统一增强
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; @Aspect @Component public class SwaggerApiLogAspect { // 切入点:拦截所有带有@ApiLog注解的方法(所有Swagger业务接口) @Pointcut("@annotation(com.example.annotation.ApiLog)") public void apiLogPointCut(){} // 环绕通知:拦截接口前后,记录完整请求信息 @Around("apiLogPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { long startTime = System.currentTimeMillis(); // 获取请求对象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // 获取注解上的接口描述 MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); ApiLog apiLog = method.getAnnotation(ApiLog.class); // 执行接口方法 Object result = point.proceed(); // 计算接口耗时 long costTime = System.currentTimeMillis() - startTime; // 统一打印Swagger接口完整日志(可存入数据库做操作审计) System.out.println("【Swagger接口审计】"); System.out.println("接口描述:" + apiLog.value()); System.out.println("请求地址:" + request.getRequestURL()); System.out.println("请求方式:" + request.getMethod()); System.out.println("请求IP:" + request.getRemoteAddr()); System.out.println("接口耗时:" + costTime + "ms"); return result; } }7.3 Swagger+AOP 组合优缺点
✅ 组合优势
代码零侵入:业务接口无需重复写日志、监控代码,统一切面处理
接口标准化+管控统一:Swagger规范接口定义,AOP统一增强管控,架构极其规整
审计日志全覆盖:所有业务接口自动留存操作记录,满足企业合规审计需求
便于统一维护:后续新增接口增强逻辑,只需修改切面,无需改动所有业务接口
❌ 组合缺点
需要自定义注解区分业务接口,避免拦截系统内置接口
切面拦截会轻微增加接口耗时,高并发场景需优化切面逻辑
🎯 适用场景:企业后台管理系统、需要操作审计、接口监控、权限统一拦截的所有前后端分离项目
八、Swagger 生产环境避坑最佳配置
生产环境必须关闭Swagger,防止接口泄露、安全漏洞,通过配置文件动态控制开启关闭
8.1 yml动态配置
# 开发环境开启,生产环境关闭 swagger: enable: true8.2 配置类动态适配
@Bean public Docket createRestApi(@Value("${swagger.enable}") boolean enable){ return new Docket(DocumentationType.SWAGGER_2) .enable(enable) // 动态控制开关 .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.controller")) .paths(PathSelectors.any()) .build(); }九、技术选型对比(Swagger vs 手写文档 vs Postman文档)
手写Word文档:效率极低、更新滞后、极易出错、无法调试,已淘汰
Postman导出文档:需手动同步接口、无法自动更新、不支持代码联动
Swagger:代码联动自动更新、可视化、可调试、可结合AOP高阶拓展,企业首选
SpringDoc:Swagger升级版,无依赖冲突、适配SpringBoot3.x,新项目首选
十、归纳总结(面试万能标准答案)
技术定位:Swagger是基于OpenAPI规范的自动接口文档生成框架,解决前后端分离项目接口文档编写、更新、对接痛点,支持在线调试。
核心价值:代码即文档,实现接口文档自动化、标准化,大幅提升团队开发与对接效率。
技术局限:旧版停止维护、存在少量安全隐患、需手动添加注解,生产环境需手动关闭。
AOP结合核心意义:Swagger负责接口标准化定义,AOP负责接口统一增强管控,实现接口日志审计、权限拦截、监控统计全局统一处理,解耦业务与通用功能。
企业规范:开发、测试环境开启Swagger方便对接调试,生产环境关闭保障安全;复杂项目推荐Swagger+AOP组合实现接口统一管控。