简介
说明
本文用示例介绍knife4j的用法。(SpringBoot整合knife4j)。
Knife4j是一个很好用的接口文档工具,Knife4j是Swagger的升级版。
之前用过Swagger,页面不太好,浏览技术网站时,偶然发现swagger-bootstrap-ui,它能将接口进行归类。早期,swagger-boostrap-ui是1.x版本,如今swagger-bootsrap-ui到2.x,同时也更改名字Knife4j,适用于单体和微服务项目。
Knife4j跟Swagger用法基本一样,swagger用法见:Swagger–使用/教程/实例 – 自学精灵
官网
首页:knife4j
文档:knife4j
gitee地址:https://gitee.com/xiaoym/knife4j
官网文档:1.6 快速开始 | knife4j
效果展示
knife4j跟Tomcat共用一个端口,默认Tomcat是8080。访问地址:
http://localhost:8080/doc.html

分组Url
“分组Url”是文档地址,其他软件(比如apifox)可以将它作为导入文档的url。
此网址可以直接访问:http://localhost:8080/v3/api-docs?group=all

文档
本处展示添加商品接口的文档,可以看到,非常清晰,全部是自动生成。
请求参数

响应参数

调试普通接口
本处展示添加用户的调试接口的方法,可以看到,非常清晰。

测试结果

调试上传文件接口

代码
下载源码
代码结构

