带有 JDBC 的 tomcat 6.0 抛出 ClassNotFoundException com.mysql.jdbc.Connection

Posted

技术标签:

【中文标题】带有 JDBC 的 tomcat 6.0 抛出 ClassNotFoundException com.mysql.jdbc.Connection【英文标题】:tomcat 6.0 with JDBC throws ClassNotFoundException com.mysql.jdbc.Connection 【发布时间】:2011-04-05 23:26:00 【问题描述】:

我已经通过 Eclipse 成功连接到 mysql 数据库而没有涉及到 tomcat,所以至少这是一些不错的进展。但是当我从我的网页(Tomcat 6.0)尝试时,它会抛出一个错误。我按照教程,阅读文档并查看了无数论坛,但现在已经 2 天了。

让我们一步一步看。我正在运行tomcat 6.0.26,我已经安装了 MySQL,并且运行良好。

1.将连接器j 放置到CATALINA_HOME/lib

makun /home/makun/tomcat/apache-tomcat-6.0.26/lib ->ls | grep -i mysql*
mysql-connector-java-5.1.13-bin.jar

2。告诉 Tomcat 我的 MySQL 信息。 (声明资源需求)并映射用于调用 db test 的 servlet(即 /tmp_db_test)

(/WEB-INF/web.xml)

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <servlet>
        <servlet-name>DatabaseTest</servlet-name>
        <servlet-class>com.masatosan.tmp.Tmp</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>DatabaseTest</servlet-name>
        <url-pattern>/tmp_db_test</url-pattern>
    </servlet-mapping>

    <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/MasatoDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
    </resource-ref>


</web-app>

3.配置tomcat资源工厂。

(CATALINE_HOME/conf/context.xml)

<!-- Default set of monitored resources -->
<WatchedResource>WEB-INF/web.xml</WatchedResource>

<!-- Masato added the line below to setup JDBC -->
<Resource 
    name="jdbc/MasatoDB" 
    auth="Container" 
    type="javax.sql.DataSource"
    maxActive="100" 
    maxIdle="30" 
    maxWait="10000"
    username="masato" 
    password="mypass" 
    driverClassName="com.mysql.jdbc.Driver"
    url="jdbc:mysql://localhost:3306/masatosan"/>

4.创建调用 servlet 的 JSP 页面 这只是一个带有发送 POST 请求的按钮的页面。

 <html>
    <head>
    </head>
    <body>
    <!-- click button to send request to servlet -->
    <form method="POST" action="tmp_db_test">
    <p><input type="submit" value="Submit" name="submit_button"></p>
    </form>
    </body>
    </html> 

5.最后实现尝试连接 MySQL 数据库的 servlet。 (Tmp.java)

package com.masatosan.tmp;

import java.io.IOException;
//import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.masatosan.dateformatter.DateFormatter;
import com.masatosan.logger.Logger;
import com.mysql.jdbc.Connection;


public class Tmp extends HttpServlet 


    private Connection conn;

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
        try 
            Context initCtx = new InitialContext();
            Context envCtx = (Context) initCtx.lookup("java:comp/env");
            DataSource ds = (DataSource)envCtx.lookup("jdbc/MasatoDB");

            conn = (Connection) ds.getConnection();

            String template = "INSERT INTO users(username, email, password, created_date) VALUES (?, ?, ?, ?);";
            PreparedStatement inserter = conn.prepareStatement(template);
            inserter.setString(1, "test_username");
            inserter.setString(2, "test@test.com");
            inserter.setString(3, "test_pass");
            inserter.setString(4, DateFormatter.formatToSqlDate(null));

            inserter.executeUpdate();
        
        catch(Exception e) 
            Logger.log(e.getMessage());
        
        finally 
            if(conn != null) 
                try 
                    conn.close();
                 catch (SQLException e) 
                    Logger.log(e.getMessage());
                
            
        
    

我编译了 Tmp.java 并放入 /WEB-INF/classes/com/masatosan/tmp/Tmp.class

然后重新部署Tomcat服务器并在浏览器上测试。当我点击提交按钮时,我收到错误:

javax.servlet.ServletException: Error instantiating servlet class com.masatosan.tmp.Tmp
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    java.lang.Thread.run(Thread.java:619)

root cause

java.lang.NoClassDefFoundError: Lcom/mysql/jdbc/Connection;
    java.lang.Class.getDeclaredFields0(Native Method)
    java.lang.Class.privateGetDeclaredFields(Class.java:2291)
    java.lang.Class.getDeclaredFields(Class.java:1743)
    org.apache.catalina.util.DefaultAnnotationProcessor.processAnnotations(DefaultAnnotationProcessor.java:181)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    java.lang.Thread.run(Thread.java:619)

root cause

java.lang.ClassNotFoundException: com.mysql.jdbc.Connection
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1516)
    org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1361)
    java.lang.Class.getDeclaredFields0(Native Method)
    java.lang.Class.privateGetDeclaredFields(Class.java:2291)
    java.lang.Class.getDeclaredFields(Class.java:1743)
    org.apache.catalina.util.DefaultAnnotationProcessor.processAnnotations(DefaultAnnotationProcessor.java:181)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    java.lang.Thread.run(Thread.java:619)

