ToB企服应用市场:ToB评测及商务社交产业平台

标题: SpringBoot 3.x 结合 Swagger3 (Knife4j )踩坑实录 [打印本页]

作者: 悠扬随风    时间: 2024-6-22 13:36
标题: SpringBoot 3.x 结合 Swagger3 (Knife4j )踩坑实录
SpringBoot 3.x + Swagger3 踩坑实录

我的是springboot 版本是:3.2.2
  1. <parent>
  2.         <groupId>org.springframework.boot</groupId>
  3.         <artifactId>spring-boot-starter-parent</artifactId>
  4.         <version>3.2.2</version>
  5.         <relativePath/>
  6.     </parent>
复制代码
官方文档

官方文档(快速开始):
1,快速开始 | Knife4j (xiaominfo.com)
https://doc.xiaominfo.com/docs/quick-start
官方文档(详细配置):
2, 增强模式 | Knife4j (xiaominfo.com)
https://doc.xiaominfo.com/docs/features/enhance
3,版本参考
Knife4j版本参考 | Knife4j (xiaominfo.com)
如果自己springboot 是 2.X.X 的版本,可参考官方文档,进行差别的依赖配置
以下是一些常见的Spring Boot版本及其对应的Knife4j版本兼容推荐:

Knife4j在之前的版本更新中,逐渐提供了一些服务端适配的增强特性功能。
但是开发者应该明白,不管是Swagger2规范还是OpenAPI3规范,Knife4j的最新版本的纯Ui版本,是可以适配Spring Boot所有版本的。
如果你不考虑使用Knife4j提供的服务端增强功能,引入Knife4j的纯Ui版本没有任何限制。只需要考虑差别的规范即可
其实大部门的报错一般都是依赖问题(比如依赖缺少,版本辩论,版本不合)
错误操纵

依赖

网上帖子一般说的结合 knife4j(Swagger3), 添加的依赖一般都只有knife4j。 但是这个是不对的,依赖没有完全,并且就算配置好yaml ,启动访问也会出错。完整依赖可看下面精确部门。
  1.          <dependency>
  2.             <groupId>com.github.xiaoymin</groupId>
  3.             <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
  4.             <version>4.4.0</version>
  5.         </dependency>
复制代码
yaml 配置

改的地方为:packages-to-scan:  com.example.eip.controller(自己项目的controller 目录)
其他地方基本上不用改。
  1. springdoc:
  2.   swagger-ui:
  3.     path: /swagger-ui.html
  4.     tags-sorter: alpha
  5.     operations-sorter: alpha
  6.   api-docs:
  7.     path: /v3/api-docs
  8.   group-configs:
  9.     - group: 'default'
  10.       paths-to-match: '/**'
  11.       #生成文档所需的扫包路径,一般为启动类目录
  12.       packages-to-scan: com.example.eip.controller
  13. #knife4j配置
  14. knife4j:
  15.   #是否启用增强设置
  16.   enable: true
  17.   #开启生产环境屏蔽
  18.   production: false
  19.   #是否启用登录认证
  20.   basic:
  21.     enable: true
  22.     username: admin
  23.     password: 123456
  24.   setting:
  25.     language: zh_cn
  26.     enable-version: true
  27.     enable-swagger-models: true
  28.     swagger-model-name: 用户模块
复制代码
这个时候访问是会报错:http://localhost:8069/doc.html#/home
报错信息解决


报错信息一: void io.swagger.v3.oas.models.OpenAPI.(io.swagger.v3.oas.models.SpecVersion)
这个报错才是访问不到的根本原因
原因:
  1. jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoSuchMethodError: 'void io.swagger.v3.oas.models.OpenAPI.<init>(io.swagger.v3.oas.models.SpecVersion)'
  2.         at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1104)
  3.         at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
  4.         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
复制代码
报错信息二:No static resource favicon.ico  这个报错影响使用访问doc文档,但是不好看
原因:spring boot3项目中浏览器中访问报错找不到favicon.ico
目前springfox已经停止维护了。最近在升级底层框架时看到spring官方推荐使用springdoc,
这个情况有人去Github提了issue,但是Spring开发老哥说了这个不是bug,那就只能自己解决了。
  1. org.springframework.web.servlet.resource.NoResourceFoundException: No static resource favicon.ico.
  2.         at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:585)
  3.         at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:52)
  4.         at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
  5.         at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
  6.         at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
  7.         at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
  8.         at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
  9.         at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
  10.         at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
  11.         at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
复制代码
精确流程

这里先提供一下目录文件:

添加精确依赖

