我正在尝试使用tomcat连接池,并在我的应用程序context.xml文件中定义它。
<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中定义的,该类放在我的应用程序库文件夹中。对我来说也很好。但是这里据说,带驱动程序类的jar只应该放在tomcat文件夹中。
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为null,驱动程序类试图通过Class.forName(driverClassName)加载。据我所知,在本例中,驱动程序类是用与BasicDataSource相同的类加载器实例加载的。这是StandardClassLoader,如果我的jar是tomcat,它将加载这个类。在我的示例中,会抛出异常并使用Thread.currentThread().getContextClassLoader(),它是WebappClassLoader实例,可以从webapp库加载类,并且可以加载类。所以我很困惑。为什么说,如果我使用容器资源中的数据源,就必须将我的驱动程序类放在tomcat库中。
请解释一下,谢谢
发布于 2013-10-17 15:43:11
Tomcat自动将容器托管连接池添加到jaxaz.sql.DataSource类型的每个资源中。提供此池的库( Commons的包重命名版本)由共享类加载器(在默认配置中与公共加载程序相同)加载。池实现需要能够加载配置好的JDBC驱动程序,并且共享(和公共)加载程序在web应用程序类加载程序中没有可见性。因此,带有JDBC驱动程序的JAR需要在$CATALINA_BASE/lib目录中才能加载。
但是,从r754776开始,如果不能加载指定的驱动程序,DBCP将返回到线程的上下文类加载器。如果将线程上下文类加载器设置为web应用程序的类加载器,则可以加载驱动程序。此更改包含在DBCP 1.3和1.4之前,这意味着它包含在5.5.30开始、6.0.27开始和每个7.0.x发布中。它也将出现在每一个8.0.x版本中。
使用MarkMail对查询卷进行相当不科学的研究表明,Tomcat用户邮件列表中的ClassNotFoundException问题有所减少,但同样可能是因为人们对这个问题有更多的了解。
我想最基本的问题是这可靠吗?如果当线程上下文类加载器是web应用程序类加载器时,DataSource总是被实例化,那么它将是可靠的。对这些资源的访问是通过JNDI进行的,这取决于正确设置线程上下文类加载器。如果不是,JNDI将无法找到web应用程序资源。在此基础上,这应该是可行的。
全局资源(显然)仍然需要JDBC驱动程序位于$CATALINA_HOME/lib中。
如果JDBC驱动程序JAR存在于$CATALINA_HOME/lib and WEB-INF/lib中,则可能会导致问题。如果web应用程序试图转换到特定于数据库的对象,那么就会失败,因为这将是尝试将由共享加载器加载的类转换为web应用程序类加载器加载的同名类,而该类总是会失败。
因此,简而言之:
WEB-INF/lib和$CATALINA_[HOME|BASE]/lib中使用JDBC驱动程序。6.0.27开始,可以将JDBC驱动程序打包到web应用程序中,而且一切都将继续工作。为最初的错误/不完整的答案道歉。这不是我第一次完全忘记我所做的承诺,我怀疑这不会是最后一次。
https://stackoverflow.com/questions/19431102
复制相似问题