【问题标题】:Using JBDC 4.0 driver in /WEB-INF/lib and yet Class#forName() is still required to load it在 /WEB-INF/lib 中使用 JBDC 4.0 驱动程序,但仍然需要 Class#forName() 来加载它
【发布时间】:2013-06-27 22:43:58
【问题描述】:


我正在尝试通过 jsp 访问我的数据库,我有以下代码:

<% 
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String value = "vuoto";


        Class.forName("com.mysql.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/onlinebookstore", "root", "sesame");
        Statement statement = connection.createStatement();
        ResultSet result = statement.executeQuery("SELECT * FROM users WHERE email = '" + username + "' " + "AND" + " password = '" + password + "'");
        if(result.next()) {
           value = "eccomi";
        }
        connection.close();
%>

我不明白为什么需要使用 Class.forName,因为我从 JDBC 4.0 中读到它没有必要,但如果我删除该语句,它就不起作用。在我的库中,我添加了 MySQL JDBC Driver -mysql-connector-java-5.1.23-bin.jar

【问题讨论】:

  • 我想知道有没有人告诉你从 JSP 打开连接和查询数据库是个坏主意...
  • 我知道,我只是在做一些尝试

标签: java mysql database jsp jdbc


【解决方案1】:

我将忽略问题中公开的在 JSP 中编写 Java 代码的不良编程实践——当你想使用原始 Java 代码而不是 HTML 拦截 HTTP 请求/响应时,你应该真正开始习惯创建沙箱 servlet .


至于具体问题,这确实是意料之中的行为。对于初学者,JDBC 4.0 驱动程序是使用ServiceLoader API 自动加载的。我们来看看它的javadoc;这是相关性的摘录(javadoc的第5段;强调我的):

如果一个特定的具体提供者类在多个配置文件中被命名,或者在同一个配置文件中被多次命名,那么重复的将被忽略。命名特定提供程序的配置文件不需要与提供程序本身位于相同的 jar 文件或其他分发单元中。 必须可以从最初查询配置文件的同一个类加载器访问提供程序;请注意,这不一定是实际加载文件的类加载器。

负责查询JAR 的/META-INF/services 文件夹中的配置文件的是servletcontainer 本身,而不是webapp。所以,本质上,JAR 必须放在 servletcontainer 自己的运行时类路径中,而不是 webapp 自己的运行时类路径中。 webapp 的 /WEB-INF/lib 文件夹被 webapp 的运行时类路径覆盖,而不是 servletcontainer 的,因此基本上是错误的位置。

您在任何地方都没有说明正在使用的 servletcontainer,但根据您在其他一些问题中发现的堆栈跟踪,我猜它是 Apache Tomcat。在这种情况下,必须将 JDBC 驱动 JAR 文件放在 Tomcat 自己的 /lib 文件夹中,以便正确利用 ServiceLoader 机制自动加载的 JDBC 驱动。

【讨论】:

    【解决方案2】:

    尽管 jar 是类路径的一部分,但您编写的代码都没有引用 Driver 类。我相信 Driver 类在其静态块之一中向 JDBC 注册自身,因此它必须由类加载器加载,才能执行该静态块,并且 JDBC api 才能使用该驱动程序类。 Class.forName 加载类,因此需要它。

    另外,正如有人回答并出于某种原因删除了该帖子,只有与 JDBC 4.0 兼容的驱动程序不需要 Class.forName,但较旧的驱动程序需要。

    【讨论】:

      【解决方案3】:

      JDBC 驱动程序mysql-connector-java-5.1.23-bin.jar 是类型 4 驱动程序,它 符合JDBC 3.0JDBC 4.0 规范。

      但要利用 JDBC 4.0 规范,您需要java 6 或更高版本。

      如果您有较旧的 java,它将考虑 JDBC 3.0 规范并且不会自动加载 Driver

      您可以在下载的 Zip 文件中提供的文档中找到此信息。

      【讨论】:

      • 我有java7,那我看不懂
      【解决方案4】:

      在我的环境中,此代码在没有 Class.forName 的情况下有效。

      public class Test {
        public static void main(String[] args) {
      
          //Class.forName("com.mysql.jdbc.Driver");
          Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "sesame");
      
          // do some query
        }
      }
      

      所以我认为你的问题可能是类加载器问题。 如果您使用的是 Tomcat,this answer 会有所帮助。

      【讨论】:

        猜你喜欢
        • 2016-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 2016-05-01
        • 1970-01-01
        • 2014-10-20
        相关资源
        最近更新 更多