完整的添加所有的依赖,每个依赖都不能少,少就可能出错(可解决报错一)
  1.                     io.swagger.core.v3            swagger-core            2.2.20                        <dependency>
  2.             <groupId>com.github.xiaoymin</groupId>
  3.             <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
  4.             <version>4.4.0</version>
  5.         </dependency>                            org.springdoc            springdoc-openapi-starter-webmvc-api            2.2.0                            org.springframework.boot            spring-boot-configuration-processor            true                                    com.fasterxml.jackson.module            jackson-module-jakarta-xmlbind-annotations            2.13.3                        javax.xml.bind        jaxb-api        2.4.0-b180830.0359        
复制代码
添加yaml 配置
  1. springdoc:
  2.   swagger-ui:
  3.     path: /swagger-ui.html
  4.     tags-sorter: alpha
  5.     operations-sorter: alpha
  6.   api-docs:
  7.     path: /v3/api-docs
  8.   group-configs:
  9.     - group: 'default'
  10.       paths-to-match: '/**'
  11.       #生成文档所需的扫包路径,一般为启动类目录
  12.       packages-to-scan: com.example.eip.controller
  13. #knife4j配置
  14. knife4j:
  15.   #是否启用增强设置
  16.   enable: true
  17.   #开启生产环境屏蔽
  18.   production: false
  19.   #是否启用登录认证
  20.   basic:
  21.     enable: true
  22.     username: admin
  23.     password: 123456
  24.   setting:
  25.     language: zh_cn
  26.     enable-version: true
  27.     enable-swagger-models: true
  28.     swagger-model-name: 用户模块
复制代码
配置过滤静态资源
  1. import jakarta.servlet.http.HttpServletRequest;
  2. import jakarta.servlet.http.HttpServletResponse;
  3. import org.springframework.boot.SpringBootConfiguration;
  4. import org.springframework.http.HttpStatus;
  5. import org.springframework.web.servlet.HandlerInterceptor;
  6. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  7. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  8. /**
  9. * @Classname FaviconConfiguration
  10. * @Description 添加配置文件,处理favicon.ico请求
  11. * @Version 1.0.0
  12. * @Date 2024/6/11 13:39
  13. * @Created by Administrator
  14. */
  15. @SpringBootConfiguration
  16. public class FaviconConfiguration implements WebMvcConfigurer {
  17.     @Override
  18.     public void addInterceptors(InterceptorRegistry registry) {
  19.         registry.addInterceptor(new HandlerInterceptor() {
  20.             @Override
  21.             public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
  22.                 if (!"GET".equalsIgnoreCase(request.getMethod()) || !request.getRequestURI().toString().equals("/favicon.ico")) {
  23.                     return true;
  24.                 }
  25.                 response.setStatus(HttpStatus.NO_CONTENT.value()); // 设置状态码为204 No Content
  26.                 return false;
  27.             }
  28.         }).addPathPatterns("/**");
  29.     }
  30. }
复制代码
这个时候就可以访问到文档:http://localhost:8069/doc.html#/home
增强模式

编写配置文件

这个部门注意是提供一些项目信息或者个人的信息
  1. import io.swagger.v3.oas.models.OpenAPI;
  2. import io.swagger.v3.oas.models.ExternalDocumentation;
  3. import io.swagger.v3.oas.models.info.Contact;
  4. import io.swagger.v3.oas.models.info.Info;
  5. import io.swagger.v3.oas.models.info.License;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. /**
  9. * @Classname SwaggerConfig
  10. * @Description TODO
  11. * @Version 1.0.0
  12. * @Date 2024/6/11 14:16
  13. * @Created by Administrator
  14. */
  15. @Configuration
  16. public class SwaggerConfig {
  17.     @Bean
  18.     public OpenAPI swaggerOpenAPI(){
  19.         return new OpenAPI()
  20.                 .info(new Info().title("标题")
  21.                         // 信息
  22.                         .contact(new Contact().name("作者").email("邮箱").url("地址"))
  23.                         // 简介
  24.                         .description("我的API文档")
  25.                         // 版本
  26.                         .version("v1")
  27.                         // 许可证
  28.                         .license(new License().name("Apache 2.0").url("http://springdoc.org")))
  29.                 .externalDocs(new ExternalDocumentation()
  30.                         .description("外部文档")
  31.                         .url("https://springshop.wiki.github.org/docs"));
  32.     }
  33. }
复制代码
配置后的结果:

配置启动链接接口地点

