所有分类
  • 所有分类
  • 未分类

Knife4j–使用/教程/实例

简介

说明

本文用示例介绍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

文档

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

请求参数

响应参数

调试普通接口

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

测试结果

调试上传文件接口

代码

下载源码

此隐藏内容仅限VIP查看升级VIP

代码结构

依赖

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

版本的区别如下:

版本说明
1.9.6蓝色皮肤风格,开始更名,增加更多后端模块
2.0~2.0.5Ui重写,底层依赖的springfox框架版本是2.9.2
2.0.6~底层springfox框架版本升级至2.10.5,OpenAPI规范是v2
3.0~底层依赖springfox框架版本升级至3.0.3,OpenAPI规范是v3

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-解决整合@ControllerAdvice时访问失败的问题 – 自学精灵

清缓存

见:Knife4j–清除缓存的方法 – 自学精灵

上传文件

见:Knife4j–解决不显示文件上传的问题 – 自学精灵

下载文件

见:Knife4j-解决下载文件乱码的问题 – 自学精灵

0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录