目录一、前言二、Swagger2 vs Swagger3 主要变化三、环境准备四、快速集成步骤4.1 创建 Spring Boot 项目4.2 添加 Swagger3 依赖4.3 配置文件4.4 OpenAPI 配置类五、核心注解使用5.1 创建实体类5.2 创建请求/响应包装类5.3 创建 Controller 示例5.4 注解说明六、高级配置6.1 接口分组6.2 隐藏接口6.3 全局响应码配置七、测试验证八、常见问题及解决8.1 访问 Swagger UI 出现 4048.2 接口文档中没有显示实体类字段描述8.3 生产环境不想暴露接口文档九、总结一、前言在前后端分离的开发模式下接口文档的重要性不言而喻。传统的手写文档方式存在维护困难、更新不及时、与代码脱节等问题。Swagger 作为一款优秀的接口文档生成工具可以自动根据代码生成接口文档极大地提高了开发效率。随着 Swagger 的演进Swagger3即 OpenAPI 3.0 规范相较于 Swagger2 有了较大的变化。本文将详细介绍如何在 Spring Boot 项目中集成 Swagger3并展示常用的配置和注解使用方式。二、Swagger2 vs Swagger3 主要变化在开始之前我们先了解一下 Swagger3 相比 Swagger2 的主要变化对比项Swagger2Swagger3依赖包springfox-swagger2springfox-swagger-uispringdoc-openapi-starter-webmvc-ui访问地址/swagger-ui.html/swagger-ui/index.html注解包io.swagger.annotationsio.swagger.v3.oas.annotations核心注解Api、ApiOperation等Tag、Operation等配置方式需要EnableSwagger2注解自动配置无需额外注解三、环境准备本文使用的开发环境JDK 17Spring Boot 3.xMaven 3.6注意Spring Boot 3.x 最低要求 JDK 17且不再支持 Swagger2 的 springfox因此我们使用 springdoc-openapi 来实现 Swagger3 集成。四、快速集成步骤4.1 创建 Spring Boot 项目首先创建一个 Spring Boot 项目添加 Web 依赖。4.2 添加 Swagger3 依赖在pom.xml中添加 springdoc-openapi 依赖dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-starter-webmvc-ui/artifactId version2.6.0/version /dependency这个依赖包含了OpenAPI 3.0 规范的支持Swagger UI 界面自动配置功能4.3 配置文件在application.yml中添加 Swagger 相关配置spring: application: name: swagger3-demo # SpringDoc 配置 springdoc: # 接口文档路径默认为 /v3/api-docs api-docs: path: /v3/api-docs enabled: true # Swagger UI 路径默认为 /swagger-ui.html swagger-ui: path: /swagger-ui.html enabled: true # 展开策略none不展开、list展开标签、full全部展开 doc-expansion: none # 请求超时时间 urls-primary-name: default # 包扫描路径多个用逗号分隔 packages-to-scan: com.example.controller # 路径匹配规则 paths-to-match: /**4.4 OpenAPI 配置类创建一个配置类用于自定义文档信息package com.example.config; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; 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(Spring Boot 3.x 集成 Swagger3 接口文档) .version(1.0.0) .description(这是一份 Swagger3 接口文档示例) .contact(new Contact() .name(作者) .email(authorexample.com) .url(https://example.com)) .license(new License() .name(Apache 2.0) .url(https://www.apache.org/licenses/LICENSE-2.0.html))); } }至此Swagger3 已经集成完成启动项目后访问http://localhost:8080/swagger-ui/index.html即可看到接口文档界面。五、核心注解使用Swagger3 提供了一系列注解来丰富接口文档内容。下面通过一个完整的 Controller 示例来演示常用注解的使用。5.1 创建实体类package com.example.entity; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; Data Schema(description 用户实体) public class User { Schema(description 用户ID, example 1) private Long id; Schema(description 用户名, example 张三, required true) private String username; Schema(description 邮箱, example zhangsanexample.com) private String email; Schema(description 年龄, example 25) private Integer age; }5.2 创建请求/响应包装类package com.example.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; Data Schema(description 通用响应结果) public class ResultT { Schema(description 状态码, example 200) private Integer code; Schema(description 提示信息, example success) private String message; Schema(description 数据) private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(success); result.setData(data); return result; } public static T ResultT error(String message) { ResultT result new Result(); result.setCode(500); result.setMessage(message); return result; } }package com.example.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; Data Schema(description 用户查询参数) public class UserQueryDTO { Schema(description 用户名模糊查询, example 张) private String username; Schema(description 最小年龄, example 18) private Integer minAge; Schema(description 最大年龄, example 60) private Integer maxAge; Schema(description 当前页码, example 1, defaultValue 1) private Integer pageNum 1; Schema(description 每页条数, example 10, defaultValue 10) private Integer pageSize 10; }5.3 创建 Controller 示例package com.example.controller; import com.example.dto.Result; import com.example.dto.UserQueryDTO; import com.example.entity.User; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.enums.ParameterIn; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.List; RestController RequestMapping(/api/users) Tag(name 用户管理, description 用户相关的接口) public class UserController { /** * 模拟数据存储 */ private final ListUser userList new ArrayList(); /** * 获取用户列表 */ GetMapping Operation(summary 获取用户列表, description 分页查询用户信息) ApiResponses(value { ApiResponse(responseCode 200, description 查询成功, content Content(schema Schema(implementation Result.class))), ApiResponse(responseCode 500, description 服务器内部错误) }) public ResultListUser getUsers( Parameter(description 用户名模糊查询) RequestParam(required false) String username, Parameter(description 年龄) RequestParam(required false) Integer age) { // 模拟查询逻辑 ListUser result userList.stream() .filter(u - username null || u.getUsername().contains(username)) .filter(u - age null || u.getAge().equals(age)) .toList(); return Result.success(result); } /** * 获取用户详情 */ GetMapping(/{id}) Operation(summary 获取用户详情, description 根据ID获取用户详细信息) ApiResponses(value { ApiResponse(responseCode 200, description 查询成功), ApiResponse(responseCode 404, description 用户不存在) }) public ResultUser getUserById( Parameter(description 用户ID, required true, example 1) PathVariable Long id) { User user userList.stream() .filter(u - u.getId().equals(id)) .findFirst() .orElse(null); if (user null) { return Result.error(用户不存在); } return Result.success(user); } /** * 创建用户 */ PostMapping Operation(summary 创建用户, description 新增用户信息) ApiResponses(value { ApiResponse(responseCode 200, description 创建成功), ApiResponse(responseCode 400, description 参数校验失败) }) public ResultUser createUser( io.swagger.v3.oas.annotations.parameters.RequestBody( description 用户信息, required true, content Content(schema Schema(implementation User.class)) ) RequestBody User user) { user.setId(System.currentTimeMillis()); userList.add(user); return Result.success(user); } /** * 更新用户 */ PutMapping(/{id}) Operation(summary 更新用户, description 根据ID更新用户信息) public ResultUser updateUser( Parameter(description 用户ID, required true) PathVariable Long id, RequestBody User user) { // 模拟更新逻辑 user.setId(id); return Result.success(user); } /** * 删除用户 */ DeleteMapping(/{id}) Operation(summary 删除用户, description 根据ID删除用户) Parameters({ Parameter(name id, description 用户ID, required true, in ParameterIn.PATH), Parameter(name force, description 是否强制删除, in ParameterIn.QUERY) }) public ResultVoid deleteUser( PathVariable Long id, RequestParam(defaultValue false) Boolean force) { // 模拟删除逻辑 return Result.success(null); } /** * 条件查询用户使用对象接收参数 */ PostMapping(/search) Operation(summary 条件查询用户, description 根据多个条件组合查询用户) public ResultListUser searchUsers(RequestBody UserQueryDTO queryDTO) { // 模拟查询逻辑 ListUser result userList.stream() .filter(u - queryDTO.getUsername() null || u.getUsername().contains(queryDTO.getUsername())) .filter(u - queryDTO.getMinAge() null || u.getAge() queryDTO.getMinAge()) .filter(u - queryDTO.getMaxAge() null || u.getAge() queryDTO.getMaxAge()) .toList(); return Result.success(result); } }5.4 注解说明注解作用使用位置Tag对 API 进行分组描述Controller 类Operation描述一个 API 操作方法Parameter描述接口参数方法参数、方法Parameters多个参数描述的组合方法ApiResponse描述响应信息方法ApiResponses多个响应描述的组合方法Schema描述模型属性实体类、DTOContent描述请求/响应内容配合 ApiResponse 使用六、高级配置6.1 接口分组当项目接口较多时可以通过分组来组织文档springdoc: group-config: groups: - name: 用户管理 paths-to-match: /api/users/** packages-to-scan: com.example.controller.user - name: 订单管理 paths-to-match: /api/orders/** packages-to-scan: com.example.controller.order或者通过代码方式配置分组Configuration public class OpenApiGroupConfig { Bean public GroupedOpenApi userApi() { return GroupedOpenApi.builder() .group(用户管理) .pathsToMatch(/api/users/**) .packagesToScan(com.example.controller.user) .build(); } Bean public GroupedOpenApi orderApi() { return GroupedOpenApi.builder() .group(订单管理) .pathsToMatch(/api/orders/**) .packagesToScan(com.example.controller.order) .build(); } }6.2 隐藏接口如果需要隐藏某些接口可以使用Hidden注解Hidden // 此接口不会出现在文档中 GetMapping(/internal) public String internalApi() { return 内部接口; }6.3 全局响应码配置Configuration public class OpenApiConfig { Bean public OpenAPI customOpenAPI() { return new OpenAPI() .components(new Components() .addResponses(BadRequest, new ApiResponse() .description(请求参数错误)) .addResponses(Unauthorized, new ApiResponse() .description(未授权)) .addResponses(Forbidden, new ApiResponse() .description(无权限访问)) .addResponses(NotFound, new ApiResponse() .description(资源不存在)) .addResponses(InternalServerError, new ApiResponse() .description(服务器内部错误))) .info(...); } }七、测试验证启动 Spring Boot 应用访问以下地址Swagger UI 界面http://localhost:8080/swagger-ui/index.htmlOpenAPI JSON 文档http://localhost:8080/v3/api-docs在 Swagger UI 界面中可以看到分组后的接口列表每个接口的请求方式、路径、描述请求参数说明响应示例在线测试功能八、常见问题及解决8.1 访问 Swagger UI 出现 404原因可能没有添加依赖或者 Spring Boot 版本不兼容。解决确保添加了正确的依赖Spring Boot 3.x 必须使用springdoc-openapi-starter-webmvc-ui。8.2 接口文档中没有显示实体类字段描述原因没有使用Schema注解标注实体类字段。解决在实体类字段上添加Schema(description 字段描述)。8.3 生产环境不想暴露接口文档解决方法通过配置控制是否启用springdoc: api-docs: enabled: false # 关闭 API 文档 swagger-ui: enabled: false # 关闭 Swagger UI或者通过 profile 控制springdoc: enabled: false九、总结本文详细介绍了在 Spring Boot 3.x 中集成 Swagger3OpenAPI 3.0的完整流程包括Swagger2 与 Swagger3 的主要区别依赖引入和基础配置核心注解的使用方法高级配置分组、隐藏接口、全局响应码常见问题及解决方案通过 Swagger3我们可以轻松地为 Spring Boot 项目生成规范、清晰的接口文档并且支持在线调试功能大大提升了前后端协作的效率。SpringDoc 作为 Swagger3 在 Spring Boot 中的官方推荐实现配置简单、功能强大是构建 RESTful API 文档的最佳选择。参考资料SpringDoc 官方文档OpenAPI 3.0 规范Swagger 注解参考