草庐IT

Knife4j 3.0.3 整合SpringBoot 2.6.4

北冥牧之 2023-10-29 原文

目录

一、引入依赖

二、代码配置

三、配置文件

四、页面功能

1.主页

2.Swagger Modules

五、如何使用

1.在controller上加两个注解:

2.方法上加注解

六、参数设置

七、非实体类参数设置 

八、忽略参数


关于 swagger 本文不再赘述,网上文章很多。本文要讲的是 Knife4j 3.0.3 整合SpringBoot 2.6.4,因为 knife4j 3.x版本(目前只有这一个版本)和2.x版本还是有一些区别的,如果配置注解方面使用不当,很容易导致文档页面打不开。同时,SpringBoot 2.6.4的版本也是相对较高的版本,在SpringBoot 2.4以上的版本和之前的版本还是不一样的,这个也容易导致一些问题。本文就这两个版本的整合做一个实战介绍。

一、引入依赖

<!-- Spring Boot 项目starter,快速使用knife4j增强文档 -->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
	<artifactId>knife4j-spring-boot-starter</artifactId>
	<version>3.0.3</version>
</dependency>

使用Knife4j 3.0.3只需要引入这一个依赖即可,其他的swagger依赖不需要了。

 这是Knife4j 3.0.3版本的依赖所包含的依赖,可见,swagger的依赖已经有了。

二、代码配置

直接上代码

package com.dake.common.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Knife4j 3.X 配置类.
 * 访问地址:
 * <p>
 *     Knife4j 访问首页:<a href="http://localhost:8090/doc.html#/home">...</a>
 * </p>
 *
 * @author fangqi
 * @date 2022-6-27 23:43:39
 */
@EnableKnife4j
@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
// 在 Swagger 3.X 以下版本报错时可以加此注解解决,但是在3.X版本以上的,加此注解会导致页面无法打开
//@EnableWebMvc
public class SwaggerConfig {

    private static final String SWAGGER_TITLE = "XXX项目 API 接口文档";
    private static final String VERSION = "3.0.3";

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.OAS_30)
                .enable(true)
                // .useDefaultResponseMessages(false)
                .apiInfo(apiInfo())
                .groupName("3.X 版本")
                .select()
                // 方式一: 配置扫描 所有想在swagger界面的统一管理接口,都必须在此包下
//                .apis(RequestHandlerSelectors.basePackage("com.dake.controller"))
                .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
                // 方式二: 只有当方法上有  @ApiOperation 注解时才能生成对应的接口文档
                // .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title(SwaggerConfig.SWAGGER_TITLE)
                .description("# XXX项目API接口文档简介")
                .termsOfServiceUrl("http://127.0.0.1/#/login")
                .contact(new Contact("fangqi", "", "fang_qi170@126.com"))
                .version(SwaggerConfig.VERSION)
                .build();
    }

    @Bean
    public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessAfterInitialization(@NotNull Object bean, @NotNull String beanName) throws BeansException {
                if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
                }
                return bean;
            }

            private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
                List<T> copy = mappings.stream()
                        .filter(mapping -> mapping.getPatternParser() == null)
                        .collect(Collectors.toList());
                mappings.clear();
                mappings.addAll(copy);
            }

            @SuppressWarnings("unchecked")
            private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
                try {
                    Field field = ReflectionUtils.findField(bean.getClass(),             "handlerMappings");
                    assert field != null;
                    field.setAccessible(true);
                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
        };
    }

}

三、配置文件

在application.yml文件中,添加如下配置:

springfox:
  documentation:
    swagger:
      v2:
        path: /api-docs
        use-model-v3: true

knife4j:
  # 开启增强
  enable: true
  # 开启登录认证
  basic:
    enable: true
    username: admin
    password: 123456

解释:

上面第一个配置是knife4j的配置,下面的配置是开启增强,打开页面时需要 输入账号密码,我们这里账号 是admin,密码是123456.

四、页面功能

浏览器输入:

