最新版 springdoc-openapi-starter-webmvc-ui 常用注解详解 + 实战示例

当然可以!在 Spring Boot 3 + SpringDoc OpenAPI(Swagger 3 替代方案)生态中,springdoc-openapi-starter-webmvc-ui 是目前官方推荐的集成方式。它提供了一套丰富的注解,用于精细化控制 API 文档的生成,提升前端、测试、产品等协作方的体验。


最新版 springdoc-openapi-starter-webmvc-ui 常用注解详解 + 实战示例

📌 当前最新稳定版本:springdoc-openapi 2.5+(2025年仍适用)
📌 所有注解位于包:io.swagger.v3.oas.annotations.*

🧩 一、核心注解概览

注解作用适用位置
@OpenAPIDefinition全局 API 信息配置(标题、版本、联系人等)@Configuration
@Tag标记 Controller 或方法所属的“标签/模块”类、方法
@Operation描述某个 API 操作(方法)的详细信息方法
@Parameter描述单个请求参数(路径、查询、Header)方法参数
@Parameters批量描述多个参数方法
@RequestBody描述请求体结构方法参数
@ApiResponse描述单个响应状态码及结构方法
@ApiResponses批量描述多个响应方法
@Schema描述 DTO 字段的含义、示例、格式等类、字段、方法参数
@Hidden隐藏某个 Controller 或方法,不生成文档类、方法、字段

🧱 二、详细注解说明 + 实战示例(带中文注释)


1️⃣ @Tag —— 模块分组标签

