Swagger 3.0 + Knife4j 入门到实战:Spring Boot API 文档搭建、注解详解与生产环境配置
Swagger 3.0 与 Knife4j
摘要:本文介绍 Swagger 3.0 与 Knife4j 的入门知识。文档详解常用注解(如 @Tag、@Operation、@Schema 等),提供实体类与控制器示例,还涵盖 API 分组、全局参数配置,以及生产环境关闭 Swagger 的方法,同时列举常见问题及解决办法与学习资源。
1. 什么是 Swagger 和 Knife4j?
Swagger 3.0
Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。Swagger 3.0(也称为 OpenAPI 3.0)是其最新版本,提供了更强大的功能和更简洁的语法。
Knife4j
Knife4j 是一款基于 Swagger 的增强工具,为 Java 开发者提供了更加友好的 API 文档界面和更多实用功能。它封装了 Swagger 的底层实现,让开发者能更简单地在 Spring Boot 项目中集成 Swagger。
knife4j-openapi3-jakarta-spring-boot-starter:4.5.0
是适用于 Jakarta EE 规范(替代传统的 JEE)的 Spring Boot starter,简化了 Swagger 3.0 在 Spring Boot 项目中的集成。
2. 环境准备
开发环境要求
- JDK 11 或更高版本
- Spring Boot 2.7.x 或 3.x
- Maven 或 Gradle 构建工具
3. 快速开始
3.1 创建 Spring Boot 项目并添加依赖
Maven 项目(pom.xml)
<dependencies><!-- Spring Boot Web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Knife4j OpenAPI3 Jakarta 依赖 --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.5.0</version></dependency>
</dependencies>
Gradle 项目(build.gradle)
dependencies {implementation 'org.springframework.boot:spring-boot-starter-web'implementation 'com.github.xiaoymin:knife4j-openapi3-jakarta-spring-boot-starter:4.5.0'
}
3.2 基本配置
创建配置类:
@Configuration
public class SwaggerConfig {@Beanpublic OpenAPI customOpenAPI() {return new OpenAPI()// API 基本信息.info(new Info().title("我的 API 文档") // 标题.description("这是一个使用 Knife4j 和 Swagger 3.0 构建的 API 文档示例") // 描述.version("1.0.0") // 版本// 联系人信息.contact(new Contact().name("开发者").email("developer@example.com").url("https://www.example.com"))// 许可证信息.license(new License().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0")));}
}
3.3 启动应用并访问文档
- 创建 Spring Boot 启动类:
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
- 启动应用后,访问 Knife4j 文档界面:
- 地址:
http://localhost:8080/doc.html
- 你将看到 Knife4j 提供的友好 API 文档界面
- 地址:
4. 常用注解详解
Swagger 3.0 提供了一系列注解来描述 API,以下是常用注解的说明:
4.1 类级别注解
@Tag
用于描述控制器类的作用
@Tag(name = "用户管理", description = "用户的增删改查操作")
@RestController
@RequestMapping("/users")
public class UserController {// ...
}
4.2 方法级别注解
@Operation
用于描述接口方法的作用
@Operation(summary = "获取用户列表", description = "查询所有用户信息")
@GetMapping
public List<User> getUsers() {// ...
}
@Parameter
用于描述方法参数
@Operation(summary = "获取用户详情", description = "根据ID查询用户信息")
@GetMapping("/{id}")
public User getUserById(@Parameter(description = "用户ID", required = true, example = "1") @PathVariable Long id
) {// ...
}
@ApiResponses 和 @ApiResponse
用于描述接口的响应信息
@Operation(summary = "删除用户", description = "根据ID删除用户")
@ApiResponses({@ApiResponse(responseCode = "200", description = "删除成功"),@ApiResponse(responseCode = "404", description = "用户不存在")
})
@DeleteMapping("/{id}")
public String deleteUser(@PathVariable Long id) {// ...
}
4.3 实体类注解
@Schema
用于描述实体类或其属性
@Schema(description = "用户实体类")
public class User {@Schema(description = "用户ID", example = "1")private Long id;@Schema(description = "用户名", example = "张三", required = true)private String name;@Schema(description = "用户年龄", example = "25", minimum = "0", maximum = "120")private Integer age;// getter 和 setter 方法
}
4.4 用注解和核心属性
注解名称 | 适用范围 | 作用描述 | 常用属性及解释 |
---|---|---|---|
@Tag | 类(控制器) | 描述控制器的整体功能,用于对接口进行分类 | - name :控制器名称(必填,如 “用户管理”)- description :控制器功能描述(如 “用户的增删改查操作”) |
@Operation | 方法(接口) | 描述单个接口的功能、用途和细节 | - summary :接口简要说明(如 “获取用户列表”)- description :接口详细描述(如 “查询所有用户信息”)- hidden :是否隐藏接口(默认 false,设为 true 则不显示在文档中) |
@Parameter | 方法参数 | 描述接口的单个参数(如路径参数、请求参数) | - name :参数名称- description :参数描述- required :是否必填(默认 false)- example :参数示例值- in :参数位置(如 “path” 路径参数、“query” 查询参数,默认自动推断) |
@Parameters | 方法 | 用于包含多个 @Parameter 注解,批量描述参数 | - 无单独属性,内部包含多个 @Parameter 注解 |
@ApiResponses | 方法 | 用于包含多个 @ApiResponse 注解,批量描述接口的响应结果 | - 无单独属性,内部包含多个 @ApiResponse 注解 |
@ApiResponse | @ApiResponses 内部 | 描述接口的单个响应状态(如 HTTP 状态码对应的结果) | - responseCode :HTTP 响应状态码(如 “200” 成功、“404” 未找到)- description :响应描述- content :响应内容类型(结合 @Content 使用,指定返回数据结构) |
@Content | @ApiResponse 内部 | 描述响应的内容类型和数据结构 | - mediaType :响应媒体类型(如 “application/json”)- schema :响应数据结构(结合 @Schema 指定实体类) |
@Schema | 实体类 / 实体属性 | 描述实体类或其属性的元信息(用于定义请求 / 响应的数据结构) | - description :类或属性的描述- required :属性是否必填(默认 false)- example :属性示例值- format :属性格式(如 “email”、“date”)- minimum /maximum :数值类型的最小 / 最大值(如年龄的 0-120) |
@RequestBody | 方法参数 | 描述请求体参数(通常用于 POST/PUT 请求的 JSON 参数) | - description :请求体描述- required :是否必填(默认 true)- content :请求体内容(结合 @Content 和 @Schema 指定实体类) |
@OpenAPIDefinition | 配置类 / 应用 | 全局定义 API 文档的元信息(如标题、版本等,可替代配置类中的 OpenAPI Bean) | - info :API 基本信息(结合 @Info 使用,包含标题、版本等)- servers :API 服务器地址(如开发 / 生产环境地址) |
@Info | @OpenAPIDefinition 内部 | 定义 API 的基本信息(标题、版本、联系人等) | - title :API 标题- version :API 版本- description :API 描述- contact :联系人信息(结合 @Contact)- license :许可证信息(结合 @License) |
@Contact | @Info 内部 | 定义 API 的联系人信息 | - name :联系人姓名- email :联系人邮箱- url :联系人网址 |
@License | @Info 内部 | 定义 API 的许可证信息 | - name :许可证名称(如 “Apache 2.0”)- url :许可证地址 |
@SecurityScheme | 配置类 | 定义安全方案(如 Token 认证) | - name :安全方案名称- type :安全类型(如 “HTTP”)- scheme :认证方案(如 “bearer”)- bearerFormat :令牌格式(如 “JWT”)- in :令牌位置(如 “header”) |
5. 完整示例
下面是一个包含控制器、实体类的完整示例:
@Schema(description = "用户实体类")
public class User {@Schema(description = "用户ID", example = "1")private Long id;@Schema(description = "用户名", example = "张三", required = true)private String name;@Schema(description = "用户年龄", example = "25", minimum = "0", maximum = "120")private Integer age;@Schema(description = "用户邮箱", example = "zhangsan@example.com", format = "email")private String email;// 构造方法public User() {}public User(String name, Integer age, String email) {this.name = name;this.age = age;this.email = email;}// getter 和 setter 方法
}
用户控制器示例:
@Tag(name = "用户管理", description = "用户的增删改查操作")
@RestController
@RequestMapping("/users")
public class UserController {// 模拟数据库存储private static final ConcurrentMap<Long, User> userMap = new ConcurrentHashMap<>();private static final AtomicLong idGenerator = new AtomicLong(1);// 初始化一些测试数据static {userMap.put(idGenerator.getAndIncrement(), new User("张三", 25, "zhangsan@example.com"));userMap.put(idGenerator.getAndIncrement(), new User("李四", 30, "lisi@example.com"));}@Operation(summary = "获取用户列表", description = "查询所有用户信息")@GetMappingpublic List<User> getUsers() {return new ArrayList<>(userMap.values());}@Operation(summary = "获取用户详情", description = "根据ID查询用户信息")@ApiResponses({@ApiResponse(responseCode = "200", description = "查询成功", content = @Content(schema = @Schema(implementation = User.class))),@ApiResponse(responseCode = "404", description = "用户不存在")})@GetMapping("/{id}")public ResponseEntity<User> getUserById(@Parameter(description = "用户ID", required = true, example = "1")@PathVariable Long id) {User user = userMap.get(id);if (user == null) {return ResponseEntity.notFound().build();}return ResponseEntity.ok(user);}@Operation(summary = "创建用户", description = "新增用户信息")@PostMappingpublic User createUser(@Parameter(description = "用户信息", required = true)@RequestBody User user) {Long id = idGenerator.getAndIncrement();user.setId(id);userMap.put(id, user);return user;}@Operation(summary = "更新用户", description = "根据ID更新用户信息")@PutMapping("/{id}")public ResponseEntity<User> updateUser(@Parameter(description = "用户ID", required = true, example = "1")@PathVariable Long id,@Parameter(description = "更新后的用户信息", required = true)@RequestBody User user) {if (!userMap.containsKey(id)) {return ResponseEntity.notFound().build();}user.setId(id);userMap.put(id, user);return ResponseEntity.ok(user);}@Operation(summary = "删除用户", description = "根据ID删除用户")@ApiResponses({@ApiResponse(responseCode = "200", description = "删除成功"),@ApiResponse(responseCode = "404", description = "用户不存在")})@DeleteMapping("/{id}")public ResponseEntity<Void> deleteUser(@Parameter(description = "用户ID", required = true, example = "1")@PathVariable Long id) {if (!userMap.containsKey(id)) {return ResponseEntity.notFound().build();}userMap.remove(id);return ResponseEntity.ok().build();}
}
6. 高级配置
6.1 配置 API 分组
当项目较大时,可以将 API 进行分组管理:
@Configuration
public class SwaggerGroupConfig {// 用户管理 API 分组@Beanpublic OpenAPI userAPI() {return new OpenAPI().info(new Info().title("用户管理 API").description("用户相关的所有接口").version("1.0.0"));}// 订单管理 API 分组@Beanpublic OpenAPI orderAPI() {return new OpenAPI().info(new Info().title("订单管理 API").description("订单相关的所有接口").version("1.0.0"));}
}
然后在控制器上指定所属分组:
@Tag(name = "用户管理", description = "用户的增删改查操作")
@RestController
@RequestMapping("/users")
@OpenAPIDefinition(openapi = @OpenAPIDefinitionRef(ref = "#/components/schemas/userAPI"))
public class UserController {// ...
}
6.2 全局参数配置
可以配置全局参数,如令牌(Token):
@Configuration
public class SwaggerGlobalParamConfig {@Beanpublic OpenAPI customOpenAPI() {// 定义安全方案SecurityScheme securityScheme = new SecurityScheme().type(SecurityScheme.Type.HTTP).scheme("bearer").bearerFormat("JWT").in(SecurityScheme.In.HEADER).name("Authorization");// 添加安全要求SecurityRequirement securityRequirement = new SecurityRequirement().addList("bearerAuth");return new OpenAPI().info(new Info().title("带全局Token的API文档").version("1.0.0")).components(new Components().addSecuritySchemes("bearerAuth", securityScheme)).addSecurityItem(securityRequirement);}
}
7. 生产环境关闭 Swagger
在生产环境中,我们通常需要关闭 Swagger 文档以提高安全性:
7.1 通过配置文件控制
# application.yml
spring:profiles:active: dev---
# application-dev.yml
knife4j:enable: true---
# application-prod.yml
knife4j:enable: false
7.2 通过注解控制
@Configuration
@Profile({"dev", "test"}) // 只在开发和测试环境生效
public class SwaggerConfig {// ...
}
8. 常见问题及解决方法
-
访问 doc.html 出现 404 错误
- 检查依赖是否正确引入
- 检查是否有拦截器拦截了请求,需要放行
/doc.html
和/webjars/**
等路径
-
注解不生效
- 检查注解是否导入正确(Swagger 3.0 的注解在
io.swagger.v3.oas.annotations
包下) - 确保配置类被 Spring 扫描到
- 检查注解是否导入正确(Swagger 3.0 的注解在
-
实体类属性不显示
- 确保实体类有 getter 和 setter 方法
- 检查是否使用了正确的
@Schema
注解
9. 学习资源推荐
-
官方文档
- OpenAPI 3.0 规范
- Knife4j 官方文档
-
相关教程
- Spring Boot 集成 Swagger 的官方指南
- Knife4j 的 GitHub 仓库示例
-
工具
- Swagger Editor - 在线编辑 OpenAPI 文档
通过以上内容,你应该已经掌握了 Swagger 3.0 和 Knife4j 的基本使用方法。建议结合实际项目进行练习,逐步熟悉各种注解和配置选项,以提高 API 文档的质量和开发效率。