http://localhost:8090/doc.html#/ 

 输入用户名和密码即可看到我们所有的controller和加了注解的实体类。

 

 左侧一共有四个被我们用红框框柱的页签。这个显示页面比原先的swagger的页面风格更加美观,也更加适合国人的使用习惯。

下面我们就这四个菜单一一讲解。

1.主页

目前我们 看到的就是主页的信息,也就是我们这个接口文档的简单介绍。

2.Swagger Modules

这部分就是我们在项目中定义的实体类,我们点击打开查看一下。

我们看到这个实际上是层次分明的,不同的实体类类型显示不同的 颜色,非常美观,比起原来的swagger好看多了。

 我们点开第一个看看实体类的情况。

我们看到,有字段的英文名、中文名和数据类型,非常的清晰明了。

要知道,这个不是我们手写的。是打开页面直接生成的,哪怕里面的字段变化了,只要我们重启项目、刷新页面,这个接口文档会同步进行变更,使用起来非常方便。以后再和其他同事对接口文档的时候就非常方便了,给他一个地址加上用户名密码,让他自己玩去,不懂了再来问。前端的小姐姐小哥哥用起来也是贼爽的。

上面的这个实体类我们还可以给他起个中文名,那样就更好了,当然你习惯英文名也很好。

上面配置我们配置过了,代码中怎么使用呢?

五、如何使用

1.在controller上加两个注解:

@Api(tags = "XX管理")
@ApiSupport(author = "fangqi", order = 1)

上面一共2个注解,第一个是用来说明这个controller的作用,第二个是用来说明是谁开发的,其他就是为了让别人知道这是谁开发的文档,到时候方便找到你。后面的那个order指的是这个controller在左边侧边栏的展示顺序。你想啊,这么多controller,你定义一个,我定义一个,项目稍微多一些代码,找起来也没有那么方便。如果我们给他定义一个顺序,岂不是美哉?order越小,越靠前。有人说了,大家都定义成1,岂不是乱了?这个当然是的,不过不会报错,都是1,等于都没用了而已。这个顺序呢,其实由项目leader定义会更好一些。最重要的放上面,其他的按照顺序排就是了。

到这里有人说了,原来的接口是你fangqi开发的,现在呢,我要在这个上面加一个功能,也就是加一个请求的方法,到时候别人还是找你,这不合适吧!你说的没错,关于这一点我们可以用另外一个注解来单独设置你增加的那个方法的作者。

比如现在有一个queryNameById的方法是fangdake新加的,那我们只需要在这个请求方法上加这个注解就行了。到时候,其他接口还是找fangqi,而你这个方法会找fangdake。

2.方法上加注解

@ApiOperationSupport(author = "fangdake")

我们上面讲了,可以给类上加注解,给一个中文的提示,告诉使用者这个controller是干什么的,但是方法上呢?当然了,方法上我们一样可以给一个中文的说明:

@ApiOperation(value = "查询初始化数据", 
notes = "新增和修改页面的初始化下拉列表数据", 
tags = "延伸操作")

其中,value标签是指的方法的基本功能;notes就是一个描述性的文字,详细的说明;tags呢,其实用处不大,在打开接口文档的时候它会把你这个方法再展示一份放到你给tags起的名字的这个标签下。你打开延伸操作的时候就能看到你加过tags标签的方法了。其实有点类似于分组一样,从你原先的controller中又给出了一个分组。个人感觉呢,一般是用来给测试或者领导看的。领导觉得有一二三四五,这五个功能比较重要,他可能偶尔要看看,或者这几个方法比较重要——其实就是太难了,测试要多次测试,而且问题很多,今天测试玩明天测试。这时你就可以把不同类的不同的几个方法抽出来放一个单独的分组,这样比一个菜单一个菜单的去找方便多了,尤其是有一些方法上面用的不是GetMapping这样的注解,而是RequestMapping,到时候,每个方法都会在这个菜单下生成很多个测试接口,也就是重复的,你会很难受。

