> 技术文档 > 【原创】Knife4j从2.x升级到4.x版本升级方案和措施,并解决SpringBoot3.x无法显示knife4j文档问题,报No static resource swagger-resources_knife4j no static resource favicon.ico

【原创】Knife4j从2.x升级到4.x版本升级方案和措施,并解决SpringBoot3.x无法显示knife4j文档问题,报No static resource swagger-resources_knife4j no static resource favicon.ico


前言

这篇文章中我的项目是从Knife4j2.0.9升级到4.4.0。起因是群里有人说swagger打不开了,说是Fastjson转换器导致的问题,我就不信这个邪了,因为我的项目中也存在这个东西,也没听说会让swagger打不开。结果我运行项目后发现swagger还真打不开了!

报错内容为:

org.springframework.web.servlet.resource.NoResourceFoundException: No static resource swagger-resources.at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:585)at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:52)at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088)at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978)at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)

看了一下knife4j的文档才发现原来是版本不匹配了,SpringBoot3.x版本必须匹配Knife4j 4.x版本,我也确实把SpringBoot版本从2.x升级到3.4.2了。

这里我就说一下如何将Knife4j从2.0.9升级到4.4.0。因为我这是我自己的项目,且用到的Knife4j的功能并不是很多,如果有疏漏请大家补充

pom引用

  com.github.xiaoymin knife4j-spring-boot-starter 2.0.9   com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter 4.4.0 

pom引用需要改为新版本的,就连maven坐标都变了,这是大改。

配置文件application.yaml

#knife4j配置信息knife4j: # 是否开启增强模式,建议必须开启 enable: true setting: language: zh_cn # production改为true则会关闭knife4j和swagger所有文档 production: false ## 开启Swagger的Basic认证功能,默认是false basic: enable: true ## Basic认证用户名 username: admin ## Basic认证密码 password: 123456# springdoc-openapi项目配置springdoc: swagger-ui: path: /swagger-ui.html tags-sorter: alpha operations-sorter: alpha enabled: true api-docs: path: /v3/api-docs enabled: true group-configs: - group: \'default\' paths-to-match: \'/**\' packages-to-scan: 改为你的包名

注意,如果要彻底关闭knife4j用于生产环境,请改production的值为true,而不是将knife4j的enable改为false!

根据自己的情况修改配置文件

ControllerAdvice

没错!被这个注解修饰的类也需要修改,需要添加上@Hidden,来自包:import io.swagger.v3.oas.annotations.Hidden

@Hidden@ControllerAdviceclass ProjectExceptionHandler(

如果不加的话进入doc.html会报错,内容为:

jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoSuchMethodError: \'void org.springframework.web.method.ControllerAdviceBean.(java.lang.Object)\'at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1103)at Caused by: java.lang.NoSuchMethodError: \'void org.springframework.web.method.ControllerAdviceBean.(java.lang.Object)\'at org.springdoc.core.service.GenericResponseService.lambda$getGenericMapResponse$8(GenericResponseService.java:702)

注解

真正的修改大头来了,OpenAPI V3的对应的注解和之前swagger2的注解完全不同,这可要了老命咯

注解对比

​旧注解(Swagger2)​​ ​新注解(OpenAPI3)​​ 功能说明 @Api(类) @Tag(类) 定义接口分组或模块名称 @ApiOperation(方法) @Operation(方法) 描述接口功能 @ApiModelProperty(字段) @Schema(字段) 描述模型属性 @ApiParam(参数) @Parameter(参数) 描述请求参数 @ApiResponse(响应) @ApiResponse(响应) 描述接口响应(名称不变,包路径变化) @ApiModel(类) @Schema(类) 描述模型类

可以说是所有注解都改了,以至于项目中所有接口相关的都要改一遍,关键是注解里面的参数也变了,原来用value的,现在换成了title/name等等

全局批量替换

建议将这些注解和包引入全部全局批量替换一下,从字多的换到字少的

import io.swagger.annotations.ApiModelPropertyimport io.swagger.v3.oas.annotations.media.Schema@ApiModelProperty(value@Schema(titleimport io.swagger.annotations.ApiModelimport io.swagger.v3.oas.annotations.media.Schema@ApiModel(@Schema(name = import io.swagger.annotations.ApiOperationimport io.swagger.v3.oas.annotations.Operation@ApiOperation(value =@Operation(summary =import io.swagger.annotations.ApiParamimport io.swagger.v3.oas.annotations.Parameter@ApiParam@Parameterimport io.swagger.annotations.Apiimport io.swagger.v3.oas.annotations.tags.Tag

以上是我批量替换的内容,4行中第1行和第3行是原来的,分别替换为第2行和第4行

Api注解替换

还剩最后一个Api注解,我原来写的是@Api(tags = [AccountController.moduleName], value = AccountController.moduleName),但是现在要写@Tag(name = AccountController.moduleName),其中XXXController是动态的,没法全局批量替换,这里采用代码替换:

fun main() { val projectRoot = File(\"你的项目路径\") // 替换为实际项目路径 val fileExtension = \"Controller.kt\" projectRoot.walk() .filter { it.isFile && it.name.endsWith(fileExtension) } .forEach { file -> val className = file.nameWithoutExtension // 提取类名(如:UserController) val originalContent = file.readText(Charset.defaultCharset()) if (originalContent.contains(\"@Api\")) { val start = originalContent.indexOf(\"@Api\") val end = originalContent.indexOf(\")\", start) val newContent = originalContent.substring(0, start) + \"@Tag(name = $className.moduleName)\" + originalContent.substring(end+1) if (originalContent != newContent) {  file.writeText(newContent)  println(\"已更新文件:${file.absolutePath}\") } } }}

Kotlin代码相当简洁,连遍历递归都不用了

去掉基类注解

【转载】【问题记录】解决Knife4j 4.x版本在SpringBoot3.x版本中返回字段类型包含泛型,但是api文档中不显示泛型中字段的问题-CSDN博客

可以看我这篇文章,如果基类中存在@Schema注解,则其中的泛型会无法解析出正确的类型,只会显示出object类型

增加favicon.ico

如果没有favicon.ico进入doc.html后会报错,内容为:

org.springframework.web.servlet.resource.NoResourceFoundException: No static resource favicon.ico.at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:585)at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:52)at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088)at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978)at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)

虽然不影响页面显示,但是后端会提示报错信息,建议在resources下建立static目录,放入一个favicon.ico文件

完成效果

完成效果如下:

结语

对于我这个个人项目来说从Knife4j2.0.9升级到4.4.0就这些步骤,如果什么需要补充的地方,欢迎大家来评论区评论,或者来我的Q群(170618278)交流也行。也是没想到这个升级改动这么大,花费了我很长时间解决问题。

Knife4j的文档还是建议查看官网:https://doc.xiaominfo.com/docs/