依赖与配置
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
Knife4j配置(非必要)
配置方案:使用openApi3.0
默认引入包就可以直接用了(无需配置)。本处只是示例如果自定义一些东西该怎么写。
package com.example.demo.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
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.oas.annotations.EnableOpenApi;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableOpenApi
// @EnableKnife4j
// @EnableSwagger2
public class Knife4jConfig {
@Bean
public Docket docket() {
Docket docket = new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("我的标题")
.description("我的描述")
// .termsOfServiceUrl("http://www.xx.com/")
.contact(new Contact("xxx", "https://xxx.com/", "xx@qq.com"))
.version("1.0")
.build())
// 分组名称
.groupName("all")
.select()
// 这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.example.demo"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
其他配置方案:使用swagger2
package com.example.demo.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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Configuration
@EnableSwagger2
public class Knife4jConfig {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("我的标题")
.description("我的描述")
// .termsOfServiceUrl("http://xxx.com/")
.contact(new Contact("xxx", "https://xxx.com", "xx@qq.com"))
.version("1.0")
.build())
//分组名称
.groupName("all")
.select()
//指定Controller扫描路径。可以不具体到controller,它会扫描指定路径下的所有
.apis(RequestHandlerSelectors.basePackage("com.example.demo"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
Controller
package com.example.demo.business.controller;
import com.example.demo.business.bo.ProductAddBO;
import com.example.demo.business.bo.ProductEditBO;
import com.example.demo.business.bo.ProductQueryBO;
import com.example.demo.business.vo.ProductVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Api(tags = "商品")
@RestController
@RequestMapping("product")
public class ProductController {
@ApiOperation("添加")
@PostMapping("add")
public ProductVO add(@RequestBody @Valid ProductAddBO productAddBO) {
// 将数据写到数据库
ProductVO productVO = new ProductVO();
BeanUtils.copyProperties(productAddBO, productVO);
productVO.setId(1L);
productVO.setCreateTime(LocalDateTime.now());
productVO.setUpdateTime(LocalDateTime.now());
return productVO;
}
@ApiOperation("修改")
@PostMapping("edit")
public ProductVO edit(@RequestBody @Valid ProductEditBO productEditBO) {
// 修改数据库的数据
ProductVO productVO = new ProductVO();
BeanUtils.copyProperties(productEditBO, productVO);
productVO.setUpdateTime(LocalDateTime.now());
return productVO;
}
@ApiOperation("查找")
@GetMapping("find")
public List<ProductVO> find(ProductQueryBO productQueryBO) {
return new ArrayList<>();
}
@ApiOperation("删除")
@PostMapping("delete")
public void delete(Long id) {
// 将数据库数据删除
}
@ApiOperation("上传文件")
@PostMapping("upload")
public void upload(@RequestPart MultipartFile file) {
}
}
Entity
说明
本处我将增删改查都单独写一个实体类。
当然,也可以将增删改的参数都写到一个实体里边,通过@NotNull等注解的groups属性来指定属于哪个分组。这样写在运行时不会有问题,但在Knife4j页面显示时是否必填等会显示不正常,原因是:Swagger没有很好地处理好这种情况。
添加
package com.example.demo.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
@ApiModel("商品添加请求")
public class ProductAddBO {
@ApiModelProperty(value = "名字", required = true)
@NotBlank(message = "名字不能为空")
private String name;
@ApiModelProperty("库存数量")
private Integer stockQuantity;
}
修改
package com.example.demo.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@ApiModel("商品修改请求")
public class ProductEditBO {
@ApiModelProperty(value = "ID", required = true)
@NotNull(message = "ID不能为空")
private Long id;
@ApiModelProperty(value = "名字", required = true)
@NotBlank(message = "名字不能为空")
private String name;
@ApiModelProperty("库存数量")
private Integer stockQuantity;
}
查询
package com.example.demo.business.bo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@Data
@ApiModel(value = "商品查询请求", description = "商品查询description")
public class ProductQueryBO {
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("名字")
private String name;
@ApiModelProperty("库存数量")
private Integer stockQuantity;
@ApiModelProperty("创建时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@ApiModelProperty("修改时间")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
}
VO
package com.example.demo.business.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@ApiModel(value = "商品响应", description = "商品响应description")
public class ProductVO {
@ApiModelProperty("商品id")
private Long id;
@ApiModelProperty("商品名")
private String userName;
@ApiModelProperty("昵称")
private String nickName;
@ApiModelProperty("邮箱")
private String email;
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
@ApiModelProperty(value = "修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
@ApiModelProperty("删除标记。0:未删除 其他:已删除")
private Long deletedFlag;
}
Knife4j新版本
简介
knife4j已经出了新版本,版本的区别如下:
| 版本 | 说明 | 建议的SpringBoot版本 |
| 1.9.6 | 蓝色皮肤风格,开始更名,增加更多后端模块 | |
| 2.0~2.0.5 | Ui重写,底层依赖的springfox框架版本是2.9.2 | |
| 2.0.6~ | 底层springfox框架版本升级至2.10.5,OpenAPI规范是v2 | |
| 3.0~ | 底层springfox框架版本升级至3.0.3,OpenAPI规范是v3 | SpringBoot2.4.0之前 |
| 4.0~ | 将OpenAPI2与OpenAPI3分开;支持SpringBoot3 | Spring Boot 2.4.0及之后 |
knife4j4.0后,依赖名发生了变化(官网地址:这里)
| 依赖(artifactId) | OpenAPI版本 | 底层 | SpringBoot版本 | 是否有knife4j增强功能 |
| knife4j-openapi2-spring-boot-starter | 2 | springfox-swagger 2.10.5 | 2.4.0~3.0.0(不包含) | |
| knife4j-openapi3-spring-boot-starter | 3 | springdoc-openapi | 2.4.0~3.0.0(不包含) | |
| knife4j-gateway-spring-boot-starter | ||||
| knife4j-openapi3-jakarta-spring-boot-starter | 3 | springdoc-openapi | >= 3.0.0-M1 |
实例
SpringBoot2.4.0-SpringBoot3.0.0的用法
依赖
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
yml配置(必须)
knife4j: enable: true
配置类(非必须)
package com.knife.example.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
@EnableKnife4j
public class Knife4jConfig {
@Bean
public Docket docket() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("我的标题")
.description("我的描述")
// .termsOfServiceUrl("http://www.xx.com/")
.contact(new Contact("xxx", "https://xxx.com/", "xx@qq.com"))
.version("1.0")
.build())
// 分组名称
.groupName("all")
.select()
// 这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.knife"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
问题解决
全局响应的处理
见:Knife4j-解决整合@ControllerAdvice时访问失败的问题 – 自学精灵
清缓存
上传文件
见:Knife4j–解决不显示文件上传的问题 – 自学精灵
下载文件

请先 !