上图其实就是2个方法,但是我们打开这个菜单的时候会显示这么多。因为接口中没有指定具体的请求方式,都是RequestMapping,所以这个接口文档的测试功能就把所有的测试方法全部给展现出来了,不管是get、post还是delete等请求。

 我们打开一个具体的接口。

 可以看到请求参数和返回参数清晰明了。之所以会这样,是因为我们的请求参数和返回参数都是对象,而且我们在具体的对象上加了注解,所以才会如此。那如何操作呢,我们来看看。

首先是请求参数:

@Data
@ApiModel(description = "查询xxx列表DTO")
public class QueryBiListDTO {

    @NotBlank(message = "页码不能为空")
    @ApiModelProperty(value = "页码", required = true)
    private Integer pageNo;

    @NotBlank(message = "每页条数不能为空")
    @ApiModelProperty(value = "每页条数", required = true)
    private Integer pageCount;

    @ApiModelProperty(value = "xxid")
    private String id;
}

返回参数同请求参数,是一样的。

我们看到上面的那个图片,有一个调试。我们点击调试。

我们启动项目,上面输入我们需要的参数,直接可以调试了,非常方便。不用像postman一样,搞来搞去,麻烦死了,而且这个是所有人都能看到的,不用每个人都去搞一份。

六、参数设置

有人说了,postman测试的东西可以保存啊!其实这个一样的。

打开文档管理:

我们看到默认是开启请求参数缓存的,也就是说我们刚才请求过一次,下一次再请求的时候,我们刚才输入的参数还在,不用每次都输入很多参数,这么麻烦。如果是一两个字段还好,如果是新增编辑,特别是很多字段的大页面的编辑,每次搞一下,办个小时过去了。这个接口就很方便了,这次新增时你输入的值,下次还在。你测试的时候只需要改个别地方就可以了,非常非常方便。

到这了,还有人会说,我们很多时候要从请求头里面那一些东西,比如token了,userId了,等等。确实,一般是这么操作的。别慌,我们这个接口文档测试的的时候一样可以搞定。

 

 

 

比如,你每次需要从请求头里面获取到用户id,那么你可以这里设置成header,然后输入userId,然后是userId的具体值。如果你要输入token,那么就输入token和具体的值。至于这个token的值嘛,需要你获取到之后放到这里。

这样看来,这个接口文档就不止是接口文档了,它同时也是测试的工具,保存测试数据的工具。至于术语咱就不bb了,什么这加那加那的综合体之类的,没啥意义。

当然,如果有人想要你这个测试的数据,又不能让你一个一个的拷贝出来给他,那多难受啊!这个文档支持4种方式的下载。

七、非实体类参数设置 

上面我们给出的接口文档的请求参数都是对象的,我们当然知道每个字段什么意思了,当时如果是单个字段或者是map呢?用map作为controller的请求参数的非蠢既坏,但是没办法,谁让人家是用户呢?

这个也很简单。

@ApiOperation("修改密码")
    @ApiImplicitParams({
	@ApiImplicitParam(name = "username",value = "账号" , dataType = "String", paramType = "query"),		
	@ApiImplicitParam(name = "oldPassword",value = "旧密码" , dataType = "String", paramType = "query"),
	@ApiImplicitParam(name = "newPassword",value = "新密码" , dataType = "String", paramType = "query")
	})

八、忽略参数

在我们的新增和编辑页面,经常是编辑只比新增多了一个id,如果此时我们再单独给新增编辑加一个实体类,其实有一些多余。此时我们只需要指定对应的字段忽略掉即可。

@PostMapping("addUser")
@ApiOperation("新增用户")
@ApiOperationSupport(ignoreParameters = "id") // 忽略掉User中的id属性,不显示在文档中
public void addUser(User user) {

}

注意:

ignoreParameters支持以数组形式添加多个忽略参数
ignoreParameters支持忽略级联对象的参数,比如User实体类中有个Address类型的属性addr,那么如果想要忽略Address的属性id,那么只需要配置为ignoreParameters = "addr.id"即可
如果要忽略的参数过多,可以使用includeParameters反向配置

 如果是以@RequestBody形式接收参数,那么ignoreParameters中填写参数名.要忽略的属性名即可。

