微信扫一扫 分享朋友圈

已有 1112 人浏览分享

开启左侧

Knife4j--使用教程及环境配置

[复制链接]
1112 0
简介
说明
        本文用示例介绍knife4j的用法。(SpringBoot整合knife4j)
        Knife4j是一个很好用的接口文档工具。之前用过Swagger,觉得页面不太好,浏览技术网站时,偶然发现swagger-bootstrap-ui,它能将接口进行归类。
        早期,swagger-boostrap-ui是1.x版本,如今swagger-bootsrap-ui到2.x,同时也更改名字Knife4j,适用于单体和微服务项目。
        Knife4j跟Swagger用法基本一样,swagger用法见:Swagger--使用/教程/实例/配置_IT利刃出鞘的博客-CSDN博客
官网
首页:knife4j
文档:knife4j
gitee地址:https://gitee.com/xiaoym/knife4j
实例
官网文档:1.6 快速开始 | knife4j
依赖及配置
依赖
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>
本处我使用比较新的版本展示。(目前2.0.9是最新的发布版,最稳定。)
版本的区别如下:
image.png
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("knife", "https://knife.blog.csdn.net/", "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://www.xx.com/")
                        .contact(new Contact("IT利刃出鞘", "https://knife.blog.csdn.net", "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.user.controller;
import com.example.demo.business.user.request.UserAddRequest;
import com.example.demo.business.user.request.UserEditRequest;
import com.example.demo.business.user.request.UserQueryRequest;
import com.example.demo.business.user.vo.UserVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Api(tags = "用户")
@RestController
@RequestMapping("/user")
public class UserController {
    @ApiOperation("添加")
    @PostMapping("/add")
    public UserVO add(@RequestBody @Valid UserAddRequest userAddRequest) {
        // 将数据写到数据库
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userAddRequest, userVO);
        userVO.setId(1L);
        userVO.setCreateTime(LocalDateTime.now());
        userVO.setUpdateTime(LocalDateTime.now());
        return userVO;
    }
    @ApiOperation("修改")
    @PostMapping("/edit")
    public UserVO edit(@RequestBody @Valid UserEditRequest userEditRequest) {
        // 修改数据库的数据
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(userEditRequest, userVO);
        userVO.setUpdateTime(LocalDateTime.now());
        return userVO;
    }
    @ApiOperation("查找")
    @GetMapping("/find")
    public List<UserVO> find(UserQueryRequest userQueryRequest) {
        return new ArrayList<>();
    }
    @ApiOperation("删除")
    @PostMapping("/delete")
    public void delete(Long id) {
        // 将数据库数据删除
    }
}
Entity
说明
        本处我将增删改查都单独写一个实体类。
        当然,也可以将增删改的参数都写到一个实体里边,通过@Null,@NotNull以及它们的groups属性来指定属于哪个分组。这样写在运行时不会有问题,但在Knife4j页面显示时会不正常,原因是:Swagger没有很好地处理好这种情况。
添加
package com.example.demo.business.user.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
@ApiModel("添加用户")
public class UserAddRequest {
    @ApiModelProperty(value = "用户名", required = true)
    @NotBlank(message = "用户名不能为空")
    private String userName;
    @ApiModelProperty("昵称")
    private String nickName;
    @ApiModelProperty("邮箱")
    private String email;
}
修改
package com.example.demo.business.user.request;
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 UserEditRequest {
    @ApiModelProperty(value = "用户ID", required = true)
    @NotNull(message = "用户ID不能为空")
    private Long id;
    @ApiModelProperty(value = "用户名", required = true)
    @NotBlank(message = "用户名不能为空")
    private String userName;
    @ApiModelProperty("昵称")
    private String nickName;
    @ApiModelProperty("邮箱")
    private String email;
}
查询
package com.example.demo.business.user.request;
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 UserQueryRequest {
    @ApiModelProperty("用户id")
    private Long id;
    @ApiModelProperty("用户名")
    private String userName;
    @ApiModelProperty("昵称")
    private String nickName;
    @ApiModelProperty("邮箱")
    private String email;
    @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.user.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 UserVO {
    @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跟Tomcat共用一个端口,默认Tomcat是8080。访问地址:
http://localhost:8080/doc.html
image.png
分组Url
“分组Url”是文档地址,其他软件(比如apifox)可以将它作为导入文档的url。
此网址可以直接访问:http://localhost:8080/v3/api-docs?group=all
image.png
文档
本处展示添加用户接口的文档:
image.png
image.png
本处展示添加用户的自测方法
image.png
image.png
简介
若加了全局的响应的处理,则会报错,或者无法正常使用。比如:“Knife4j文档请求异常”。
官网
快速开始 | knife4j
解决方法
需要将knife4j的接口数据忽略掉。配置如下:
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.common.entity.ResultWrapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.Arrays;
import java.util.List;
@ControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
    private List<String> KNIFE4J_URI = Arrays.asList(
            "/doc.html",
            "/swagger-resources",
            "/swagger-resources/configuration",
            "/v3/api-docs",
            "/v2/api-docs",
            "/webjars/**");
    @Override
    public boolean supports(MethodParameter returnType,
                                Class<? extends HttpMessageConverter<?>> converterType) {
        // 若接口返回的类型本身就是ResultWrapper,则无需操作,返回false
        // return !returnType.getParameterType().equals(ResultWrapper.class);
        return true;
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                      MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof String) {
            // 若返回值为String类型,需要包装为String类型返回。否则会报错
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                ResultWrapper<String> result = ResultWrapper.success().data(body);
                return objectMapper.writeValueAsString(result);
            } catch (JsonProcessingException e) {
                throw new RuntimeException("序列化String返回类型错误");
            }
        } else if (body instanceof ResultWrapper) {
            return body;
        } else if (isKnife4jUrl(request.getURI().getPath())) {
            //如果是接口文档的uri,直接跳过
            return body;
        }
        return ResultWrapper.success().data(body);
    }
    private boolean isKnife4jUrl(String uri) {
        AntPathMatcher pathMatcher = new AntPathMatcher();
        for (String s : KNIFE4J_URI) {
            if (pathMatcher.match(s, uri)) {
                return true;
            }
        }
        return false;
    }
}
清缓存
简介
        有时候Knife4j会出现莫名其妙的问题,比如:Knife4j页面的显示与后端的接口不一致。这是Knife4j的前端页面的缓存导致的。
        Knife4j的缓存全部存储在浏览器中的IndexedDB中,所以通过浏览器的强制刷新等操作是无法起到清理缓存的作用的。
官网
3.14 清除缓存 | knife4j
解决方案
F12=> Application=> Storage=> IndexdDB=> 清除Knife4j的缓存
方法如下图所示
image.png
image.png

免责声明:
1,海欣资源网所发布的资源由网友上传和分享,不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
2,海欣资源网的资源来源于网友分享,仅限用于学习交流和测试研究目的,不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。
3,海欣资源网所发布的资源由网友上传和分享,版权争议与本站无关,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。
4,如果您喜欢,请支持正版,购买正版,得到更好的正版服务,如有侵权,请联系我们删除并予以真诚的道歉,联系方式邮箱 haixinst@qq.com
海欣资源-企业信息化分享平台。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

37

主题
热度排行
回复排行
最新贴子

Archiver|手机版|海欣资源 ( 湘ICP备2021008090号-1 )|网站地图

GMT+8, 2024-3-29 01:25 , Gzip On, MemCached On.

免责声明:本站所发布的资源和文章均来自网络,仅限用于学习交流和测试研究目的,不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 本站信息来自网络,版权争议与本站无关,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 如果您喜欢,请支持正版,购买正版,得到更好的正版服务,如有侵权,请联系我们删除并予以真诚的道歉。