每次都要打开浏览器输入地点访问不友好,我们在启动类似进行地点配置
启动类上优化 或者 编写配置类
第一种方式: 编写配置类(推荐使用)
创建文件:DocumentationConfig
  1. import io.micrometer.common.util.StringUtils;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.core.env.Environment;
  5. import java.net.InetAddress;
  6. import java.net.UnknownHostException;
  7. /**
  8. * @Classname DocumentationConfig
  9. * @Description TODO
  10. * @Version 1.0.0
  11. * @Date 2024/6/11 15:28
  12. * @Created by Administrator
  13. */
  14. @Configuration
  15. @Slf4j
  16. public class DocumentationConfig {
  17.     public void logApplicationStartup(Environment env) {
  18.         String protocol = "http";
  19.         if (env.getProperty("server.ssl.key-store") != null) {
  20.             protocol = "https";
  21.         }
  22.         String serverPort = env.getProperty("server.port");
  23.         String contextPath = env.getProperty("server.servlet.context-path");
  24.         if (StringUtils.isBlank(contextPath)) {
  25.             contextPath = "/doc.html";
  26.         } else {
  27.             contextPath = contextPath + "/doc.html";
  28.         }
  29.         String hostAddress = "localhost";
  30.         try {
  31.             hostAddress = InetAddress.getLocalHost().getHostAddress();
  32.         } catch (UnknownHostException e) {
  33.             log.warn("The host name could not be determined, using `localhost` as fallback");
  34.         }
  35.         log.info("""
  36.                         ----------------------------------------------------------
  37.                         \t应用程序“{}”正在运行中......
  38.                         \t接口文档访问 URL:
  39.                         \t本地: \t\t{}://localhost:{}{}
  40.                         \t外部: \t{}://{}:{}{}
  41.                         \t配置文件: \t{}
  42.                         ----------------------------------------------------------""",
  43.                 env.getProperty("spring.application.name"),
  44.                 protocol,
  45.                 serverPort,
  46.                 contextPath,
  47.                 protocol,
  48.                 hostAddress,
  49.                 serverPort,
  50.                 contextPath,
  51.                 env.getActiveProfiles());
  52.     }
  53. }
复制代码
第二种方式:启动类上优化
  1. import io.micrometer.common.util.StringUtils;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.mybatis.spring.annotation.MapperScan;
  4. import org.springframework.boot.Banner;
  5. import org.springframework.boot.SpringApplication;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. import org.springframework.core.env.Environment;
  8. import java.net.InetAddress;
  9. import java.net.UnknownHostException;
  10. @SpringBootApplication
  11. @MapperScan("com.mijiu.mapper")
  12. @Slf4j
  13. public class SpringbootTemplateApplication {
  14.     public static void main(String[] args) {
  15.         SpringApplication app = new SpringApplication(SpringbootTemplateApplication.class);
  16.         Environment env = app.run(args).getEnvironment();
  17.         app.setBannerMode(Banner.Mode.CONSOLE);
  18.         logApplicationStartup(env);
  19.     }
  20.     private static void logApplicationStartup(Environment env) {
  21.         String protocol = "http";
  22.         if (env.getProperty("server.ssl.key-store") != null) {
  23.             protocol = "https";
  24.         }
  25.         String serverPort = env.getProperty("server.port");
  26.         String contextPath = env.getProperty("server.servlet.context-path");
  27.         if (StringUtils.isBlank(contextPath)) {
  28.             contextPath = "/doc.html";
  29.         } else {
  30.             contextPath = contextPath + "/doc.html";
  31.         }
  32.         String hostAddress = "localhost";
  33.         try {
  34.             hostAddress = InetAddress.getLocalHost().getHostAddress();
  35.         } catch (UnknownHostException e) {
  36.             log.warn("The host name could not be determined, using `localhost` as fallback");
  37.         }
  38.         log.info("""
  39.                         ----------------------------------------------------------
  40.                         \t应用程序“{}”正在运行中......
  41.                         \t接口文档访问 URL:
  42.                         \t本地: \t\t{}://localhost:{}{}
  43.                         \t外部: \t{}://{}:{}{}
  44.                         \t配置文件: \t{}
  45.                         ----------------------------------------------------------""",
  46.                 env.getProperty("spring.application.name"),
  47.                 protocol,
  48.                 serverPort,
  49.                 contextPath,
  50.                 protocol,
  51.                 hostAddress,
  52.                 serverPort,
  53.                 contextPath,
  54.                 env.getActiveProfiles());
  55.     }
  56. }
复制代码
配置后的结果:点击可以直接访问

如果代码写的有问题,欢迎各人评论交流,进行指点!!!
也希望各人点个关注哦~~~~~~~~

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4