简介
说明
本文用示例介绍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–解决不显示文件上传的问题 – 自学精灵
下载文件
请先
!