Tim*_*dik 2 java tomcat jdbc classloader tomcat7
我正在尝试使用tomcat jdbc连接池,我在我的应用程序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,它放在我的应用程序lib文件夹中.它对我来说很好.但是在这里说,带有驱动程序类的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为null,并且尝试通过加载驱动程序类Class.forName(driverClassName).据我所知,在这种情况下,驱动程序类正在加载相同的类加载器实例BasicDataSource.这就是StandardClassLoader,如果我的jar在tomcat库中,它将加载该类.在我的情况下,抛出并Thread.currentThread().getContextClassLoader()使用异常,这是WebappClassLoader实例,可以从webapp lib加载类,它可以.所以我很困惑.为什么说,如果我使用容器资源中的数据源,我必须将我的驱动程序类放在tomcat库中.
请解释一下,谢谢
Tomcat自动将容器管理的连接池添加到每个类型的资源jaxaz.sql.DataSource.提供此池的库(Commons DBCP的包重命名版本)由共享类加载器加载(在默认配置中与公共加载器相同).池实现需要能够加载已配置的JDBC驱动程序,并且共享(和公共)加载器无法查看Web应用程序类加载器.因此,带有JDBC驱动程序的JAR需要位于$CATALINA_BASE/lib目录中,以便可以加载它.
但是,从r754776开始,如果DBCP无法加载指定的驱动程序,它将回退到Thread的上下文类加载器.如果线程上下文类加载器设置为Web应用程序的类加载器,则可以加载驱动程序.此更改包括在内部DBCP 1.3和1.4之后,这意味着它包含在5.5.30向前,6.0.27向前和每个7.0.x版本中.它也将在每个8.0.x版本中.
使用MarkMail对查询量进行相当不科学的观察表明,ClassNotFoundExceptionTomcat用户邮件列表中的问题有所减少,但同样可能是人们更加意识到这个问题.
我想根本问题是这个可靠吗?如果在DataSource线程上下文类加载器是Web应用程序类加载器时始终实例化,那么它将是可靠的.访问这些资源是通过的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站立6.0.27开始,就可以打包在Web应用程序的JDBC驱动程序,一切都将仍然工作.抱歉最初的错误/不完整的答案.这不是我第一次完全忘记我做出的提交,我怀疑它不会是最后一次.
| 归档时间: | 
 | 
| 查看次数: | 4381 次 | 
| 最近记录: |