Knife4j 实战
Knife4j 核心认知
什么是 Knife4j
Knife4j 是面向 Java Web 项目的接口文档增强解决方案。它能够读取应用生成的 OpenAPI 文档,并提供更易用的接口展示、在线调试、搜索、排序、离线导出和访问控制等功能。
在 Spring Boot 3 项目中,可以将相关组件理解为以下关系:
- OpenAPI 3:描述 RESTful API 的规范。
- springdoc-openapi:扫描 Spring Web 接口并生成 OpenAPI 3 文档。
- Swagger UI:展示和调试 OpenAPI 文档的通用 Web 界面。
- Knife4j:在 OpenAPI 文档基础上提供增强界面和扩展能力。
因此,Knife4j 不是一种新的接口规范,也不等同于 OpenAPI 3。对于 Spring Boot 3 项目,Knife4j 的底层文档生成能力主要由 springdoc-openapi 提供。
Spring Boot 2 与 Spring Boot 3 的主要差异
| 对比项 | Spring Boot 2 常见方案 | Spring Boot 3 推荐方案 |
|---|---|---|
| Java 版本 | 通常可以使用 JDK 8 或更高版本,具体取决于 Spring Boot 版本 | 最低需要 JDK 17 |
| Java EE 包名 | 主要使用 javax.* | 迁移到 jakarta.* |
| 接口文档规范 | 可以使用 OpenAPI 2 或 OpenAPI 3 | 推荐使用 OpenAPI 3 |
| 常见实现 | Springfox 或 springdoc-openapi | springdoc-openapi |
| Knife4j Starter | 根据规范和框架版本选择对应 Starter | 使用 Jakarta 版本的 OpenAPI 3 Starter |
| 常用注解 | 旧项目可能使用 io.swagger.annotations.* | 使用 io.swagger.v3.oas.annotations.* |
注意:并不是 Spring Boot 3 本身“废弃了 Swagger 2 注解”,而是 Spring Boot 3 项目通常不再使用基于 Springfox 的旧方案。迁移到 springdoc-openapi 后,应将旧注解替换为 OpenAPI 3 注解。
Knife4j 相比 Swagger UI 的常见增强
| 对比项 | Swagger UI | Knife4j |
|---|---|---|
| 页面展示 | 提供标准 OpenAPI 文档界面 | 提供更适合中文项目的增强界面 |
| 接口调试 | 支持在线发送请求 | 增强参数填写、请求调试和结果展示 |
| 接口检索 | 支持基础过滤 | 提供接口搜索等增强功能 |
| 文档导出 | 默认不提供完整的离线导出流程 | 支持导出 Markdown、HTML、Word 和 OpenAPI 文档 |
| 扩展配置 | 使用 Swagger UI 配置项 | 额外提供 Knife4j 增强配置 |
| 访问保护 | 通常需要自行结合安全框架处理 | 提供生产保护和 Basic 认证等辅助配置 |
适用场景
- 前后端分离项目中自动生成并维护接口文档。
- 开发和测试阶段在线调用接口。
- 展示请求参数、响应结构、状态码和字段说明。
- 多模块或微服务项目中统一管理接口文档。
- 将接口文档导出后用于交付或归档。
Spring Boot 3 集成 Knife4j
环境要求
本文示例采用以下环境:
- JDK 17 或更高版本。
- Spring Boot 3.x。
- Maven 项目。
spring-boot-starter-web。- Knife4j 4.5.0。
实际项目中应根据 Spring Boot 的具体版本检查依赖兼容性,不要仅凭“版本更高”判断组件一定兼容。
引入 Maven 依赖
Spring Boot 3 使用 Jakarta 版本的 Knife4j Starter:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
该 Starter 已经集成 OpenAPI 3 所需的 springdoc-openapi 相关依赖。通常不需要再单独引入 Springfox、Swagger 2 或其他版本的 springdoc-openapi,否则可能产生依赖冲突。
配置 application.yml
下面给出一个适合单模块项目的基础配置:
server:
port: 8080
spring:
application:
name: knife4j-spring-boot3-demo
springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: default
paths-to-match: /**
packages-to-scan: com.example.knife4jdemo.controller
knife4j:
enable: true
setting:
language: zh_cn配置说明:
springdoc.api-docs.path用于配置 OpenAPI JSON 文档地址。springdoc.group-configs用于配置文档分组、接口路径和控制器扫描包。packages-to-scan必须替换为当前项目实际的控制器包名。knife4j.enable用于开启 Knife4j 增强功能。knife4j.setting.language用于设置界面语言。
配置接口文档基本信息
通过声明 OpenAPI Bean 可以统一设置文档标题、版本、说明和联系信息:
package com.example.knife4jdemo.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 Knife4jOpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("用户管理系统接口文档")
.version("1.0.0")
.description("基于 Spring Boot 3、OpenAPI 3 和 Knife4j 构建的接口文档")
.contact(new Contact()
.name("项目开发组")
.email("demo@example.com"))
.license(new License()
.name("Apache 2.0")));
}
}启动项目并访问文档
启动 Spring Boot 项目后,在浏览器中访问:
http://localhost:8080/doc.html
OpenAPI JSON 文档的默认访问地址为 /v3/api-docs。如果配置了分组,还可能生成对应的分组文档地址。
doc.html 无法访问时的排查顺序
正常情况下,引入 Starter 后不需要手动配置静态资源映射。如果出现 404、401 或 403,应按照以下顺序排查:
-
检查 Maven 依赖是否使用了 Spring Boot 3 对应的 Jakarta Starter。
-
检查项目是否错误引入了多个 springdoc-openapi 或 Springfox 版本。
-
检查
packages-to-scan是否为真实的控制器包路径。 -
检查项目是否使用了
@EnableWebMvc,或者是否完全接管了 Spring MVC 配置。 -
检查 Spring Security 是否拦截了文档页面和 OpenAPI 文档接口。
-
检查应用是否配置了
context-path,访问地址是否需要增加上下文路径。
只有在项目确实自定义了静态资源规则,并确认自动配置没有生效时,才考虑补充资源映射:
package com.example.knife4jdemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebResourceConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}这段配置属于故障排查方案,不是所有 Spring Boot 3 项目的固定必配项。
OpenAPI 3 常用注解
旧注解与新注解对照
| 功能 | 旧版 Swagger 2 注解 | OpenAPI 3 注解 |
|---|---|---|
| 控制器分组 | @Api | @Tag |
| 接口说明 | @ApiOperation | @Operation |
| 参数说明 | @ApiParam、@ApiImplicitParam | @Parameter |
| 多个参数说明 | @ApiImplicitParams | @Parameters |
| 模型说明 | @ApiModel | @Schema |
| 字段说明 | @ApiModelProperty | @Schema |
| 隐藏接口或类 | @ApiIgnore | @Hidden 或 @Operation(hidden = true) |
使用 @Schema 描述实体类
package com.example.knife4jdemo.domain;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "用户信息")
public class User {
@Schema(
description = "用户主键",
requiredMode = Schema.RequiredMode.REQUIRED,
example = "10001"
)
private Long id;
@Schema(
description = "用户名",
requiredMode = Schema.RequiredMode.REQUIRED,
example = "zhangsan"
)
private String username;
@Schema(
description = "手机号码",
requiredMode = Schema.RequiredMode.REQUIRED,
example = "13800138000"
)
private String phone;
@Schema(description = "年龄", example = "26")
private Integer age;
@Schema(description = "用户状态:0 表示禁用,1 表示正常", example = "1")
private Integer status;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
}使用 Lombok 的项目可以通过 @Data 简化 Getter 和 Setter,但需要确保项目已经正确引入 Lombok 并启用注解处理。
使用 @Tag 和 @Operation 描述控制器
package com.example.knife4jdemo.controller;
import com.example.knife4jdemo.domain.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/users")
@Tag(name = "用户管理", description = "提供用户查询接口")
public class UserController {
@GetMapping("/{id}")
@Operation(
summary = "根据编号查询用户",
description = "根据用户主键查询用户详细信息"
)
public User getUserById(
@Parameter(
description = "用户主键",
required = true,
example = "10001"
)
@PathVariable("id") Long id
) {
User user = new User();
user.setId(id);
user.setUsername("zhangsan");
user.setPhone("13800138000");
user.setAge(26);
user.setStatus(1);
return user;
}
@GetMapping
@Operation(
summary = "查询用户列表",
description = "查询当前系统中的用户数据"
)
public List<User> listUsers() {
return List.of(getUserById(10001L));
}
}重启项目后访问:
http://localhost:8080/doc.html
页面中应展示用户管理分组、接口摘要、参数说明和响应模型。
Knife4j 进阶功能
配置全局 JWT 认证
对于使用 JWT 的项目,可以在 OpenAPI 文档中声明 HTTP Bearer 认证方案。下面的配置是前面 OpenAPI Bean 的升级版本,实际项目中只保留一个 OpenAPI Bean:
package com.example.knife4jdemo.config;
import io.swagger.v3.oas.models.Components;
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 io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class Knife4jOpenApiConfig {
private static final String SECURITY_SCHEME_NAME = "BearerAuth";
@Bean
public OpenAPI customOpenAPI() {
SecurityScheme securityScheme = new SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
.description("输入登录后获得的 JWT");
return new OpenAPI()
.info(new Info()
.title("用户管理系统接口文档")
.version("1.0.0")
.description("支持 JWT 调试的接口文档")
.contact(new Contact()
.name("项目开发组")
.email("demo@example.com"))
.license(new License()
.name("Apache 2.0")))
.components(new Components()
.addSecuritySchemes(SECURITY_SCHEME_NAME, securityScheme))
.addSecurityItem(new SecurityRequirement()
.addList(SECURITY_SCHEME_NAME));
}
}配置完成后,文档页面会显示认证入口。开发人员输入 JWT 后,调试请求会按照 Bearer 认证方式携带 Authorization 请求头。
注意:将安全方案添加到 OpenAPI 对象表示文档默认要求认证,但它不会替代 Spring Security 的服务端鉴权逻辑。
导出离线文档
Knife4j 的文档管理功能可以导出以下内容:
- Markdown 文档。
- 离线 HTML 文档。
- Word 文档。
- 原始 OpenAPI JSON 文档。
Knife4j 官方导出功能不直接生成 PDF。需要 PDF 时,可以先导出 Markdown 或 HTML,再使用其他工具转换为 PDF。
隐藏不需要展示的接口
使用 @Hidden 可以隐藏控制器或接口:
package com.example.knife4jdemo.controller;
import io.swagger.v3.oas.annotations.Hidden;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Hidden
@RestController
@RequestMapping("/admin")
public class AdminController {
@PostMapping("/password")
public String updatePassword() {
return "密码修改成功";
}
}也可以只隐藏单个方法:
@Hidden
@PostMapping("/internal/reset")
public String resetData() {
return "重置成功";
}
重要说明:@Hidden 只控制接口是否出现在 OpenAPI 文档中,不会阻止客户端访问该接口。敏感接口仍然必须通过 Spring Security、权限校验和网关策略进行保护。
生产环境安全配置
开发环境配置
开发环境可以开启接口文档:
knife4j:
enable: true
production: false
生产环境关闭文档
生产环境可以同时关闭 Knife4j 页面、Swagger UI 和 OpenAPI JSON 接口:
springdoc:
api-docs:
enabled: false
swagger-ui:
enabled: false
knife4j:
enable: false
production: true其中:
knife4j.production用于开启 Knife4j 的生产环境保护策略。springdoc.api-docs.enabled用于关闭 OpenAPI JSON 接口。springdoc.swagger-ui.enabled用于关闭 Swagger UI。
生产环境是否完全禁用接口文档,应根据项目的网络隔离、权限模型和运维要求决定。
使用 Basic 认证保护文档
在内部测试环境确实需要开放文档时,可以启用 Basic 认证:
knife4j:
enable: true
production: false
basic:
enable: true
username: doc_user
password: ${KNIFE4J_PASSWORD}
不要在代码仓库中直接保存真实密码。示例使用环境变量 KNIFE4J_PASSWORD 注入密码。
Basic 认证只能作为文档访问保护的一部分。生产系统还应结合 HTTPS、网络访问控制、Spring Security 和统一身份认证等措施。
常见问题
页面能够打开,但没有接口
重点检查:
packages-to-scan是否配置正确。- 控制器是否使用了
@RestController。 - 请求方法是否使用了
@GetMapping、@PostMapping等映射注解。 - 控制器是否位于 Spring Boot 默认扫描范围内。
- 是否错误配置了
paths-to-match。
文档页面返回 401 或 403
这通常表示请求被安全过滤器拦截。需要在开发环境中按需放行以下资源:
/doc.html/webjars/**/v3/api-docs/**/swagger-ui/**/swagger-ui.html
是否放行以及如何放行,应以项目实际使用的 Spring Security 版本和权限策略为准。
文档页面返回 404
重点检查:
- Starter 是否选择正确。
- 依赖是否下载成功。
- 是否存在依赖冲突。
- 是否配置了应用上下文路径。
- 是否使用
@EnableWebMvc覆盖了自动配置。 - 是否自定义了静态资源映射。
注解没有显示在文档中
检查注解导包是否来自 io.swagger.v3.oas.annotations。不要混用旧版 io.swagger.annotations 和 OpenAPI 3 注解。
修改接口后文档没有变化
可以依次尝试:
-
确认代码已经重新编译并重启应用。
-
刷新浏览器页面。
-
清除 Knife4j 页面缓存。
-
检查当前查看的是否为正确分组。
-
直接访问
/v3/api-docs,确认后端生成的 OpenAPI JSON 是否已经更新。
总结
Spring Boot 3 集成 Knife4j 的核心流程如下:
-
使用 JDK 17 或更高版本。
-
引入 Jakarta 版本的 Knife4j OpenAPI 3 Starter。
-
通过
springdoc配置扫描包、分组和 OpenAPI 文档路径。 -
通过
OpenAPIBean 设置文档基本信息和认证方案。 -
使用
@Tag、@Operation、@Parameter和@Schema描述接口。 -
在开发环境开放文档,在生产环境按安全要求关闭或限制访问。
-
明确区分“隐藏接口文档”和“保护真实接口”,不能将
@Hidden当作权限控制手段。
喜欢的话,留下你的评论吧~