如果您需要更多说明,请告诉我。

编辑

根据建议,connectorj jar 保留在 CATALINA_HOME/lib 中

我已将 Tmp.java 中的导入行修复为:

import java.sql.Connection 而不是com.mysql.jdbc.Connection

现在点击浏览器上的提交按钮时出现新错误。

Cannot create JDBC driver of class '' for connect URL 'null'

我试图跟踪日志:

makun /home/makun/tomcat/apache-tomcat-6.0.26/logs ->tail -f localhost.2010-08-30.log

当我单击提交按钮时,什么也没有出现。 (我认为这是正确的日志,因为其他有错误的页面会在日志中输出消息)

更新

我不知道为什么,但是当我尝试将异常堆栈跟踪打印到我的日志时它开始工作。我一直在从管理器页面重新加载 Tomcat 很多次,这可能会导致一些奇怪的事情并得到相同的错误页面,即使我已经进行了代码更改(它吓坏了我 404 和 500 可以互换。我希望我能提供确切的细节但是我在问题部分中描述的步骤似乎有效(在修复了一些建议的事情之后)

【问题讨论】:

【参考方案1】:

此异常告诉您它在加载/实例化期间调查 servlet 的声明字段以收集注释缓存的任何注释时找不到 com.mysql.jdbc.Connection 类。

您应该使用java.sql.Connection,而不是com.mysql.jdbc.Connection。事实上,所有您的 JDBC 代码应该导入/使用java(x).sql 接口/类。否则,您的 JDBC 代码与所使用的 DB 和 JDBC 驱动程序紧密耦合,并且不能与其他 DB 和/或驱动程序重用,这违反了 JDBC 的整个抽象概念。


也就是说,将Connection 声明为 servlet 的实例变量是一个非常糟糕的主意。 servlet 仅被实例化一次,并在 web 应用程序的生命周期内在 所有 请求之间共享。您应该在 尽可能短的 范围内获取和关闭连接,即已经在同一个方法块中。更好的是,将所有 JDBC 逻辑放在一个可重用的 DAO 类中,您只需将其导入 servlet。

另见:

Servlet instantiation, session variables and multithreading Basic JDBC-DAO tutorial(第二部分包含针对 JSP/Servlet 的示例)

【讨论】:

我注意到我也可以导入 2 个不同的连接。非常令人困惑......我已经修复并得到了新的错误,所以我会看看错误指示是什么。 (也添加到我的编辑部分) @Adam:此异常是在加载/实例化 servlet 期间引发的,而不是在加载资源期间引发的。 @masato:这是一个包装/嵌套的异常。阅读根本原因的服务器日志。它包含有关问题根本原因的详细信息。很有可能您应该将 MySQL JDBC 驱动程序保留在它所属的 Tomcat/lib 中,并删除 /WEB-INF/lib 中的那个。 @BalusC:感谢您的提示!我会尽快在编辑中发布结果。 @masato:你在 Eclipse 中使用 Tomcat 插件吗?一切都登录到 Eclipse 控制台。您可能需要切换显示的控制台。 @BalusC:不,我没有使用插件。我手动编译java类并将它们放在相应的WEB-INF中,然后从管理器页面(localhost:8080/manager/html/reload?path=/head_first)重新加载tomcat服务器。【参考方案2】:

找不到“com.mysql.jdbc.Connection”的类应该在mysql-connector-java-5.1.13-bin.jar中。我认为tomcat 应该能够从$CATALINE_HOME/lib 中获取它。所以从你所说的“应该”工作......

也许检查用户 tomcat 是否以对文件具有读取权限的身份运行? jar 文件是否已损坏 - 可能是文本模式下的 ftp 损坏?您确定 CATALINA_HOME 是 /home/makun/tomcat/apache-tomcat-6.0.26 - 也许检查 tomcat 启动脚本以查看它是否配置为其他位置?

如果仍然无法正常工作,您可以尝试将 jar 文件放入 web-inf/lib。

【讨论】:

感谢您的提示!放入 /WEB-INF/lib 确实进行了一些更改,但找不到类异常的根本原因是由于导入了错误的连接包(请参阅编辑部分)

以上是关于带有 JDBC 的 tomcat 6.0 抛出 ClassNotFoundException com.mysql.jdbc.Connection的主要内容,如果未能解决你的问题,请参考以下文章

使用 spring-data-jpa 和完整的 tomcat-jdbc 配置的 spring boot 为 ResetAbandonedTimer 抛出 java.lang.ClassNotFound

带有纯 JDBC-JNDI:javax.naming.NameNotFoundException 的 Tomcat 8.5:名称 [jdbc/KDB] 未绑定在此上下文中。找不到 [jdbc]

中间件怎么部署jar包

放弃连接的警告 - 使用 tomcat 7 抛出 PooledConnection 异常

JDBC 超时不抛出 SQLTimeoutException

java.lang.UnsupportedClassVersionError: com/mysql/cj/jdbc/Driver : Unsupported major.minor version 5