当前位置: 代码网 > it编程>编程语言>Java > SpringBoot整合knife4j实践

SpringBoot整合knife4j实践

2025年06月23日 Java 我要评论
springboot 整合knife4jknife4j是一款基于swagger 2的在线api文档框架在spring boot中,使用此框架时,需要:添加依赖在配置文件(`application.pr

springboot 整合knife4j

knife4j是一款基于swagger 2的在线api文档框架

在spring boot中,使用此框架时,需要:

  • 添加依赖
  • 在配置文件(`application.properties`)中开启增强模式
  • 编写配置类(代码相对固定,建议cv)

引入knife4j

添加依赖

<dependency>
    <groupid>com.github.xiaoymin</groupid>
    <artifactid>knife4j-spring-boot-starter</artifactid>
    <version>3.0.3</version>
</dependency>

创建 swagger 配置依赖

package com.yolo.knife4j.config;

import io.swagger.annotations.api;
import lombok.extern.slf4j.slf4j;
import org.springframework.beans.factory.annotation.value;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.context.annotation.import;
import springfox.bean.validators.configuration.beanvalidatorpluginsconfiguration;
import springfox.documentation.builders.*;
import springfox.documentation.service.*;
import springfox.documentation.spi.documentationtype;
import springfox.documentation.spring.web.plugins.docket;
import springfox.documentation.swagger2.annotations.enableswagger2webmvc;

@slf4j
@configuration
@enableswagger2webmvc
// 对jsr303提供支持
@import(beanvalidatorpluginsconfiguration.class)
public class knife4jconfig {

    @value("${spring.application.name}")
    private string applicationname;
    @bean
    public docket defaultapi() {
        return new docket(documentationtype.swagger_2)
                .apiinfo(apiinfo())
                .groupname(applicationname)
                .select()
                // 添加@api注解才显示
                .apis(requesthandlerselectors.withclassannotation(api.class))
                // 这里指定controller扫描包路径
//                .apis(requesthandlerselectors.basepackage("com.yolo"))
                .paths(pathselectors.any())
                .build();
    }

    /**
     * swagger-api接口描述信息
     */
    private apiinfo apiinfo() {
        return new apiinfobuilder()
                .title("api文档")
                .description("api文档")
                .contact(
                        new contact(
                                "yolo",
                                "https://gitee.com/huanglei1111",
                                "2936412130@qq.com"
                        )
                )
                .version("1.0.0")
                .build();
    }
}

application.yml配置文件

# https://doc.xiaominfo.com/knife4j
knife4j:
  # 开启增强配置
  enable: true
  # 是否开启生产环境屏蔽   true:关闭swagger,false:开启swagger
  production: false
  basic:
    # 是否开启认证
    enable: false
    # basic认证用户名
    username: admin
    # basic认证密码
    password: 123456
spring:
  application:
    name: test-knife4j

注解

@api(tags = {“用户操作”})
加在controller类上
tags表示该类的标签,在页面会独立显示一个菜单
 
@apioperation(value = “保存用户”, notes = “保存时,id由数据库生成,无需填写,有则忽略”, tags = “保存”)
加在相应的请求处理方法上
value表示该方法的说明
notes相当于对该方法的详细说明,也就是更加完整的描述
tags 表示标签,,在页面会独立显示一个菜单
 
@apiimplicitparam(name = “id”, value = “用户id”, defaultvalue = “1”)
方法只有一个基本类型参数时加在方法上。方法有多个参数时加在@apiimplicitparams内
name 参数中属性的名字
value 对这个属性的描述
defaultvalue 默认值,这个还是有必要填写的,在页面进行请求时,会自动填充
 
@apiimplicitparams(value = {})
用在请求方法上
这个注解必须和@apiimplicitparam配合使用
当请求方法中的请求参数很多的时候,例如saveuser(string username, integer age, date birthday, string phone)
 
@apiparam(value = “当前页”, defaultvalue = “1”)
加在请求方法的普通参数上
value的值是对该参数的说明
与@apiimplicitparam使用的效果等同,根据个人喜好进行使用
 
@apimodel(value = “用户信息”)
加在请求方法的对象类上
value 对该对象参数的描述
例如有一个请求方法save(userdto userdto), 则需要加在userdto这个类上面(可以参照下面的示例)
 
@apimodelproperty(value = “用户id”, example = “1”)
加在请求方法的参数对象的属性上
value 对该属性的描述
example 属性的示例值,在页面会自动填充该值
 
 
@apiignore:注解类、参数、方法,注解后将不在swagger ui中显示

案例

package com.yolo.knife4j.controller;

import cn.hutool.core.collection.listutil;
import com.yolo.knife4j.base.resultvo;
import com.yolo.knife4j.dto.useraddrequest;
import com.yolo.knife4j.vo.studentvo;
import com.yolo.knife4j.vo.uservo;
import io.swagger.annotations.*;
import org.springframework.web.bind.annotation.*;
 
import javax.validation.valid;
import java.util.date;

@apiresponses(value = {
        @apiresponse(code = 200, message = "接口返回成功状态"),
        @apiresponse(code = 500, message = "接口返回未知错误,请联系开发人员调试")
})
@api(tags = "用户")
@restcontroller
@requestmapping("/user")
public class usercontroller {


    @apioperation(value = "保存用户", notes = "简单传参")
    @postmapping("/add")
    public resultvo<object> add(@requestbody @valid useraddrequest useraddrequest) {
        return resultvo.builder().build().setcode(200).setsuccess(true)
                .settime(new date()).setmsg("保存用户成功").setdata(useraddrequest);
    }

    @apioperation(value = "保存用户2", notes = "复杂传参")
    @postmapping("/add2")
    public resultvo<object> add2(@requestbody @valid useraddrequest useraddrequest) {
        return resultvo.builder().build().setcode(200).setsuccess(true)
                .settime(new date()).setmsg("保存用户成功").setdata(useraddrequest);
    }


    @getmapping("/list")
    @apioperation(value = "查找用户列表", notes = "根据id查找单个用户")
    public resultvo<object> list(@requestparam @apiparam(value = "当前页", defaultvalue = "1") integer pagenum,
                          @requestparam @apiparam(value = "页大小", defaultvalue = "10") integer pagesize) {

        uservo vo = new uservo();
        studentvo studentvo = studentvo.builder().build().setaddress("wuhan").setcode(2);
        vo.setstudentvos(listutil.of(studentvo));

        return resultvo.builder().build().setcode(200).setsuccess(true)
                .settime(new date()).setmsg("查找用户列表").setdata(vo);
    }

    @deletemapping("/{id}")
    @apioperation(value = "删除用户", notes = "删除后无法恢复")
    @apiimplicitparam(name = "id", value = "用户id", defaultvalue = "1")
    public resultvo<object> delete(@pathvariable(name = "id") long id) {
        return resultvo.builder().build().setcode(200).setsuccess(true)
                .settime(new date()).setmsg("删除用户");
    }
}

响应参数

package com.yolo.knife4j.base;

import com.fasterxml.jackson.annotation.jsonformat;
import io.swagger.annotations.apimodel;
import io.swagger.annotations.apimodelproperty;
import lombok.allargsconstructor;
import lombok.builder;
import lombok.data;
import lombok.noargsconstructor;
import lombok.experimental.accessors;

import java.io.serializable;
import java.util.date;

@data
@builder
@accessors(chain = true)
@apimodel("响应参数")
@allargsconstructor
@noargsconstructor
public class resultvo<t> implements serializable {

    private static final long serialversionuid = -8054007511410819665l;

    @apimodelproperty(value = "响应状态码", example = "1", datatype = "integer")
    private int code;

    // 是否成功标识.true表示成功,false表示失败
    @apimodelproperty("success标识,true表示成功,false表示失败")
    private boolean success;

    // 操作成功时需要响应给客户端的响应数据
    @apimodelproperty("响应信息")
    private string msg;


    @apimodelproperty("响应数据")
    private t data;

    @apimodelproperty("当前时间")
    @jsonformat(pattern = "yyyy-mm-dd hh:mm:ss", timezone = "gmt+8")
    private date time;
}

tips: http://127.0.0.1:8080/doc.html

这里端口,就是你运行项目的端口

knife4j增强功能

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

接口添加作者

添加作者有俩种方式

  • 在方法上使用注解 @apioperationsupport(author = "yolo-test")
  • 在controller类上使用注解 @apisupport(author = "yolo-controller")

如果在方法上使用了注解,并且也在类上使用了注解,那么最后的展示结果以方法上的注解为准

资源屏蔽

当我们在生成环境的时候不想显示接口文档,由于 knife4j 基于 servlet 体系提供了过滤 filter 功能,所以就不需要我们再去造轮子了,直接使用即可

knife4j:
  # 开启增强配置
  enable: true
  # 是否开启生产环境屏蔽   true:关闭swagger,false:开启swagger
  production: true

然后重启项目

访问页面加权控制

针对swagger的资源接口,knife4j提供了简单的basic认证功能

简单点说,指定一个用户名和密码,访问 swagger 文档需要验证登录名和密码,验证通过之后才能正常访问

如果用户开启了 basic (knife4j.basic.enable = true)认证功能,但是没有指定 username 和password,那么 knife4j 提供了一组默认的用户名密码

admin/123321
knife4j:
  # 开启增强配置
  enable: true
  # 是否开启生产环境屏蔽   true:关闭swagger,false:开启swagger
  production: false
  basic:
    # 是否开启认证
    enable: true
    # basic认证用户名
    username: admin
    # basic认证密码
    password: 123456

如果开启生产环境屏蔽了,开启basic认证是不生效的

接口排序

@apioperationsupport注解中增加了 order 字段,用于接口排序。在使用此注解之前需要开启增强功能

分组排序

分组,顾名思义,就是多个 controller 之间的排序,开发者可以通过注解实现每个controller 之间的排序,实现这个功能的注解一共有三个,具体如下

@apisupport

@restcontroller
@requestmapping(value = "/test")
@apisupport(author = "yolo-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

tips:

  • 这三个注解是存在优先级的,也就是说,当同时使用时,只会有一个注解生效,所以在使用的时候需要特别注意。优先级规则如下
  • @apisupport > @apisort>@api

请求参数缓存

我们在调试接口的时候,有的接口会有很多参数,当我们好不容易填好了所有的参数,由于我们不小心关闭了页面,下次再调试的时候发现还需要再次将参数输入一遍,心态会爆炸吧,所以 knife4j 在文档管理中增加了一个选项:开启请求参数缓存

tips:

俩种情况会失效

  • 1、 @apimodelproperty 注解中添加 example (属性的示例值)属性,那么, knife4j 将不会使用缓存,使用的是后端指定的 example
  • 2、当域名发生改变时,所有缓存将会失效

过滤请求参数

我们在开发过程中,经常会遇到这样的一个问题,新增和修改接口,修改接口需要传递修改的记录id,但是新增则不需要,而后端往往会将修改和新增的入参对象设置为一个对象,那么这个对象中必然会存在 id 字段,这就会对新增造成误导

所以,knife4j 支持了请求参数的过滤(忽略),实现方式也是非常的简单,使用自定义增强注解apioperationsupport中的ignoreparameters属性,可以强制忽略要显示的参数

这里表单和json格式过滤参数是不一样的

我们先看表单格式

@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;
}

@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;
}



    @postmapping(value = "/saveuser")
    @apioperation("新增用户信息-表单")
    @apioperationsupport(author = "yolo",ignoreparameters = {"id","useraddressdto.id"})
    public string saveuser(userdto userdto){
        system.out.println("前端传递的用户信息:"+ userdto);
        return "save success";
    }
    @postmapping(value = "/updateuser")
    @apioperation("编辑用户信息")
    @apioperationsupport(author = "yolo")
    public string updateuser( userdto userdto){
        system.out.println("前端传递的用户信息:"+ userdto);
        return "edit success";
    }

在过滤字段的时候,第一层我们只要填写对象中的属性名即可,但如果需要过滤第二层,根据忽略规则中的第二条,我们在 userdto 对象中引入 useraddressdto 对象:private useraddressdto useraddressdto; 我们还需要忽略 useraddressdto 对象中的 id 属性,那么需要填上 useraddressdto.id ,其中 useraddressdto 要与 userdto 对象中的 useraddressdto 属性名一致

新增操作没有id

编辑操作

json格式忽略

专业说法是:实例名.属性名,以新增用户为例,我们需要过滤用户id,那么写法就是:userdto.id,其中 userdto 为 saveuser() 的 参数名

    @postmapping(value = "/saveuser")
    @apioperation("新增用户信息")
    @apioperationsupport(author = "yolo",ignoreparameters = {"userdto.id","userdto.useraddressdto.id"})
    public string saveuser(@requestbody userdto userdto){
        system.out.println("前端传递的用户信息:"+ userdto);
        return "save success";
    }

禁用调试

knife4j:
  enable: true
  setting:
    enabledebug: false

enabledebug:该属性是一个boolean值,代表是否启用调试功能,默认值为true(代表开启调试),如果要禁用调试,该值设为false

同样,此操作也需要开发者在创建docket逻辑分组对象时,通过knife4j提供的工具对象openapiextensionresolver将扩展属性进行赋值

禁用搜索框

发者如果想要禁用ui界面中的搜索功能,需要通过增强属性进行配置,此功能需要开启增强功能

knife4j:
  enable: true
  setting:
    enablesearch: false

enablesearch:该属性是一个boolean值,代表是否启用搜索功能,默认值为true(代表开启搜索),如果要禁用搜索,该值设为false

同样,此操作也需要开发者在创建docket逻辑分组对象时,通过knife4j提供的工具对象openapiextensionresolver将扩展属性进行赋值。具体的代码实现请参考禁用调试和自定义主页内容,我这里就不重复了。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com