SpringBoot Swagger

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 groupIdio.springfox/groupId artifactIdspringfox-swagger2/artifactId version2.9.2/version /dependency dependency groupIdio.springfox/groupId artifactIdspringfox-swagger-ui/artifactId version2.9.2/version /dependency5.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/jsonconsumes指定模块统一请求Content-Typehidden布尔值是否隐藏当前模块所有接口true则不生成文档// 官网标准完整写法 Api( tags 用户管理模块, value 用户业务接口, description 包含用户新增、查询、修改、删除、登录等全部用户相关接口, produces application/json;charsetUTF-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指定接口返回实体Classcode接口默认成功状态码// 官网完整规范写法 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等异常返回信息是企业规范文档必填注解。属性说明codeHTTP响应状态码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是否为必填参数默认falseexample参数示例值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、Parameter6.8 注解使用官网最佳规范所有对外业务接口必须补齐Api ApiOperation ApiResponses全套注解所有请求/返回实体必须补齐ApiModel ApiModelProperty字段说明与示例值敏感字段密码、密钥、身份证通过hiddentrue隐藏禁止暴露文档测试接口、内部接口统一使用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 查询成功; } }步骤3AOP切面类拦截所有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 SwaggerAOP 组合优缺点✅ 组合优势代码零侵入业务接口无需重复写日志、监控代码统一切面处理接口标准化管控统一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高阶拓展企业首选SpringDocSwagger升级版无依赖冲突、适配SpringBoot3.x新项目首选十、归纳总结面试万能标准答案技术定位Swagger是基于OpenAPI规范的自动接口文档生成框架解决前后端分离项目接口文档编写、更新、对接痛点支持在线调试。核心价值代码即文档实现接口文档自动化、标准化大幅提升团队开发与对接效率。技术局限旧版停止维护、存在少量安全隐患、需手动添加注解生产环境需手动关闭。AOP结合核心意义Swagger负责接口标准化定义AOP负责接口统一增强管控实现接口日志审计、权限拦截、监控统计全局统一处理解耦业务与通用功能。企业规范开发、测试环境开启Swagger方便对接调试生产环境关闭保障安全复杂项目推荐SwaggerAOP组合实现接口统一管控。