关于knife4j
Knife4j的前身是swagger-bootstrap-ui,前身swagger-bootstrap-ui是一个纯swagger-ui的ui皮肤项目
一开始项目初衷是为了写一个增强版本的swagger的前端ui,但是随着项目的发展,面对越来越多的个性化需求,不得不编写后端Java代码以满足新的需求,在swagger-bootstrap-ui的1.8.5~1.9.6版本之间,采用的是后端Java代码和Ui都混合在一个Jar包里面的方式提供给开发者使用.这种方式虽说对于集成swagger来说很方便,只需要引入jar包即可,但是在微服务架构下显得有些臃肿。
因此,项目正式更名为knife4j,取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍,更名也是希望把她做成一个为Swagger接口文档服务的通用性解决方案,不仅仅只是专注于前端Ui前端.
swagger-bootstrap-ui的所有特性都会集中在knife4j-spring-ui包中,并且后续也会满足开发者更多的个性化需求.
主要的变化是,项目的相关类包路径更换为com.github.xiaoymin.knife4j前缀,开发者使用增强注解时需要替换包路径
后端Java代码和ui包分离为多个模块的jar包,以面对在目前微服务架构下,更加方便的使用增强文档注解(使用SpringCloud微服务项目,只需要在网关层集成UI的jar包即可,因此分离前后端)
knife4j沿用swagger-bootstrap-ui的版本号,第1个版本从1.9.6开始,关于使用方法,请参考文档(摘自 knife4j 官方介绍)。
引入knife4j
knife4j 主要的版本基本如下所示
版本 | 说明 |
---|---|
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 |
我们引入的是3.0.3,由于3.x只发布了一个版本,稳定性可能存在一定的问题,如果你想最求稳定,那么推荐你使用 2.x,由于我这里只是demo展示,加上我自己喜欢新版本,所以我这里使用了3.0.3,提前帮大家猜猜坑。
com.github.xiaoymin
knife4j-spring-boot-starter
3.0.3
注意
- knife4j 已经引入了 springfox,所以在使用的时候无需再次引入
springfox,否则有可能会导致版本冲突,如果你在网关聚合时,必须禁用 knife4j 的增强功能。 - 使用Knife4j2.0.6及以上的版本,Spring Boot的版本必须大于等于2.2.x
创建 Swagger 配置依赖
package com.ymy.notes.config.kinfe4j;
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 Knife4jConfiguration {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
String groupName="3.X版本";
Docket docket=new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("这是knife4j API ")
.description("# 这里记录服务端所有的接口的入参,出参等等信息")
.termsOfServiceUrl("http://yaomaoyang.com")
.contact(new Contact("逆流星","http://yaomaoyang.com","[email protected]"))
.version("3.0")
.build())
//分组名称
.groupName(groupName)
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.ymy.notes.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
这里需要注意一点,如果你使用的是 2.x,那么需要将 @EnableSwagger2 替换成 @EnableSwagger2WebMvc, 因为 @EnableSwagger2 是在 3.x 才引入的注解,并且将@EnableSwagger2WebMvc 设置为不推荐使用。
配置项目名和端口信息
server:
port: 8818
spring:
application:
name: notes
创建一个简单的 RESTful 接口
package com.ymy.notes.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/test")
@Api(tags = "测试swagger")
public class Knife4jTestController {
@GetMapping(value = "/hello")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("测试接口")
public String test(@RequestParam("name") String name){
return "hello "+name+", I am meimei han";
}
}
启动项目
如果你在启动项目的时候抛出:Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
千万不要慌,那是因为你的 springboot 版本太高,应该是 2.6.x,由于Springfox使用的路径匹配是基于AntPathMatcher,而Spring Boot 2.6.X使用的是PathPatternMatcher,所以将MVC的路径匹配规则改成 AntPathMatcher,在配置文件中加入如下参数即可(如果没有报错,可以跳过这个环节)
spring:
mvc:
pathmatch:
# Springfox使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher
# 所以需要配置此参数
matching-strategy: ant_path_matcher
启动成功之后,在浏览器中访问:http://127.0.0.1:8818/doc.html(ip+端口+/doc.html)。
如果看到下面的画面,说明knife4j已经配置成功。
到此为止,knife4j 已经完美的运行起来了,后端人员在自测的时候再也不需要使用 postman了,也不需要给前端单独写接口文档了,一下子就增加的自己的摸鱼时间,美滋滋。
knife4j增强功能
什么是 knife4j 的增强功能?我们在前面看到的只是 knife4j 最基础的使用方式,knife4j 还有很多强大的功能还没有展示出来,比如:i18n国际化、接口添加作责、自定义文档、访问权限控制、接口排序、到处离线文档、过滤请求参数等等,这些都是 knife4j 的增强功能,那如何开启 knife4j 的增强功能呢?
Knife4j自2.0.6版本开始,将目前在Ui界面中一些个性化配置剥离,开发者可以在后端进行配置,并且提供的knife4j-spring-boot-strater组件自动装载,开发者可以在配置文件中决定需要开启的功能。
springboot 中 knife4j的完整参数如下:
knife4j:
enable: true
documents:
-
group: 2.X版本
name: 接口签名
locations: classpath:sign/*
setting:
language: zh-CN
enableSwaggerModels: true
enableDocumentManage: true
swaggerModelName: 实体类列表
enableVersion: false
enableReloadCacheParameter: false
enableAfterScript: true
enableFilterMultipartApiMethodType: POST
enableFilterMultipartApis: false
enableRequestCache: true
enableHost: false
enableHostText: 192.168.0.193:8000
enableHomeCustom: true
homeCustomLocation: classpath:markdown/home.md
enableSearch: false
enableFooter: false
enableFooterCustom: true
footerCustomContent: Apache License 2.0 | Copyright 2019-[浙江八一菜刀股份有限公司](https://gitee.com/xiaoym/knife4j)
enableDynamicParameter: false
enableDebug: true
enableOpenApi: false
enableGroup: true
cors: false
production: false
basic:
enable: false
username: test
password: 12313
knife4j 的增强功能是需要开启的,默认关闭,开启也是十分的简单,在以前的版本中,开发者需要在配置文件中手动使用@EnableKnife4j来使用增强,自2.0.6版本后,只需要在配置文件中配置knife4j.enable=true即可不在使用注解
注意:要使用Knife4j提供的增强,knife4j.enable=true必须开启。包括后面所讲解到的所有增强功能,都需要设置这个参数。
下面我来介绍以下上面的这些属性值所表达的是什么意思
属性 | 默认值 | 说明 |
---|---|---|
knife4j.enable | false | 是否开启Knife4j增强模式 |
knife4j.cors | false | 是否开启一个默认的跨域配置,该功能配合自定义Host使用 |
knife4j.production | false | 是否开启生产环境保护策略,详情参考文档 |
knife4j.basic | 对Knife4j提供的资源提供BasicHttp校验,保护文档 | |
knife4j.basic.enable | false | 关闭BasicHttp功能 |
knife4j.basic.username | basic用户名 | |
knife4j.basic.password | basic密码 | |
knife4j.documents | 自定义文档集合,该属性是数组 | |
knife4j.documents.group | 所属分组 | |
knife4j.documents.name | 类似于接口中的tag,对于自定义文档的分组 | |
knife4j.documents.locations | markdown文件路径,可以是一个文件夹(classpath:markdowns/*),也可以是单个文件(classpath:md/sign.md) | |
knife4j.setting | 前端Ui的个性化配置属性 | |
knife4j.setting.enableAfterScript | true | 调试Tab是否显示AfterScript功能,默认开启 |
knife4j.setting.language | zh-CN | Ui默认显示语言,目前主要有两种:中文(zh-CN)、英文(en-US) |
knife4j.setting.enableSwaggerModels | true | 是否显示界面中SwaggerModel功能 |
knife4j.setting.swaggerModelName | Swagger Models | 重命名SwaggerModel名称,默认 |
knife4j.setting.enableDocumentManage | true | 是否显示界面中"文档管理"功能 |
knife4j.setting.enableReloadCacheParameter | false | 是否在每个Debug调试栏后显示刷新变量按钮,默认不显示 |
knife4j.setting.enableVersion | false | 是否开启界面中对某接口的版本控制,如果开启,后端变化后Ui界面会存在小蓝点 |
knife4j.setting.enableRequestCache | true | 是否开启请求参数缓存 |
knife4j.setting.enableFilterMultipartApis | false | 针对RequestMapping的接口请求类型,在不指定参数类型的情况下,如果不过滤,默认会显示7个类型的接口地址参数,如果开启此配置,默认展示一个Post类型的接口地址 |
knife4j.setting.enableFilterMultipartApiMethodType | POST | 具体接口的过滤类型 |
knife4j.setting.enableHost | false | 是否启用Host |
knife4j.setting.enableHomeCustom | false | 是否开启自定义主页内容 |
knife4j.setting.homeCustomLocation | 主页内容Markdown文件路径 | |
knife4j.setting.enableSearch | false | 是否禁用Ui界面中的搜索框 |
knife4j.setting.enableFooter | true | 是否显示Footer |
knife4j.setting.enableFooterCustom | false | 是否开启自定义Footer |
knife4j.setting.footerCustomContent | false | 自定义Footer内容 |
knife4j.setting.enableDynamicParameter | false | 是否开启动态参数调试功能 |
knife4j.setting.enableDebug | true | 启用调试 |
knife4j.setting.enableOpenApi | true | 显示OpenAPI规范 |
knife4j.setting.enableGroup | true | 显示服务分组 |
以下增强功能都需要
接口添加作者
前端李雷在对接接口的时候发现接口有问题,但是不知道是谁在负责这个接口,通过层层查找,终于找到了是韩梅梅负责,这样大大的阻碍了开发的效率,所以这个时候在接口上标记对应的开发着,能让找人和背锅都能做到非常精准。
使用方式:添加注解 @ApiOperationSupport(author = "逆流星007")
@GetMapping(value = "/hello")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("测试接口")
@ApiOperationSupport(author = "逆流星007")
public String test(@RequestParam("name") String name){
return "hello "+name+", I am meimei han";
}
但是对于后端来说,在每个接口上都加上这个注解,着实有点浪费时间了,所以 knife4j 在收到反馈之后,决定在 Controller 类上增加一个注解,表示当前接口类下的所有接口都是该作者负责开发。
因此在 2.0.3 版本中新增加了 @ApiSupport 注解,该注解目前有两个属性,分别是author(作者)和order(排序)
注意:如果在controller 类上添加了@ApiSuppor 注解,并且在某个接口上也添加了 @ApiOperationSupport 注解,那么接口上的作者将会覆盖 controller 类上的作者
@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "逆流星007-controller")
@Api(tags = "测试swagger")
public class Knife4jTestController
@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "逆流星007-controller")
@Api(tags = "测试swagger")
public class Knife4jTestController {
@GetMapping(value = "/hello")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("测试接口")
@ApiOperationSupport(author = "逆流星逆流星007-test")
public String test(@RequestParam("name") String name){
return "hello "+name+", I am meimei han";
}
}
访问权限控制
虽然 knife4j给我们提供了很方便的在线接口文档,俗话说的好,凡事都具有两面性,有利自然也有弊,那就是在生茶环境上,也会显示出接口文档,这是非常危险的一件事情,问题如下:
- 系统部署生产环境时,我们想屏蔽Swagger的文档功能,不管是接口或者html文档
- 通常我们有时候需要生产环境部署后,又需要Swagger的文档调试功能,辅助开发者调试,但是存在安全隐患,没有对Swagger的资源接口过滤
Knife4j 基于 Servlet 体系提供了过滤 Filter 功能,如果开发者使用 Spring Boot 开发框架进行开发的话,只需在application.properties
或者application.yml
配置文件中配置相关属性即可方便的解决上面的问题,不用删除 Springfox-swagger 的 jar 包或者删除相关代码等复杂的操作,提升开发体验。
资源屏蔽
目前Springfox-Swagger
以及Knife4j
提供的资源接口包括如下
资源 | 说明 |
---|---|
/doc.html | Knife4j提供的文档访问地址 |
/v2/api-docs-ext | Knife4j提供的增强接口地址,自2.0.6 版本后删除 |
/swagger-resources | Springfox-Swagger提供的分组接口 |
/v2/api-docs | Springfox-Swagger提供的分组实例详情接口 |
/swagger-ui.html | Springfox-Swagger提供的文档访问地址 |
/swagger-resources/configuration/ui | Springfox-Swagger提供 |
/swagger-resources/configuration/security | Springfox-Swagger提供 |
项目发布到生产环境之后,我们需要屏蔽 swagger 相关的资源,由于 Knife4j 基于 Servlet 体系提供了过滤 Filter 功能,所以就不需要我们再去造轮子了,直接使用即可。
springboot 只需要在配置文件中做如下修改即可
knife4j:
# 开启增强配置
enable: true
# 开启生产环境屏蔽
production: true
然后重启项目
如果看到如下信息,说明资源已经屏蔽成功,但是你又不想在生产环境中屏蔽 swagger 资源,只想给一部分人使用,也是可以的,加入权限校验即可。
访问页面加权控制
针对Swagger的资源接口,Knife4j
提供了简单的Basic认证功能
简单点说,指定一个用户名和密码,访问 Swagger 文档需要验证登录名和密码,验证通过之后才能正常访问。
knife4 允许开发者在配置文件(application.yml/properties)中增加一组用户名和密码。
knife4j:
# 开启增强配置
enable: true
# 开启Swagger的Basic认证功能,默认是false
basic:
enable: true
# Basic认证用户名
username: test
# Basic认证密码
password: 123
如果用户开启了 basic (knife4j.basic.enable = true)认证功能,但是没有指定 username 和password,那么 knife4j 提供了一组默认的用户名密码
admin/123321
配置好application.yml 文件之后,我们再次重启项目(这个时候需要将之前设置的资源屏蔽需要去掉哦)
接口排序
我们在开发中,一个 controller 中往往会存在很多的接口,这样我们在文档查找的时候就会变得很苦恼,所以 knife4j 在 @ApiOperationSupport
注解中增加了 order 字段,用于接口排序。
在使用此注解之前需要开启增强功能。
package com.ymy.notes.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "逆流星007-controller")
@Api(tags = "测试swagger")
public class Knife4jTestController {
@GetMapping(value = "/hello1")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("测试接口01")
@ApiOperationSupport(author = "逆流星逆流星007-test",order = 1)
public String test01(@RequestParam("name") String name){
return "hello "+name+", I am meimei han";
}
@GetMapping(value = "/hello3")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("测试接口03")
@ApiOperationSupport(author = "逆流星逆流星007-test",order = 3)
public String test03(@RequestParam("name") String name){
return "hello "+name+", I am meimei han";
}
@GetMapping(value = "/hello2")
@ApiImplicitParam(name = "name",value = "姓名",required = true)
@ApiOperation("测试接口02")
@ApiOperationSupport(author = "逆流星逆流星007-test",order = 2)
public String test02(@RequestParam("name") String name){
return "hello "+name+", I am meimei han";
}
}
分组排序
分组,顾名思义,就是多个 controller 之间的排序,开发者可以通过注解实现每个controller 之间的排序,实现这个功能的注解一共有三个,具体如下:
- @ApiSupport
- @ApiSort
- @Api
这三个注解是存在优先级的,也就是说,当同时使用时,只会有一个注解生效,所以在使用的时候需要特别注意。优先级规则如下:
@ApiSupport>
@ApiSort>
@Api
controller 之间的排序规则为降序,越大的排在越靠前,但是排序的最小值一定需要大于 0 。
@ApiSupport
@RestController
@RequestMapping(value = "/test")
@ApiSupport(author = "逆流星007-controller",order = 999)
@Api(tags = "测试swagger")
public class Knife4jTestController
@ApiSort
@RestController
@RequestMapping(value = "/test")
@ApiSort(value = 999)
@Api(tags = "测试swagger")
public class Knife4jTestController
@Api
@RestController
@RequestMapping(value = "/test")
@Api(tags = "测试swagger",position = 999)
public class Knife4jTestController
虽然 @Api 中的position 字段也能实现 controller 之间的排序,但是该字段已经被 knife4j 标记为不推荐使用,所以还是推荐使用第一种排序方式(@ApiSupport)。
请求参数缓存
我们在调试接口的时候,有的接口会有很多参数,当我们好不容易填好了所有的参数,由于我们不小心关闭了页面,下次再调试的时候发现还需要再次将参数输入一遍,心态会爆炸吧,所以 knife4j 在文档管理中增加了一个选项:开启请求参数缓存。
勾选这个选项之后,你填写的参数将会被 knife4j 缓存,关闭页面也不会丢失,是不是很人性呢?
编写代码,准备数据
@PostMapping(value = "/saveUser")
@ApiOperation("保存用户信息")
@ApiOperationSupport(author = "逆流星逆流星007")
public String saveUser(@RequestBody UserDTO userDTO){
System.out.println("前端传递的用户信息:"+ userDTO);
return "save success";
}
package com.ymy.notes.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@ApiModel("用户信息")
@Getter
@Setter
@ToString
public class UserDTO {
@ApiModelProperty(value = "用户名")
private String username;
@ApiModelProperty(value = "性别")
private String gender;
@ApiModelProperty(value = "手机号码")
private String phone;
}
不过你不能高兴的太早,缓存也不是一定会生效的,我已知的这两种情况,缓存将会失效,在使用的时候需要注意哦。
- 在字段的
@ApiModelProperty
注解中添加 example (属性的示例值)属性,那么, knife4j 将不会使用缓存,使用的是后端指定的 example 。
public class UserDTO {
@ApiModelProperty(value = "用户名",example = "李雷")
private String username;
@ApiModelProperty(value = "性别",example = "男")
private String gender;
@ApiModelProperty(value = "手机号码",example = "18888888888")
private String phone;
}
- 当域名发生改变时,所有缓存将会失效。
动态请求参数
作为开发,不知道大家有没有做过这种操作,接口参数并不是实体对象接收,而是Map,虽然我没这么做过,但是我见过别人这么写过,当后端程序员使用 Map 接收参数的时候,Swagger ui 会怎么展示呢?我们一起来模拟一下。
定义一个以 Map 接收参数的接口
@PostMapping(value = "/saveUserForMap")
@ApiOperation("新增用户信息-map")
@ApiOperationSupport(author = "逆流星007")
private String saveUserForMap(Map userDTO ){
System.out.println("前端传递的用户信息:"+ userDTO);
return "save success";
}
我们来看看 Swagger ui 如何展示这个 Map类型的参数
这。。。。。要是前端看到这样的接口文档,心里开始问候后端的家人了吧,如何解决这个问题呢?其实很简单,knife4j 早已为我们想到了解决方案,招到文档管理 - 个性化设置 ,勾选开启动态请求参数就能解决这个问题了。
我们现在再来看看勾选了 开启动态请求参数之后的效果
在输入了一个参数之后,参数列表会自动追加新的一行,但是参数的 key 却需要前端人员自己填写,前端有很大可能是不知道参数的key,所以还是需要找后端开发人员,虽然开启了动态参数可以增加参数的个数,但是还没没有办法解决参数值的问题,那这个怎么解决呢?那这就是另外一个增强功能了:动态请求参数添加文档注释
过滤请求参数
我们在开发过程中,经常会遇到这样的一个问题,新增和修改接口,修改接口需要传递修改的记录id,但是新增则不需要,而后端往往会将修改和新增的入参对象设置为一个对象,那么这个对象中必然会存在 id 字段,这就会对新增造成误导,前端可能百思不得其解,新增的 id 我应该怎么传呢? 总不可能去偷一个吧。
所以,knife4j 支持了请求参数的过滤(忽略),实现方式也是非常的简单,使用自定义增强注解ApiOperationSupport
中的ignoreParameters
属性,可以强制忽略要显示的参数。
使用字段忽略之前我们得先了解一下字段忽略的规则:
- 1.例如新增接口时,某实体类不需要显示Id,即可使用该属性对参数进行忽略.
ignoreParameters={"id"}
- 2.如果存在多个层次的参数过滤,则使用名称.属性的方式,例如
ignoreParameters={"uptModel.id","uptModel.uptPo.id"}
,其中uptModel是实体对象参数名称,id为其属性,uptPo为实体类,作为uptModel类的属性名称 - 3。如果参数层级只是一级的情况下,并且参数是实体类的情况下,不需要设置参数名称,直接给定属性值名称即可
- 4.如果实体类属性中是通过List这种数组的方式,那么过滤规则会有所不同,在属性后面需要追加一个下标
[0]
,ignoreParameters={"uptModel.uptPo[0].id"}
实现此功能需要开启增强功能。
表单提交和 JSON 提交的格式是不一样的,所以这里需要分开讲解一下,我们先来看表单提交怎么忽略字段属性。
前置条件:我们先创建两个 DTO 用来接收前端传递二点参数
package com.ymy.notes.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@ApiModel("用户信息")
@Getter
@Setter
@ToString
public class UserDTO {
@ApiModelProperty(value = "用户id")
private Long id;
@ApiModelProperty(value = "用户名",example = "李雷")
private String username;
@ApiModelProperty(value = "性别",example = "男")
private String gender;
@ApiModelProperty(value = "手机号码",example = "18888888888")
private String phone;
@ApiModelProperty(value = "用户收货地址信息")
private UserAddressDTO userAddressDTO;
}
package com.ymy.notes.dto;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class UserAddressDTO {
@ApiModelProperty(value = "收获地址的记录id")
private Long id;
@ApiModelProperty(value = "省")
private String province;
@ApiModelProperty(value = "市")
private String city;
@ApiModelProperty(value = "区")
private String district;
@ApiModelProperty(value = "详细地址")
private String addr;
}
表单提交
创建新增接口和修改接口,并且希望在添加的时候过滤掉 UserDTO 中的 id 字段 与 UserAddressDTO 中的 id 字段,因为新增用户和收获地址的时候是没有 id 信息的,只有新增完成之后才会存在 id字段。
@ApiOperationSupport(author = "逆流星007",ignoreParameters = {"id","userAddressDTO.id"})
@PostMapping(value = "/saveUser")
@ApiOperation("新增用户信息-表单")
@ApiOperationSupport(author = "逆流星007",ignoreParameters = {"id","userAddressDTO.id"})
public String saveUser( UserDTO userDTO){
System.out.println("前端传递的用户信息:"+ userDTO);
return "save success";
}
@PostMapping(value = "/updateUser")
@ApiOperation("编辑用户信息")
@ApiOperationSupport(author = "逆流星007")
public String updateUser( UserDTO userDTO){
System.out.println("前端传递的用户信息:"+ userDTO);
return "edit success";
}
在过滤字段的时候,第一层我们只要填写对象中的属性名即可,但如果需要过滤第二层,根据忽略规则中的第二条,我们在 UserDTO 对象中引入 UserAddressDTO 对象:private UserAddressDTO userAddressDTO
; 我们还需要忽略 UserAddressDTO 对象中的 id 属性,那么需要填上 userAddressDTO.id ,其中 userAddressDTO 要与 UserDTO 对象中的 UserAddressDTO 属性名一致。
代码写好了,我们一起来看看效果。
添加接口
这里我们看不到 UserDTO 中的 id ,同时也看不到 UserAddressDTO 中的 id,忽略成功。
修改接口
由于我们在修改的时候并没有忽略 这两个字段,所以可以正常显示,这也是没有问题的。
JSON提交
由于表单提交和 json 提交的格式存在一定的差异,所以他们忽略参数的格式也存在一定的差异,我们将原来的修改和修改接口的参数接收方式改为 json 格式并且保持和表单提交一样的忽略格式(为了看到更明显的效果,我在多忽略一个字段:"username")。
@ApiOperationSupport(author = "逆流星007",ignoreParameters = {"id","userAddressDTO.id"})
@PostMapping(value = "/saveUser")
@ApiOperation("新增用户信息")
@ApiOperationSupport(author = "逆流星007",ignoreParameters = {"id","userAddressDTO.id"})
public String saveUser(@RequestBody UserDTO userDTO){
System.out.println("前端传递的用户信息:"+ userDTO);
return "save success";
}
@PostMapping(value = "/updateUser")
@ApiOperation("编辑用户信息")
@ApiOperationSupport(author = "逆流星007")
public String updateUser(@RequestBody UserDTO userDTO){
System.out.println("前端传递的用户信息:"+ userDTO);
return "save success";
}
我们先来看看效果会是什么样子?是否能够成功忽略呢?
新增接口
哦吼,居然也忽略成功了,卧槽,这打脸的也太快了,UserDTO 中被忽略一个字段:id,,UserAddressDTO 对象我忽略了 id 字段,我们查看 ui 界面发现确实忽略成功了,这是怎么回事呢?具体为啥,我也不太清楚,可能是 3.x 做了升级,忽略方式和表单一致了,也许是3.x 不太稳定,出现了诡异的bug,导致了 json 格式也能这样忽略,虽然这样同样可以忽略成功,由于我不确定是高版本做了优化没有更新文档还是诡异bug导致,我还是继续介绍一下 json 格式参数的忽略格式,有可能同学们这样使用却是不可以的,我推荐还是按照下面的格式编写。
json 格式如何忽略呢?
专业说法是:实例名.属性名,以新增用户为例,我们需要过滤用户id,那么写法就是:userDTO.id,其中 userDTO 为 saveUser() 的 参数名。
现在我们来改造一下我们的代码
@PostMapping(value = "/saveUser")
@ApiOperation("新增用户信息")
@ApiOperationSupport(author = "逆流星逆流星007",ignoreParameters = {"userDTO.id","userDTO.userAddressDTO.id"})
public String saveUser(@RequestBody UserDTO userDTO){
System.out.println("前端传递的用户信息:"+ userDTO);
return "save success";
}
我们一起来看看效果
这里还有一个情况是需要注意的,如果你忽略的字段在对象的第二层,那么在请求示例中,将会看不到完成的示例代码,会缺斤少两,可能 3.x 的bug吧,所以开头我申明过, 3.x 目前可能还不够稳定,升级或者使用的同学还是需要慎重啊。
搜索API接口
在文档的右上角,Knife4j
提供了文档检索的功能
那这个搜索框都支持哪些关键字搜索呢?
- 接口地址。
- 接口名称。
- 接口描述。
以上三个搜索都是模糊搜索,但是,需要注意的是:目前检索功能仅对当前分组下的已经加载的接口有效,对于分组中的接口,没有加载的情况下是搜索不到的,这点需要注意,换句话说该检索功能并非是全局检索,只对当前你看到的整体所有接口列表进行检索。
版本要求:knife4j
版本>2.0.1 使用此规则。
全局参数
Knife4j提供基于UI临时设置全局参数功能,例如后台全局token参数等.提供该功能主要是方便开发者进行调试
目前全局参数功能主要提供两种参数类型:query(表单)、header(请求头)
如果后端Swagger有配置全局参数,该功能可以无视
功能目录:文档管理 -> 全局参数设置
自定义主页内容
不知道大家有没有觉得 swagger 的首页有一种很丑的感觉?是不是很不想看到它呢?那么接下来这条增强功能,决定是你的福利啊,knife4j 支持开发者自己替换首页,不过目前只支持 md 格式。
需要开启增强功能。
Knife4j自2.0.8
版本开始,开发者可以提供一个Markdown文件来自定义显示Home主页的显示内容,通过配置yml来进行开启,配置文件如下
knife4j:
enable: true
setting:
enableHomeCustom: true
homeCustomLocation: classpath:markdown/home.md
属性说明:
enableHomeCustom
:该属性为Boolean值,默认false
,如果开发者要自定义主页内容,该选项设置为true
homeCustomLocation
:提供一个主页的Markdown文件位置
我们先在 resources 目录下创建一个 markdown 目录,然后在 markdown 目录下创建 home.md
逆流星007
昵称:逆流星007
职业:java开发工程
开源博客地址:http://yaomaoyang.com https://blog.csdn.net/qq_33220089
联系邮箱:[email protected]
上面是home.md 的内容,接下来我们重启项目,一起来看看效果
咦,为什么没有发生改变呢?明明已经修改了啊,别急,我们忘记了最核心的一步,所以它没有替换成功,开发者需要在创建Docket
逻辑分组对象时,通过Knife4j
提供的工具对象OpenApiExtensionResolver
将扩展属性进行赋值。
package com.ymy.notes.config.kinfe4j;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import org.springframework.beans.factory.annotation.Autowired;
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 Knife4jConfiguration {
private final OpenApiExtensionResolver openApiExtensionResolver;
@Autowired
public Knife4jConfiguration(OpenApiExtensionResolver openApiExtensionResolver) {
this.openApiExtensionResolver = openApiExtensionResolver;
}
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
String groupName="3.X版本";
Docket docket=new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("这是knife4j API ")
.description("# 这里记录服务端所有的接口的入参,出参等等信息")
.termsOfServiceUrl("http://yaomaoyang.com")
.contact(new Contact("逆流星","http://yaomaoyang.com","[email protected]"))
.version("3.0")
.build())
//分组名称
.groupName(groupName)
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.ymy.notes.controller"))
.paths(PathSelectors.any())
.build()
.extensions(openApiExtensionResolver.buildSettingExtensions());
return docket;
}
}
通过上面示例代码,主要步骤如下:
1、通过@Autowired
注解引入Knife4j
向Spring容器注入的Bean对象OpenApiExtensionResolver
2、最终在Dcoket
对象构建后,通过调用Docket
对象的extensions
方法进行插件赋值
3、插件赋值需要调用OpenApiExtensionResolver
提供的buildSettingExtensions
方法,获取x-settings
的增强属性
这样,我们就能看到效果了。
禁用调试
在以前的版本中,开发者如果要禁用调试功能,是通过在服务端创建UiConfiguration的实体Bean对象,配置supportMethod来达到禁用部分接口的调试,自2.0.8
版本后,该属性被废弃
此功能需要开启增强模式才能使用
如果开发者需要禁用调试功能,只需要在配置文件中进行操作即可
knife4j:
enable: true
setting:
enableDebug: false
属性说明:
enableDebug
:该属性是一个Boolean
值,代表是否启用调试功能,默认值为true
(代表开启调试),如果要禁用调试,该值设为false
同样,此操作也需要开发者在创建Docket
逻辑分组对象时,通过Knife4j
提供的工具对象OpenApiExtensionResolver
将扩展属性进行赋值。
package com.ymy.notes.config.kinfe4j;
import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver;
import org.springframework.beans.factory.annotation.Autowired;
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 Knife4jConfiguration {
private final OpenApiExtensionResolver openApiExtensionResolver;
@Autowired
public Knife4jConfiguration(OpenApiExtensionResolver openApiExtensionResolver) {
this.openApiExtensionResolver = openApiExtensionResolver;
}
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
String groupName="3.X版本";
Docket docket=new Docket(DocumentationType.OAS_30)
.apiInfo(new ApiInfoBuilder()
.title("这是knife4j API ")
.description("# 这里记录服务端所有的接口的入参,出参等等信息")
.termsOfServiceUrl("http://yaomaoyang.com")
.contact(new Contact("逆流星","http://yaomaoyang.com","[email protected]"))
.version("3.0")
.build())
//分组名称
.groupName(groupName)
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.ymy.notes.controller"))
.paths(PathSelectors.any())
.build()
.extensions(openApiExtensionResolver.buildSettingExtensions());
return docket;
}
}
全部操作完成之后,重启项目看效果
调试和 open 按钮没有了。
禁用搜索框
发者如果想要禁用Ui界面中的搜索功能,需要通过增强属性进行配置,此功能需要开启增强功能。
knife4j:
enable: true
setting:
enableSearch: false
属性说明:
enableSearch
:该属性是一个Boolean
值,代表是否启用搜索功能,默认值为true
(代表开启搜索),如果要禁用搜索,该值设为false
同样,此操作也需要开发者在创建Docket
逻辑分组对象时,通过Knife4j
提供的工具对象OpenApiExtensionResolver
将扩展属性进行赋值。具体的代码实现请参考禁用调试和自定义主页内容,我这里就不重复了。
重启项目看效果
好了,knife4j 的介绍到这里就结束了,还有一些高级的功能,就需要大家自己慢慢的摸索了,本文大部分参考了 knife4j 的官方文档,自己写的 demo,如果觉得对您有帮助,希望留下您宝贵的一赞。