修改springboot版本为springboot3之后knife4j生成接口文档无法正常使用问题

问题描述

在学习黑马的苍穹外面项目的时候,由于jdk版本问题,修改了spring boot的版本为3.x,而后导致Swagger用不了了,如下图

 

网上找到的结果是:springboot3.x不支持Knife4j的3.0~3.0.3版本,因此需要换为最新版本。

Knife4j4.0配置

一、简介

官网:Knife4j · 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j

Knife4j是一个集Swagger2 和 OpenAPI3 为一体的增强解决方案

Knife4j 是为 Java MVC 框架集成 Swagger 生成 Api 文档的增强解决方案,前身是 swagger-bootstrap-ui,致力于 springfox-swagger 的增强 UI 实现。knife4j 为了契合微服务的架构发展,由于原来 swagger-bootstrap-ui 采用的是后端 Java 代码 + 前端 UI 混合打包的方式,在微服务架构下显的很臃肿,因此项目正式更名为 knife4j,更名后主要专注的方面如下:

  • 后端 Java 代码以及前端 UI 模块进行了分离,在微服务架构下使用更加灵活

  • 提供专注于 Swagger 的增强解决方案,不同于只是单纯增强前端 UI 部分

二、版本说明

版本说明
1.0~1.9.6名称是叫swagger-bootstrap-ui,蓝色风格Ui
1.9.6蓝色皮肤风格,开始更名,增加更多后端模块
2.0~2.0.5Ui基于Vue2.0+AntdV重写,黑色风格,参考示例,底层依赖的springfox框架版本是2.9.2,仅提供Swagger2规范的适配
2.0.6~2.0.9底层springfox框架版本升级知2.10.5,,仅提供Swagger2规范的适配
3.0~3.0.3底层依赖springfox框架版本升级至3.0.3,OpenAPI规范是v3,过度版本,建议开发者不要使用
4.0~区分OpenAPI2和Swagger3的Maven坐标artifactId OpenAPI2规范服务端解析框架稳定在springfox2.10.5 OpenAPI3框架服务端解析跟随springdoc项目更新迭代 建议开发者使用该版本,请参考4.x升级文档

Spring Boot版本兼容性

Spring Boot版本Knife4j Swagger2规范Knife4j OpenAPI3规范
1.5.x~2.0.0<Knife4j 2.0.0>=Knife4j 4.0.0
2.0~2.2Knife4j 2.0.0 ~ 2.0.6>=Knife4j 4.0.0
2.2.x~2.4.0Knife4j 2.0.6 ~ 2.0.9>=Knife4j 4.0.0
2.4.0~2.7.x>=Knife4j 4.0.0>=Knife4j 4.0.0
>= 3.0>=Knife4j 4.0.0>=Knife4j 4.0.0

Swagger2规范OpenAPI3规范的说明

nife4j版本Swagger2规范OpenAPI3规范说明
1.0~1.9.6springfox 2.9.2Knife4j的前身,名称为swagger-bootstrap-ui
1.9.6~2.0.5springfox 2.9.2
2.0.6~2.0.9springfox 2.10.5
3.0.0~3.0.3springfox 3.0.3过度版本,建议开发者不要使用
4.0.0~springfox 2.10.5>=springdoc-openapi 1.6.9Swagger2规范稳定使用springfox2.10.5保持不变。开发者应该尽早迁移到OpenAPI3规范上来,请参考4.x升级文档

三、使用

1.引入依赖

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

2.修改配置文件application.yml

# springdoc-openapi项目配置
springdoc:
  swagger-ui:
    path: /swagger-ui.html
    tags-sorter: alpha
    operations-sorter: alpha
  api-docs:
    path: /v3/api-docs
  group-configs:
    - group: 'default'
      paths-to-match: '/**'
      packages-to-scan: com.xiaominfo.knife4j.demo.web
# knife4j的增强配置,不需要增强可以不配
knife4j:
  enable: true
  setting:
    language: zh_cn

3.编写配置类

package com.sky.config;
​
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 通过knife4j生成接口文档
 * @return
 */