@PostMapping("addUser2")
@ApiOperation("添加用户2")
@ApiOperationSupport(ignoreParameters = {"user.id", "user.age"})
public void addUser2(@RequestBody User user) {

}

注意:

ignoreParameters支持以数组形式添加多个忽略参数
ignoreParameters支持忽略级联对象的参数,比如User实体类中有个Address类型的属性addr,那么如果想要忽略Address的属性id,那么只需要配置为ignoreParameters = "user.addr.id"即可
如果要忽略的参数过多,可以使用includeParameters反向配置

九、生产上关闭 knife4j

如果要在生产上关闭knife4j文档——生产上肯定要关闭的,只要在配置文件中配置:

# 开启屏蔽文档资源
production: true

 如果你的项目中只有一个application.yml,则项目上线时会指定profile,也就是prd的环境,这个时候把屏蔽文档资源打开即可;如果是多个application文件,比如一个基础的application.yml,然后一个application-dev.yml,一个application-uat.yml,一个application-prd.yml,那么只要在prd这个文件中添加上面 的配置即可。

有关Knife4j 3.0.3 整合SpringBoot 2.6.4的更多相关文章

  1. springboot定时任务 - 2

    如果您希望在Spring中启用定时任务功能,则需要在主类上添加 @EnableScheduling 注解。这样Spring才会扫描 @Scheduled 注解并执行定时任务。在大多数情况下,只需要在主类上添加 @EnableScheduling 注解即可,不需要在Service层或其他类中再次添加。以下是一个示例,演示如何在SpringBoot中启用定时任务功能:@SpringBootApplication@EnableSchedulingpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.ru

  2. 基于SpringBoot的线上日志阅读器 - 2

    软件特点部署后能通过浏览器查看线上日志。支持Linux、Windows服务器。采用随机读取的方式,支持大文件的读取。支持实时打印新增的日志(类终端)。支持日志搜索。使用手册基本页面配置路径配置日志所在的目录,配置后按回车键生效,下拉框选择日志名称。选择日志后点击生效,即可加载日志。windows路径E:\java\project\log-view\logslinux路径/usr/local/XX历史模式历史模式下,不会读取新增的日志。针对历史文件可以分页读取,配置分页大小、跳转。历史模式下,支持根据关键词搜索。目前搜索引擎使用的是jdk自带类库,搜索速度相对较低,优点是比较简单。2G日志全文搜

  3. springboot使用validator进行参数校验 - 2

    1.依赖导入org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-validation2.validation常用注解@Null被注释的元素必须为null@NotNull被注释的元素不能为null,可以为空字符串@AssertTrue被注释的元素必须为true@AssertFalse被注释的元素必须为false@Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值@Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值@D

  4. ruby - 是否有 Log4J for Ruby 的等价物,Log4Ruby? - 2

    找了一圈也没找到。是否有Ruby的Log4X等价物?如果不是,那么处理所有调试语句的最佳方法是什么。我是Ruby的新手。谢谢! 最佳答案 Ruby带有一个内置的日志库,但是有log4r.内置库的一个简短示例:#!/usr/bin/envrubyrequire'logger'log=Logger.new('mylog.txt')log.debug"Hellolog" 关于ruby-是否有Log4JforRuby的等价物,Log4Ruby?,我们在StackOverflow上找到一个类似的问

  5. ruby - 如何将 Interactive Ruby 整合到我的开发过程中? - 2

    我正在尝试找到一种更好的方法将IRB与我的常规ruby​​开发集成。目前我很少在我的代码中使用IRB。我只用它来验证语法或尝试一些小的东西。我知道我可以将我自己的代码加载到ruby​​中作为一个require'mycode'但这通常不符合我的编程风格。有时我要检查的变量超出范围或在循环内。有没有一种简单的方法可以启动我的脚本并在IRB内的某个点卡住?我想我正在寻找一种更简单的方法来调试我的ruby​​代码而不破坏我的F5(编译)键。也许有经验的ruby开发者可以和我分享一个更精简的开发方法。 最佳答案 安装ruby​​-debugg

  6. ruby - 使用 Drupal 和 Ruby。有没有人整合两者? - 2

    我开始了一个小型网络项目并使用Drupal来构建它。到目前为止,还不错:您可以快速建立一个不错的面向CMS的网站,通过模块添加社交功能,并且您有一个广泛的API可以在一个架构良好的平台中进行自定义。现在问题来了:网站的增长超出了最初的计划,我发现自己正处于认真开始为它编写代码的境地。由于Drupal项目,我对PHP有了新的认识,但我想用Ruby来做。我会感觉更舒服,以后维护起来更容易,我可以在其他Ruby/Rails应用程序中重用它。随着时间的推移,我想我会用Ruby重写Drupal中的现有部分。基于此,问题是:是否有人将两者(成功或失败的故事)结合起来?这是一个相当大的决定,但我在G

  7. 停车系统源码-基于springboot+uniapp开源项目 - 2

    Iparking停车收费管理系统-可商用介绍Iparking是一款基于springBoot的停车收费管理系统,支持封闭车场和路边车场,支持微信支付宝多种支付渠道,支持多种硬件,涵盖了停车场管理系统的所有基础功能。技术栈Springboot,MybatisPlus,Beetl,Mysql,Redis,RabbitMQ,UniApp功能云端功能序号模块功能描述1系统管理菜单管理配置系统菜单2系统管理组织管理管理组织机构3系统管理角色管理配置系统角色,包含数据权限和功能权限配置4系统管理用户管理管理后台用户5系统管理租户管理多租户管理6系统管理公众号配置租户公众号配置7系统管理操作日志审计日志8系统

  8. ruby - 使用 Knife 更新 Chef 中的运行列表 - 2

    我有一本包含Recipe列表的Recipe。在chefknife中使用命令行工具从Recipe中添加一些特定Recipe(不是全部)的命令是什么?我知道将整个Recipe添加到运行列表的命令是knifenoderun_listaddservernamerecipe[cookbookname]。 最佳答案 所以你的想法是对的,knifenoderun_listadd$nodename$item就是你想要的命令。recipe[mycookbook]没有添加“整个Recipe”,而只是recipe[mycookbook::default]

  9. ruby-on-rails - neo4j 的哪个 Ruby REST API 客户端? - 2

    我想知道Ruby(不是JRuby,所以native绑定(bind)不是一个选项)可以使用哪些RESTAPI客户端?理想情况下,我希望API类似于neo4jgem或ActiveRecord(验证、迁移、观察者等)。当前可用的(REST)工具甚至无法与我们所拥有的相提并论,例如,在ActiveRecrod中:neograhy-只是普通RESTAPI。与模型等无关neology-只是对新地理学的包装,并不是功能齐全的ActiveModel。architect4r-符合ActiveModel,但仅提供一种查询数据的方式(Cypher语言),也不支持索引。我更喜欢architect4r的代码(主

  10. 优化大数据量查询方案——SpringBoot(Cloud)整合ES - 2

    一、Elasticsearch简介实际业务场景中,多端的查询功能都有很大的优化空间。常见的处理方式有:建索引、建物化视图简化查询逻辑、DB层之上建立缓存、分页…然而随着业务数据量的不断增多,总有那么一张表或一个业务,是无法通过常规的处理方式来缩短查询时间的。在查询功能优化上,作为开发人员应该站在公司的角度,本着优化客户体验的目的去寻找解决方案。本人有幸做过Tomcat整合solr,今天一起研究一下当前比较火热的Elasticsearch搜索引擎。Elasticsearch是一个非常强大的搜索引擎。它目前被广泛地使用于各个IT公司。Elasticsearch是由Elastic公司创建。它的代码位

随机推荐