tl; dr:我们的Spring Boot jar中的类似乎看到了捆绑罐中的类,但它们的内容似乎无法实现。为什么呢?
我们的主要产品是网络应用,但所有业务逻辑都集中在核心mac-guffin-api.jar
中。 mac-guffin-api.jar
不是一个Spring Boot项目,但有一个名为net.initech.api.Configuration
的Spring Java配置文件初始化所有服务和存储库等。我们使用MS SQL Server作为我们的后端sqljdbc42:jar
驱动程序。
我们需要编写一个需要从API项目中重用相同业务逻辑的ETL,因此我们创建了一个Spring {4}导入mac-guffin-api.jar
作为Maven依赖项的Spring Boot Spring Batch项目。 ETL的配置(net.initech.etl.Configuration
)导入的API配置没有问题(我可以从控制台日志中看到它),但是当API配置创建数据库连接时它无法找到司机。
Caused by: java.lang.ClassNotFoundException: 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:246)
... 113 more
但是,我可以清楚地看到包含驱动程序的JAR存在。 ETL jar的内容是( Nb: mac-guffin-api.jar
和sqljdbc42-4.2.jar
不解压缩,它们是ETL jar中的jar:)
mac-guffin-etl.jar
|
+- org.springframework.boot.loader...
|
+- BOOT-INF
|
+- classes
| |
| +- com.initech.etl.Main.class
| |
| +- com.initech.etl.Configuration.class
|
+- lib
|
+- mac-guffin-api.jar
| |
| +- com.initech.api.Configuration.class
|
+- sqljdbc42-4.2.jar
|
+- com.microsoft.sqlserver.jdbc.SQLServerDriver.class
显然,类ETL的配置类可以看到包含的JAR的内容(或者至少是API jar的内容),但是他们的API jar似乎无法看到SQL Server JDBC jar中的com.microsoft.sqlserver.jdbc.SQLServerDriver.class
。
我甚至可以在Spring上下文实例化之前做Class.forName( "com.microsoft.sqlserver.jdbc.SQLServerDriver.class" )
并且它没有问题。
这是类加载器的限制吗?这是因为API项目不是Spring Boot吗?是因为缺少配置参数?这里发生了什么?
答案 0 :(得分:1)
在您的配置中的某个地方,您最终得到了用作值的类名:
'com.microsoft.sqlserver.jdbc.SQLServerDriver'
用单引号括起来。通常,正在加载的类名称不带引号,双引号或单引号。
这可以解释为什么你能够加载类,但API jar不能。检查配置/构建文件以确定驱动程序名称的设置位置。
我能得到像你这样的信息的唯一方法:
Caused by: java.lang.ClassNotFoundException: 'com.microsoft.sqlserver.jdbc.SQLServerDriver'
而不是:
Caused by: java.lang.ClassNotFoundException: com.microsoft.sqlserver.jdbc.SQLServerDriver
是故意要求在名称中加载带单引号的类。例如:
import java.lang.*;
public class myclass {
public static void test(String thename) {
System.out.println("trying " + thename);
try {
myclass test = (myclass) myclass.class
.getClassLoader()
.loadClass(thename)
.newInstance();
System.out.println(test.toString());
} catch (Exception e){
System.out.println("failed to load " + thename);
e.printStackTrace();
}
}
public static void main(String[] args) {
test("my.package.itwontexist");
test("'my.package.itwontexist'");
}
}
输出:
trying my.package.itwontexist
failed to load my.package.itwontexist
java.lang.ClassNotFoundException: my.package.itwontexist
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at myclass.test(myclass.java:10)
at myclass.main(myclass.java:20)
trying 'my.package.itwontexist'
failed to load 'my.package.itwontexist'
java.lang.ClassNotFoundException: 'my.package.itwontexist'
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at myclass.test(myclass.java:10)
at myclass.main(myclass.java:21)
答案 1 :(得分:1)
您可能从配置中获取驱动程序值,例如
my.driver ='com.microsoft.sqlserver.jdbc.SQLServerDriver'
该配置使用单引号返回值。请检查配置文件。
答案 2 :(得分:0)
看起来你错过了MANFIEST.MF文件,它指示Spring如何加载嵌套的jar。这是Spring文档的一个示例层次结构。您可以了解如何配置它by going here。
MANIFEST.MF应该包含这个(对于下面的结构):
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: com.mycompany.project.MyApplication
Start-Class
是您进入申请的入口点
Main-Class
是加载嵌套jar所需的Loader。
示例结构:
example.war
|
+-META-INF
| +-MANIFEST.MF
+-org
| +-springframework
| +-boot
| +-loader
| +-<spring boot loader classes>
+-WEB-INF
+-classes
| +-com
| +-mycompany
| +-project
| +-YourClasses.class
+-lib
| +-dependency1.jar
| +-dependency2.jar
+-lib-provided
+-servlet-api.jar
+-dependency3.jar