最近在打fat-jar包时,出现一个问题,运行fat-jar时报错:
2024-03-08 10:08:08.772 WARN [Thread-5] c.k.s.f.ExternalFuncClassLoader : 创建了未包含任何路径的自定义类加载器实例
2024-03-08 10:08:08.781 INFO [Thread-5] c.k.s.d.DataSourceConnectionPool : Calcite连接池初始化完成![连接池最大连接数:10,最大空闲数:5,最小空闲数:3,等待时间:PT3S]
java.sql.SQLException: No suitable driver found for jdbc:h2:file:C:\Users\yingxu.zhao\JsonQuery;MODE=MySQL;DB_CLOSE_DELAY=-1;AUTO_RECONNECT=TRUE;AUTO_SERVER=TRUEat java.sql.DriverManager.getConnection(DriverManager.java:689)at java.sql.DriverManager.getConnection(DriverManager.java:270)at com.kanyun.sql.util.H2Utils.<clinit>(H2Utils.java:38)at com.kanyun.sql.core.column.JsonTableColumnFactory.loadTableColumnInfo(JsonTableColumnFactory.java:124)at com.kanyun.ui.JsonQuery.initConfig(JsonQuery.java:88)at com.kanyun.ui.AsyncInitializer.run(AsyncInitializer.java:40)at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-5" java.lang.RuntimeException: java.lang.NullPointerExceptionat com.kanyun.ui.AsyncInitializer.run(AsyncInitializer.java:61)at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerExceptionat com.kanyun.sql.util.H2Utils.execQuery(H2Utils.java:47)at com.kanyun.sql.core.column.JsonTableColumnFactory.loadTableColumnInfo(JsonTableColumnFactory.java:124)at com.kanyun.ui.JsonQuery.initConfig(JsonQuery.java:88)at com.kanyun.ui.AsyncInitializer.run(AsyncInitializer.java:40)... 1 more
以上报错内容是使用maven-shade-plugin插件打包的,而换了maven-dependency-plugin打包也是同样的报错。
但是代码在IDEA中运行是没有问题的,报错提示的是找不到H2数据库驱动,查找打好包的fat-jar,里面是包含H2的驱动的。
这就很奇怪了,驱动明明在就是无法获取链接
然后找到一篇文章
java - No suitable driver found when exporting to a JAR-file? - Stack Overflow
里面的提问者,提到了他的应用里面同时使用了PostgreSQL和Mysql,由于数据库驱动使用了SPI机制,而打包时驱动的META-INF/services/java.sql.Driver并覆盖了,导致只能加载一个META-INF/services/java.sql.Driver。此时想到其实我的应用里面也有两个驱动 Calcite和H2。
然后就想到maven-shade-plugin是可以合并配置文件的。
找到以下文章:
使用Maven构建的可执行Jar无法在运行时解析多个数据库驱动程序的依赖关系 - IT屋-程序员软件开发技术分享社区
最终maven-shade-plugin配置如下:
<!--将项目的所有依赖项合并到单个可执行的JAR文件中,注意与maven-assembly-plugin插件的区别--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-shade-plugin</artifactId><version>3.5.2</version><executions><execution><phase>package</phase><goals><goal>shade</goal></goals></execution></executions><configuration><!--原始jar名称:xx.jar,最终输出名称 true:xx-shaded.jar false:xx.jar并修改原始名称为original-xx.jar--><shadedArtifactAttached>true</shadedArtifactAttached><!--生成名为dependency-reduced-pom.xml,这个POM文件去掉了原始pom中已被包含的进fat-jar的依赖项--><createDependencyReducedPom>true</createDependencyReducedPom><!-- 解决插件打包后运行报错:Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes--><filters><filter><artifact>*:*</artifact><excludes><exclude>META-INF/*.SF</exclude><exclude>META-INF/*.DSA</exclude><exclude>META-INF/*.RSA</exclude></excludes></filter></filters><!--自动移除项目中没有使用到的依赖,以此来最小化 jar 包的体积--><!--<minimizeJar>true</minimizeJar>--><transformers><!-- 添加入口类 --><transformerimplementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"><manifestEntries><!-- 入口类 --><Main-Class>${main-class}</Main-Class></manifestEntries></transformer><transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer"><!-- 合并服务,多个数据库驱动并存的情况不合并的话,H2驱动会报错(No suitable driver found for jdbc:h2:file)因为程序包含两个数据库驱动,Calcite和H2 --><resource>META-INF/services/java.sql.Driver</resource></transformer></transformers><artifactSet><!--默认所有的依赖都会被解压并平铺到最终的fat-jar中,这里指定要排除的依赖--><excludes><!--<exclude>*:hutool-all</exclude>--></excludes></artifactSet></configuration></plugin>