我该把JDBC驱动程序放在哪里,以便Tomcat的连接池能够使用?

30

所以我已经找出了我的错误,现在只是想了解到底发生了什么。我正在使用Apache Tomcat版本7.0.32。我正在使用这个教程来设置JDBC连接池。在我的META-INF文件夹中,我创建了一个context.xml文件,并将其放置在其中。

<?xml version="1.0" encoding="UTF-8"?>

<Context>
    <Resource type="javax.sql.DataSource" name="jdbc/gmustudent"
        factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost:3306/official"
        username="root" password="root"
        maxActive="100" maxIdle="20" minIdle="15" initialSize="15" maxWait="10000" />
</Context>

当我写这段代码时,出现了以下错误

WARNING: Unexpected exception resolving reference
java.sql.SQLException: com.mysql.jdbc.Driver
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:254)
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:699)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:631)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:485)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:143)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
    at org.apache.tomcat.jdbc.pool.DataSourceFactory.createDataSource(DataSourceFactory.java:539)
    at org.apache.tomcat.jdbc.pool.DataSourceFactory.getObjectInstance(DataSourceFactory.java:237)
    at org.apache.naming.factory.ResourceFactory.getObjectInstance(ResourceFactory.java:143)
    at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:304)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:843)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:154)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:831)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:168)
    at org.apache.catalina.core.NamingContextListener.addResource(NamingContextListener.java:1061)
    at org.apache.catalina.core.NamingContextListener.createNamingContext(NamingContextListener.java:671)
    at org.apache.catalina.core.NamingContextListener.lifecycleEvent(NamingContextListener.java:270)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5173)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:246)
    ... 29 more
Oct 31, 2012 11:23:25 AM org.apache.catalina.core.NamingContextListener addResource
WARNING: Failed to register in JMX: javax.naming.NamingException: com.mysql.jdbc.Driver
Oct 31, 2012 11:23:25 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-8086"]
Oct 31, 2012 11:23:25 AM org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
Oct 31, 2012 11:23:25 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 794 ms

只有当我在我的context.xml文件中包含这个语句时才会出现这个错误。当我删除它时就没有错误了。

factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 

我希望能确定我拥有它,因为在Apache Tomcat教程中它是必需的。

factory is required, and the value should be org.apache.tomcat.jdbc.pool.DataSourceFactory

然后我在SO上做了一些研究,发现有一篇帖子说如果你使用的是旧版的Tomcat,需要将这个jar添加到您的lib文件夹中。所以我添加了这个jar,现在它可以正常工作,但我想知道是什么原因导致我在指定factory时出错。还有,我正在使用最新版本的Tomcat,这个jar是什么东西,为什么几乎没有关于它的文档?如果有任何关于这里发生的事情的信息,将不胜感激。

2个回答

64
JDBC驱动程序必须对与数据源工厂本身相同的类加载器可见。数据源工厂库位于Tomcat自己的/lib文件夹中,因此由Tomcat的"common"类加载器加载。
您的问题听起来很像是将JDBC驱动程序放在了Web应用程序的/WEB-INF/lib目录中。Web应用程序的/WEB-INF/lib对"common"类加载器不可见。因此从技术上讲,您必须将JDBC驱动程序放置在Tomcat自己的/lib文件夹中(或者至少放置在可由/conf/catalina.properties中的common.loader设置指定的可配置路径中),以使其对数据源工厂可见。
或者,正如您尝试的那样,将数据源工厂复制到/WEB-INF/lib中也可以解决问题。Web应用程序的/WEB-INF/lib比Tomcat的/lib文件夹具有更高的类加载优先级。因此,如果在/WEB-INF/lib中找到数据源工厂,它将从那里加载。由于JDBC驱动程序也在那里,它将被看到。但是,这不是您具体问题的正确解决方案,这更像是一个解决方法,因此您不应该这样做。

没有专门针对这个问题的文档。然而,Tomcat Class Loader HOW-TO 可以帮助理解 Tomcat 中的类加载层次结构。

screen shot showing Tomcat folder with nested "lib" folder with nested JDBC driver .jar file

参见:


谢谢!谢谢!谢谢!你真的是最棒的!我理解你说的一切,以及我为什么会出现错误。唯一让我不明白的是“Tomcat自己的/lib”文件夹在哪里?我目前正在使用Eclipse,我的工作区中有两个文件夹:gmustudent和Servers。当我展开Servers时,我看到一个名为Tomcat v7.0 Server at localhost-config的文件夹,在其中有几个XML文件。我尝试将其放入该文件夹中,但那是一个巨大的错误!所以我很抱歉要问第二个问题,但是你所说的“Tomcat自己的/lib文件夹”是什么意思? - gmustudent
2
在本地磁盘文件系统上的Tomcat安装文件夹中。例如C:\path\to\apache-tomcat-7.0.30。这不应该从Eclipse内部进行管理。我回答中提到的/conf文件夹也在其中。 - BalusC
3
这是tomcat-jdbc.jar文件。 工厂值是完全限定类名,需要传递给Tomcat内部代码中的Class#forName(),以便它可以被加载和实例化。 是的,JDBC驱动程序JAR文件应该保存在Tomcat的/lib目录下(或者至少按照common.loader属性指定的路径)。 - BalusC
1
这真的是用户名/密码组合在JDBC URL中指定的给定DB上不被接受。注意大小写和空格。还要确保JDBC URL中的DB名称正确。JDBC驱动程序等都没问题。否则就不会到达你现在的这个点了。如果仍然无法解决,请联系主机支持。 - BalusC
你是最棒的!无法想象去找其他人寻求帮助,谢谢你! - gmustudent
显示剩余7条评论

0

我也遇到了同样的问题,你提供的解决方案对我没用。 我不得不将'mysql-connector-java-5.1.30-bin.jar'文件添加到我的lib文件夹中才能解决这个问题,因为我使用的是这个驱动程序 :) 谢谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接