​
@Configuration
@Slf4j
public class Knife4jConfiguration {
    /**
     * 管理端接口文档
     * @return
     */
    @Bean
    public GroupedOpenApi adminApi() {
        log.info("准备生成接口文档");
        return GroupedOpenApi.builder()  // 创建了一个api接口的分组
                .group("管理端接口")         // 分组名称
                .pathsToMatch("/admin/**")  // 接口请求路径规则
                .build();
    }
    /**
     * 用户端接口文档
     * @return
     */
    @Bean
    public GroupedOpenApi userApi() {
        log.info("准备生成接口文档");
        return GroupedOpenApi.builder()  // 创建了一个api接口的分组
                .group("用户端接口")         // 分组名称
                .pathsToMatch("/user/**")  // 接口请求路径规则
                .build();
    }
    @Bean
    public OpenAPI openAPI(){
        return new OpenAPI()
                .info(new Info()
                        .title("苍穹外卖项目接口文档")
                        .description("苍穹外卖项目接口文档")
                        .version("v1")
                        .contact(new Contact().name("robin").email("robin@gmail.com"))
                        .license(new License().name("Apache 2.0").url("http://springdoc.org"))
                );
​
    }
​
}

其中pathsToMatch用于匹配对应的接口,其匹配的是接口的url地址

然后在WebMVCConfiguration中设置静态资源映射

    /**
     * 设置静态资源映射
     * @param registry
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始设置静态资源映射");
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

4.编写User类用作模型

package com.mcode.knife4jdemo.entity;
​
import io.swagger.v3.oas.annotations.media.Schema;
​
/**
 * ClassName: User
 * Package: com.mcode.knife4jdemo.entity
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
@Schema(description = "用户实体")
public class User {
    @Schema(description = "用户名称")
    private String userName;
    @Schema(description = "密码")
    private String password;
    @Schema(description = "邮箱")
    private String email;
​
    @Schema(description = "年龄")
    private int age;
​
​
    public String getUserName() {
        return userName;
    }
​
    public void setUserName(String userName) {
        this.userName = userName;
    }
​
    public String getPassword() {
        return password;
    }
​
    public void setPassword(String password) {
        this.password = password;
    }
​
    public String getEmail() {
        return email;
    }
​
    public void setEmail(String email) {
        this.email = email;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    public User() {
    }
​
    public User(String userName, String password, String email, int age) {
        this.userName = userName;
        this.password = password;
        this.email = email;
        this.age = age;
    }
}

5.编写控制器

package com.mcode.knife4jdemo.controller;
​
import com.mcode.knife4jdemo.entity.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
​
/**
 * ClassName: IndexController
 * Package: com.mcode.knife4jdemo.controller
 * Description:
 *
 * @Author: robin
 * @Version: v1.0
 */
@RestController
@Tag(name = "首页")
@RequestMapping("/admin/index")
public class IndexController {
    @Operation(summary = "获取用户")
    @GetMapping("/getUser")
    public User getUser( @Parameter(name = "userName",description = "用户名称",in = ParameterIn.QUERY)String userName) {
        return new User(userName, "123456", "123@qq.com", 18);
    }
    @Operation(summary = "新增用户")
    @PostMapping("/addUser")
    public Boolean addUser(@RequestBody  User user) {
        return true;
    }
}

运行项目,访问:http://ip:port/doc.html

解决方法

配置完如上之后,发现仍然不行,还是报错。

然后忽然想起在三小时前看到的一篇文章:Knife4j文档请求异常(基于SpringBoot3,查找原因并解决)-CSDN博客

跟着他的思路,F12打开控制台准备进行debug,发现报出如下错误:

img

大致意思是JSON返回了一个token,继续从网络的响应查找:

img

发现响应码(200)正常,并且返回格式为json,查看响应内容:

img

相应内容是一长串字符串,而不是Json数据

最后发现是之前设置过一个消息转换器,将Date类型转换为yyyy-MM-dd HH:mm格式去显示,消息转换器将JSON数据不正常解析

于是将消息转换器注释掉,便正常显示了:

img

如果还想保留消息转换器,让后端返回正确的时间数据格式,那么可以调整消息转换器列表中转换器的顺序,代码如下:

    /**
     * 扩展消息转换器,将日期类型从列表转换为时间戳
     * 这个是导致knife4j不能正常显示的罪魁祸首,特别要注意添加的位置
     * @param converters 消息转换器列表
     */
    @Override
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        jackson2HttpMessageConverter.setObjectMapper(new JacksonObjectMapper());
        converters.add(converters.size()-1,jackson2HttpMessageConverter);
    }

参考文章

官方文档(快速开始):快速开始 | Knife4j

官方文档(详细介绍):3.1 增强模式 | Knife4j

Spring Boot3整合knife4j(swagger3)-阿里云开发者社区

https://www.cnblogs.com/vic-tory/p/17773531.html

Knife4j文档请求异常(基于SpringBoot3,查找原因并解决)-CSDN博客

https://www.cnblogs.com/slankka/p/11437034.html

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值