我想使用tomcat jdbc连接池,并在我的应用程序context.xml文件中定义它。通过资源(Tomcat 7)加载jdbc驱动程序
<Context>
<Resource auth="Container" name="jdbc/iup" type="javax.sql.DataSource"
maxActive="300" maxIdle="30" maxWait="20000"
username="${db.username}" password="${db.password}" driverClassName="net.sf.log4jdbc.DriverSpy"
url="jdbc:log4jdbc:sqlserver://${db.server};databaseName=${db.name}"/>
</Context>
类net.sf.log4jdbc.DriverSpy
在log4jdbc4-1.2.jar
,其被放置在我的申请LIB文件夹中定义。对我来说它工作得很好。但here据说,带驱动程序类的jar只能放在tomcat的lib文件夹中。
Tomcat使用它BasicDataSource
类加载驱动程序:
if (driverClassName != null) {
try {
try {
if (driverClassLoader == null) {
Class.forName(driverClassName);
} else {
Class.forName(driverClassName, true, driverClassLoader);
}
} catch (ClassNotFoundException cnfe) {
driverFromCCL = Thread.currentThread(
).getContextClassLoader().loadClass(
driverClassName);
}
} catch (Throwable t) {
String message = "Cannot load JDBC driver class '" +
driverClassName + "'";
logWriter.println(message);
t.printStackTrace(logWriter);
throw new SQLNestedException(message, t);
}
}
driverClassLoader
为空,而驱动程序类是尝试通过Class.forName(driverClassName)
被加载。据我所知,在这种情况下,驱动程序类正在加载与BasicDataSource
相同的类加载器实例。这是StandardClassLoader
,如果我的jar在tomcat库中,它将加载这个类。在我的情况下,抛出异常,并使用Thread.currentThread().getContextClassLoader()
,这是WebappClassLoader
实例,并可以从Web应用程序库中加载类,它会。所以我很困惑。为什么说,如果我从容器资源使用数据源,我必须将我的驱动程序类放在tomcat库中。
请解释一下,谢谢
我知道。从代码中可以看到,当通用加载程序无法加载驱动程序时,上下文类加载程序(指的是webapp classloader)会成功加载驱动程序。这就是为什么我很困惑 –
嗯。让我去挖掘源代码。你确定你在使用Tomcat 7吗?究竟是哪个版本? (Tomcat 8有上面的代码,但Tomcat 7没有 - 该源代码片段从哪里来?) –
我使用的是7.0.27版本。此外,我已经检查过版本6,并看到代码的相同部分 –