在 /WEB-INF/lib 中使用 JBDC 4.0 驱动程序,但仍然需要 Class#forName() 来加载它
Posted
技术标签:
【中文标题】在 /WEB-INF/lib 中使用 JBDC 4.0 驱动程序,但仍然需要 Class#forName() 来加载它【英文标题】:Using JBDC 4.0 driver in /WEB-INF/lib and yet Class#forName() is still required to load it 【发布时间】: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 打开连接和查询数据库是个坏主意... 我知道,我只是在做一些尝试 【参考方案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.0
和JDBC 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 会有所帮助。
【讨论】:
以上是关于在 /WEB-INF/lib 中使用 JBDC 4.0 驱动程序,但仍然需要 Class#forName() 来加载它的主要内容,如果未能解决你的问题,请参考以下文章
如何在eclipse中使用Ivy + IvyDE将不同的jar放到lib和web-inf/lib中
如何签署放置在 maven 中 /WEB-INF/lib 目录中的 JAR 文件