用于对 Controller 或方法进行分组,前端文档左侧菜单按 Tag 分组显示。
@Tag(name ="用户管理模块", description ="提供用户增删改查、状态管理等核心功能")@RestController@RequestMapping("/api/users")publicclassUserController{// ...}

作用

  • 在 Swagger UI 左侧菜单中显示为“用户管理模块”。
  • 可用于模块化组织大型项目 API。

2️⃣ @Operation —— API 操作描述

描述某个接口的用途、注意事项、是否已废弃等。
@Operation( summary ="分页查询用户列表", description ="支持按用户名、年龄范围、状态筛选,返回分页数据。\n"+"createTime 字段为 ISO 格式,如:2025-04-01T10:00:00", tags ={"用户管理模块"},// 可覆盖类上的 Tag deprecated =false,// 是否废弃 security =@SecurityRequirement(name ="Bearer Token")// 安全要求(需配合 SecurityScheme))@GetMappingpublicResult<IPage<UserVO>>listUsers(@Parameter(description ="当前页码,从1开始", example ="1")@RequestParam(defaultValue ="1")Integer current,@Parameter(description ="每页大小,最大100", example ="10")@RequestParam(defaultValue ="10")Integer size,UserQueryDTO query){// ...}

作用

  • summary:接口简短标题(必填,显示在接口列表)
  • description:详细说明,支持 Markdown
  • deprecated:标记为废弃接口(UI 会显示删除线)
  • security:声明该接口需要认证(需全局配置 SecurityScheme)

3️⃣ @Parameter —— 单个参数描述

用于描述 @RequestParam, @PathVariable, @RequestHeader 等参数。
@GetMapping("/{id}")@Operation(summary ="根据ID获取用户详情")publicResult<UserVO>getUserById(@Parameter( name ="id", description ="用户唯一标识,雪花ID", required =true, example ="123456789012345678", schema =@Schema(type ="integer", format ="int64"))@PathVariableLong id){User user = userService.getById(id);if(user ==null){returnResult.error(404,"用户不存在");}returnResult.success(userStructMapper.toVO(user));}

作用

  • name:参数名(通常可省略,自动推断)
  • description:参数说明
  • required:是否必填
  • example:示例值(非常重要!前端可一键填充)
  • schema:指定数据类型和格式(如 int64、date-time、email 等)

4️⃣ @RequestBody —— 请求体描述

用于描述 @RequestBody 注解的 DTO 对象结构。
@PostMapping@Operation(summary ="创建新用户")publicResult<String>createUser(@io.swagger.v3.oas.annotations.parameters.RequestBody( description ="用户创建请求体", required =true, content =@Content( mediaType ="application/json", schema =@Schema(implementation =UserCreateDTO.class), examples ={@ExampleObject( name ="创建普通用户", value =""" { "name": "张三", "age": 25, "email": "[email protected]", "status": 1 } """),@ExampleObject( name ="创建未成年用户", value =""" { "name": "小明", "age": 16, "email": "[email protected]", "status": 0 } """)}))@Valid@RequestBodyUserCreateDTO createDTO){boolean saved = userService.createUser(createDTO);return saved ?Result.success("用户创建成功"):Result.error("创建失败");}

作用

  • description:请求体说明
  • content.schema.implementation:指定 DTO 类,自动生成字段文档
  • examples:提供多个示例(前端可切换使用)
  • 支持 JSON/YAML 示例
💡 注意:不要与 org.springframework.web.bind.annotation.RequestBody 混淆,这里是 io.swagger.v3.oas.annotations.parameters.RequestBody

5️⃣ @Schema —— 字段/类级描述(最常用!)

用于描述 DTO/Entity 的字段含义、格式、示例、是否只读等。
@Data@Schema(description ="用户创建请求参数")publicclassUserCreateDTO{@Schema( description ="用户名,2-20位中文或英文", example ="张三", minLength =2, maxLength =20, requiredMode =Schema.RequiredMode.REQUIRED // 必填)@NotBlank(message ="用户名不能为空")privateString name;@Schema( description ="年龄,0-150岁", example ="25", minimum ="0", maximum ="150", requiredMode =Schema.RequiredMode.REQUIRED )@NotNull(message ="年龄不能为空")@Min(value =0, message ="年龄不能小于0")privateInteger age;@Schema( description ="邮箱地址", example ="[email protected]", format ="email",// 格式校验提示 requiredMode =Schema.RequiredMode.NOT_REQUIRED )@Email(message ="邮箱格式不正确")privateString email;@Schema( description ="用户状态:0=禁用,1=启用", example ="1", allowableValues ={"0","1"},// 枚举值提示 requiredMode =Schema.RequiredMode.REQUIRED )@NotNull(message ="状态不能为空")privateInteger status;}

作用

  • 自动生成字段说明、示例、校验规则提示
  • format:支持 date, date-time, email, uuid, uri
  • allowableValues:枚举值提示(前端下拉可选)
  • accessMode:可设置 READ_ONLY(仅响应)或 WRITE_ONLY(仅请求,如密码字段)
  • implementation:用于嵌套对象或接口类型

6️⃣ @ApiResponse & @ApiResponses —— 响应结构描述

描述不同 HTTP 状态码对应的响应结构,特别是错误码。
@PutMapping@Operation(summary ="更新用户信息")@ApiResponses(value ={@ApiResponse( responseCode ="200", description ="更新成功", content =@Content(schema =@Schema(implementation =Result.class))),@ApiResponse( responseCode ="400", description ="参数校验失败", content =@Content(schema =@Schema(implementation =Result.class))),@ApiResponse( responseCode ="404", description ="用户不存在", content =@Content(schema =@Schema(implementation =Result.class))),@ApiResponse( responseCode ="500", description ="系统内部错误", content =@Content(schema =@Schema(implementation =Result.class)))})publicResult<String>updateUser(@Valid@RequestBodyUserUpdateDTO updateDTO){boolean updated = userService.updateUser(updateDTO);return updated ?Result.success("更新成功"):Result.error("更新失败");}

作用

  • 前端可预知不同状态码的响应结构
  • 配合全局异常处理器,可标准化错误返回
  • responseCode:HTTP 状态码
  • description:状态码含义
  • content.schema:指定响应体结构(通常为 Result<T>

7️⃣ @Hidden —— 隐藏接口或字段

隐藏不想暴露给前端的接口或敏感字段。
@Hidden// 整个 Controller 不生成文档@RestController@RequestMapping("/api/internal")publicclassInternalController{// ...}// 或隐藏某个字段(如密码、密钥)@DatapublicclassUserVO{privateLong id;privateString name;@Hidden// 不在 Swagger 中显示privateString internalCode;privateString email;}

作用

  • 隐藏内部接口(如运维、回调、定时任务触发接口)
  • 隐藏敏感字段(如密码、密钥、审计字段)

8️⃣ @OpenAPIDefinition —— 全局 API 信息配置

通常放在启动类或独立配置类中,定义 API 全局元信息。
@OpenAPIDefinition( info =@Info( title ="企业用户管理系统 API 文档", version ="v1.2.0", description ="提供用户管理、权限控制、操作日志等核心功能", contact =@Contact( name ="API支持团队", email ="[email protected]", url ="https://www.company.com"), license =@License( name ="Apache 2.0", url ="https://www.apache.org/licenses/LICENSE-2.0.html")), servers ={@Server(url ="http://localhost:8080", description ="本地开发环境"),@Server(url ="https://api.company.com", description ="生产环境")})@SpringBootApplication@MapperScan("com.example.demo.mapper")publicclassDemoApplication{publicstaticvoidmain(String[] args){SpringApplication.run(DemoApplication.class, args);}}

作用

  • 定义 API 标题、版本、描述、联系人、许可证
  • 定义多环境服务器地址(前端可切换)
  • 显示在 Swagger UI 顶部

9️⃣ @SecurityScheme + @SecurityRequirement —— 安全认证配置

配置 JWT/Bearer Token 认证方式。
@SecurityScheme( name ="Bearer Token", type =SecuritySchemeType.HTTP, bearerFormat ="JWT", scheme ="bearer"// 小写 bearer)@ConfigurationpublicclassOpenApiConfig{// 可放在此类,或与 @OpenAPIDefinition 合并}

然后在需要认证的接口上添加:

@Operation( summary ="删除用户", security =@SecurityRequirement(name ="Bearer Token")// 引用上面定义的 name)@DeleteMapping("/{id}")publicResult<String>deleteUser(@PathVariableLong id){// ...}

作用

  • Swagger UI 顶部会出现 🔒 认证按钮
  • 前端可输入 Token,后续请求自动带 Authorization: Bearer xxx
  • 提升 API 安全性和测试便利性

🧪 三、完整 Controller 示例(整合所有注解)

packagecom.example.demo.controller;importcom.example.demo.entity.dto.*;importcom.example.demo.entity.vo.UserVO;importcom.example.demo.service.IUserService;importcom.example.demo.util.Result;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.extension.plugins.pagination.Page;importio.swagger.v3.oas.annotations.Operation;importio.swagger.v3.oas.annotations.Parameter;importio.swagger.v3.oas.annotations.Parameters;importio.swagger.v3.oas.annotations.media.Content;importio.swagger.v3.oas.annotations.media.ExampleObject;importio.swagger.v3.oas.annotations.media.Schema;importio.swagger.v3.oas.annotations.responses.ApiResponse;importio.swagger.v3.oas.annotations.responses.ApiResponses;importio.swagger.v3.oas.annotations.security.SecurityRequirement;importio.swagger.v3.oas.annotations.tags.Tag;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.validation.annotation.Validated;importorg.springframework.web.bind.annotation.*;importjavax.validation.Valid;importjavax.validation.constraints.Min;importjavax.validation.constraints.NotNull;@Tag(name ="用户管理模块", description ="提供用户增删改查、状态管理、批量操作等核心功能")@Validated@RestController@RequestMapping("/api/users")publicclassUserController{@AutowiredprivateIUserService userService;@AutowiredprivateUserStructMapper userStructMapper;// ==================== 查询 ====================@Operation( summary ="分页查询用户列表", description =""" 支持多条件组合查询: - 按用户名模糊匹配 - 按年龄范围筛选 - 按状态精确匹配 - 按创建时间区间筛选 返回标准分页结构。 """, security =@SecurityRequirement(name ="Bearer Token"))@Parameters({@Parameter(name ="current", description ="当前页码,从1开始", example ="1", required =true),@Parameter(name ="size", description ="每页大小,建议10~50", example ="10", required =true)})@ApiResponses({@ApiResponse(responseCode ="200", description ="查询成功", content =@Content(schema =@Schema(implementation =Result.class))),@ApiResponse(responseCode ="401", description ="未授权", content =@Content(schema =@Schema(implementation =Result.class)))})@GetMappingpublicResult<IPage<UserVO>>listUsers(@Min(1)@RequestParam(defaultValue ="1")Integer current,@Min(1)@RequestParam(defaultValue ="10")Integer size,UserQueryDTO query){Page<User> page =newPage<>(current, size);IPage<User> userPage = userService.searchUsers(query, page);List<UserVO> voList = userStructMapper.toVOList(userPage.getRecords());IPage<UserVO> voPage =newPage<>(userPage.getCurrent(), userPage.getSize(), userPage.getTotal()); voPage.setRecords(voList);returnResult.success(voPage);}// ==================== 创建 ====================@Operation( summary ="创建新用户", description ="创建用户时会自动填充创建时间,状态默认启用")@io.swagger.v3.oas.annotations.parameters.RequestBody( description ="用户创建请求体", required =true, content =@Content( mediaType ="application/json", schema =@Schema(implementation =UserCreateDTO.class), examples ={@ExampleObject( name ="成人用户", value =""" { "name": "张三", "age": 25, "email": "[email protected]", "status": 1 } """),@ExampleObject( name ="未成年用户", value =""" { "name": "小明", "age": 16, "email": "[email protected]", "status": 0 } """)}))@PostMappingpublicResult<String>createUser(@Valid@RequestBodyUserCreateDTO createDTO){boolean saved = userService.createUser(createDTO);return saved ?Result.success("用户创建成功"):Result.error("创建失败");}// ==================== 更新 ====================@Operation(summary ="更新用户信息")@PutMappingpublicResult<String>updateUser(@Valid@RequestBodyUserUpdateDTO updateDTO){boolean updated = userService.updateUser(updateDTO);return updated ?Result.success("更新成功"):Result.error("更新失败");}// ==================== 删除 ====================@Operation( summary ="删除用户(逻辑删除)", description ="不会物理删除数据,仅标记 deleted=1", security =@SecurityRequirement(name ="Bearer Token"))@Parameter(name ="id", description ="用户ID", required =true, example ="123456789012345678")@DeleteMapping("/{id}")publicResult<String>deleteUser(@PathVariable@NotNullLong id){boolean deleted = userService.removeById(id);return deleted ?Result.success("删除成功"):Result.error("用户不存在或已被删除");}}

✅ 四、最佳实践建议

实践项说明
所有公开接口必须加 @Operation至少写 summary,让前端知道接口用途
DTO 字段必须加 @Schema描述 + 示例 + 校验规则,极大提升协作效率
关键参数加 @Parameter(example=...)前端可一键填充测试数据
提供多个 @ExampleObject覆盖正常、边界、异常场景
敏感接口加 @SecurityRequirement明确告知需要 Token
废弃接口加 deprecated = true前端可见,避免误用
内部接口用 @Hidden避免文档混乱
全局配置 @OpenAPIDefinition统一团队 API 文档风格

🌐 五、访问与调试

  • 文档地址:http://localhost:8080/swagger-ui/index.html
  • OpenAPI JSON:http://localhost:8080/v3/api-docs
  • 支持 Try it out → 在线调试 → 自动生成 Curl/Request

✅ 六、总结

通过合理使用 SpringDoc OpenAPI 注解,你可以:

✅ 生成专业级、可交互、可调试的 API 文档
减少前后端沟通成本,提升开发效率
标准化接口设计,避免“口口相传”
提升项目专业度和可维护性

💡 提示:注解虽好,但不要过度堆砌。保持简洁、实用、一致即可。大型项目建议制定《API 文档规范》,统一注解使用标准。

📌 官方文档参考:https://springdoc.org/


这份指南涵盖了企业开发中 95% 以上的 SpringDoc 注解使用场景,可直接用于生产项目!

Read more

Android WebRTC 视频通话开发实战:从零搭建到性能调优

快速体验 在开始今天关于 Android WebRTC 视频通话开发实战:从零搭建到性能调优 的探讨之前,我想先分享一个最近让我觉得很有意思的全栈技术挑战。 我们常说 AI 是未来,但作为开发者,如何将大模型(LLM)真正落地为一个低延迟、可交互的实时系统,而不仅仅是调个 API? 这里有一个非常硬核的动手实验:基于火山引擎豆包大模型,从零搭建一个实时语音通话应用。它不是简单的问答,而是需要你亲手打通 ASR(语音识别)→ LLM(大脑思考)→ TTS(语音合成)的完整 WebSocket 链路。对于想要掌握 AI 原生应用架构的同学来说,这是个绝佳的练手项目。 从0到1构建生产级别应用,脱离Demo,点击打开 从0打造个人豆包实时通话AI动手实验 Android WebRTC 视频通话开发实战:从零搭建到性能调优 移动端P2P视频通话的三大挑战 开发Android端视频通话应用时,我们常遇到几个核心难题: * NAT穿透/NAT Traversal:

乡村政务办公系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

乡村政务办公系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

摘要 随着信息技术的快速发展,数字化政务管理成为提升乡村治理效率的重要手段。传统的乡村政务办公模式依赖纸质文档和人工操作,存在效率低、信息传递滞后、数据易丢失等问题。乡村政务信息管理系统的建设能够有效解决这些问题,实现政务信息的数字化、规范化和高效化管理。该系统通过整合SpringBoot后端、Vue前端和MySQL数据库技术,构建了一个功能完善、操作便捷的乡村政务办公平台。关键词:乡村政务、数字化管理、SpringBoot、Vue、MySQL。 该系统采用SpringBoot作为后端框架,提供高效的接口服务和数据处理能力;Vue作为前端框架,实现用户友好的交互界面;MySQL作为数据库,确保数据的稳定存储和高效查询。系统功能涵盖村民信息管理、帮扶信息管理、新闻公告发布等模块,支持数据的增删改查、多条件筛选和统计分析。系统设计注重实用性和可扩展性,能够满足乡村政务办公的多样化需求。关键词:村民信息管理、帮扶信息管理、新闻公告、数据统计分析。 数据表设计 村民信息数据表 村民信息数据表用于存储村民的基本信息,包括姓名、身份证号、联系方式等。创建时间通过函数自动获取,村民ID是该

3步搞定通义千问3-14B部署:Ollama+WebUI双buff叠加教程

3步搞定通义千问3-14B部署:Ollama+WebUI双buff叠加教程 1. 为什么Qwen3-14B值得你花5分钟部署 你有没有遇到过这样的困境:想用一个真正能干活的大模型,但发现30B级别的性能动辄要双卡A100,本地跑不动;而能单卡运行的模型,又常常在长文档理解、复杂推理或多语言任务上“掉链子”? Qwen3-14B就是为这个痛点而生的——它不是“缩水版”,而是“精准裁剪版”。148亿参数全激活(非MoE稀疏结构),却在C-Eval、MMLU、GSM8K等权威榜单上交出接近30B模型的答卷。更关键的是,它原生支持128k上下文,实测轻松处理40万汉字的PDF报告、法律合同或技术白皮书,一次喂入,整篇理解。 它不靠参数堆砌,而是靠架构优化和训练策略升级:FP8量化后仅14GB显存占用,在RTX 4090(24GB)上就能全速推理,每秒生成80个token;同时提供两种推理模式——你可以让它“慢思考”,显式输出<think>中的逻辑链,专攻数学证明、代码调试、多步推理;也可以一键切到“快回答”

Clawdbot整合Qwen3-32B保姆级教程:Web网关18789端口调试全记录

Clawdbot整合Qwen3-32B保姆级教程:Web网关18789端口调试全记录 1. 为什么需要这个整合方案 你是不是也遇到过这样的问题:想用本地部署的大模型做聊天机器人,但发现直接调用Ollama的API在Web前端里跨域报错?或者Clawdbot配置完后一直连不上模型,控制台疯狂刷404?又或者好不容易跑起来了,发个消息却卡在“正在思考”半天没反应? 这正是我们搭建这套环境时踩过的坑。Clawdbot本身不直接对接Ollama,它需要一个中间层来处理协议转换、请求转发和端口映射。而18789这个端口,就是整个链路里最关键的“通关密码”——它不是随便选的,而是Clawdbot默认监听的Web网关入口。 整套方案的核心逻辑其实很朴素: * 你在浏览器里访问 http://localhost:18789,看到的是Clawdbot的聊天界面 * Clawdbot收到你的消息后,不自己去算答案,而是把请求转给内部代理 * 代理再把请求发到 http://localhost:8080(Ollama API地址) * Ollama调用本地的Qwen3-32B模型生成回复