告别丑陋与低效!Spring Boot 整合 Knife4j,让你的 API 文档颜值与实力并存!
拒绝手工维护文档,让接口文档在代码写完的瞬间自动"新鲜出炉"
在后端开发的世界里,有一句"谎言"流传甚广:"我下次一定补接口文档。"
在前后端分离开发的今天,接口文档就像是一座桥梁。然而,传统的 Swagger UI 虽然解决了自动生成的问题,但它的界面实在是一言难尽,面对成百上千个接口,不仅查找困难,返回的 JSON 数据也无法折叠,调试起来极其痛苦。
如果说原生 Swagger 是一把"水果刀",那么我们今天要介绍的 Knife4j 就是一把功能强悍的"瑞士军刀"。
一、为什么我们要放弃"手工织布"?
你是否经历过以下场景:
- Postman 请求满天飞:前端给你发一个 Postman 链接,后端给一个 JSON 串,两个人对着半天发现参数对不上。
- Word 文档版本错乱:接口文档从
V1.0改到V5.3_final_final(真的不改了).doc。 - 联调全靠吼:"你 Swagger 地址给我一下?""哦,那个地址我看不清,你本地启动了吗?"
这一切的根源,在于文档与代码的不同步。
Knife4j(曾用名 swagger-bootstrap-ui)正是为了解决这些痛点而生。它不仅是一个 UI 增强工具,更是一套完整的 Java API 文档解决方案。
二、Knife4j:Swagger 的"究极进化体"
与丑小鸭般的原生 Swagger UI 相比,Knife4j 带来了哪些颠覆性的体验?
- 颜值即正义:界面采用左右布局,清爽简洁,支持深色模式(部分版本),不再像原生界面那样简陋得像是 90 年代的调试工具。
- 丝滑的调试体验:支持 Json 参数格式化、返回数据折叠。当接口返回几百行数据时,你可以像在 Chrome 开发者工具里一样,轻松折叠对象节点。
- 强大的搜索功能:接口多了找不到?Knife4j 提供了接口搜索功能,输入方法名或路径,一键直达。
- 文档即产品:支持在线调试,支持 Markdown、HTML、Word 格式的离线文档导出,方便交付给客户进行验收。
- 全局参数托管:配合 JWT 等 Token 鉴权,只需设置一次全局 Header(如
Authorization),即可调试所有需要登录的接口,无需每个接口都手动输入 Token。
三、实战:Spring Boot 极速整合 Knife4j
都说它好,到底有多好?只需要 3 分钟,你就能在自己的 Spring Boot 项目中体验到它的魅力。
第一步:引入 Maven 依赖
Knife4j 提供了官方 Starter,无需再单独引入 Swagger 依赖,它会帮你自动搞定一切。
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.1.0</version> <!-- 建议使用最新版本 -->
</dependency>
第二步:配置 Swagger(Java Config)
创建一个配置类,像以前一样定义接口分组和基本信息。
package com.cbitedu.springboot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
//.title("swagger-bootstrap-ui-demo RESTful APIs")
.description("# swagger-bootstrap-ui-demo RESTful APIs")
.termsOfServiceUrl("http://www.xx.com/")
.contact("xx@qq.com")
.version("1.0")
.build())
//分组名称
.groupName("2.X版本")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.cbitedu.springboot.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
第三步:享受成果
什么都不用改!你之前的 @Api、@ApiOperation、@ApiModel 注解全部有效。
例如:用户controller
package com.cbitedu.springboot.controller;
import com.cbitedu.springboot.entity.UserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("/users")
@Api(tags = "用户管理API接口")
public class UserController {
@GetMapping("/list")
@ApiOperation(value = "查询用户列表", notes = "目前仅仅是作为测试,所以返回用户全列表")
public List<UserVO> list() {
// 查询列表
List<UserVO> result = new ArrayList<>();
result.add(new UserVO().setId(1).setUsername("zhangsan"));
result.add(new UserVO().setId(2).setUsername("lisi"));
result.add(new UserVO().setId(3).setUsername("wangwu"));
// 返回列表
return result;
}
@GetMapping("/get")
@ApiOperation("获得指定用户编号的用户")
@ApiImplicitParam(name = "id", value = "用户编号", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
public UserVO get(@RequestParam("id") Integer id) {
// 查询并返回用户
return new UserVO().setId(id).setUsername(UUID.randomUUID().toString());
}
@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
@PostMapping("/add")
public void add() {
System.out.println("创建用户");
}
@ApiOperation(value = "更新用户详细信息", notes = "根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "Long"),
@ApiImplicitParam(name = "user", value = "用户详细实体user", required = true, dataType = "User")
})
@RequestMapping(value = "/update/{id}", method = RequestMethod.PUT)
public void update(@PathVariable Integer id) {
System.out.println("更新用户详细信息");
}
@PostMapping("/delete")
@ApiOperation(value = "删除指定用户编号的用户")
@ApiImplicitParam(name = "id", value = "用户编号", paramType = "query", dataTypeClass = Integer.class, required = true, example = "1024")
public Boolean delete(@RequestParam("id") Integer id) {
// 删除用户记录
Boolean success = false;
// 返回是否更新成功
return success;
}
}
实体类
package com.cbitedu.springboot.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("用户 VO")
public class UserVO {
@ApiModelProperty(value = "用户编号", required = true, example = "1024")
private Integer id;
@ApiModelProperty(value = "账号", required = true, example = "yudaoyuanma")
private String username;
public Integer getId() {
return id;
}
public UserVO setId(Integer id) {
this.id = id;
return this;
}
public String getUsername() {
return username;
}
public UserVO setUsername(String username) {
this.username = username;
return this;
}
}
启动你的 Spring Boot 应用,打开浏览器,输入:
http://localhost:8080/doc.html
注意:是
doc.html,不再是以前的swagger-ui.html了!
映入眼帘的将是一个功能强大、界面友好的文档中心。你可以在这里直接点击接口进行在线测试,Knife4j 甚至会为你生成请求示例。
四、那些让你爱不释手的"骚操作"
1. 解决 401 未授权问题(全局参数设置)
现在的项目几乎都有 Token 验证。在 Knife4j 页面右上角,点击 "全局参数" 或者 "授权" 按钮,添加 Key 为 Authorization,Value 为 Bearer your-token 的参数。从此,调试所有接口都不需要再手动填 Token 了。
2. 文档导出
在页面右上角找到"离线文档"按钮,可以选择 Markdown 格式。导出后直接发给前端,前端可以直接用 Typora 打开,格式清晰,随时可查,不用再写 Word 了。
五、写在最后
在敏捷开发的时代,效率就是生命。
Knife4j 不仅仅是一个"皮肤",它改变了后端开发维护文档的习惯。它让写文档这件事变得无感:你写 Swagger 注解的过程,就是写文档的过程。
如果你还在忍受原生 Swagger 的卡顿和简陋,如果你还在为前后端联调时的沟通成本发愁,不妨花 5 分钟时间,把 Knife4j 引入你的 Spring Boot 项目。
让接口文档重新变得优雅,让你的代码不止于实现功能,更是一份完美的说明书。