【问题标题】:JDBC Error when moving JAR from $HOME/jre/lib/ext to Gradle将 JAR 从 $HOME/jre/lib/ext 移动到 Gradle 时出现 JDBC 错误
【发布时间】:2017-03-25 03:51:28
【问题描述】:

我的团队在 $JAVA_HOME/jre/lib/ext/ 文件夹中有我们应用程序的 com.mysql.jdbc.Driver jar,但我正在尝试删除对 JDK 的这种依赖,以便使用 Gradle 创建更可重复的构建。

我将驱动程序添加到我的 build.gradle 中,您可以在我的依赖项顶部看到它:

dependencies {
        compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.+'
        compile group: 'com.notnoop.apns', name: 'apns', version: '1.0.0.Beta6'
        compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'
        compile group: 'com.google.code.gson', name: 'gson', version: '1.7.2'
        compile group: 'net.sf.jazzy', name: 'jazzy', version: '0.5.2-rtext-1.4.1'
        compile group: 'org.apache.lucene', name: 'com.springsource.org.apache.lucene.search.spell', version: '2.4.1'
        compile group: 'com.rabbitmq', name: 'com.springsource.com.rabbitmq.client', version: '1.8.1'
        compile group: 'com.sun.xml', name: 'com.springsource.com.sun.xml.bind', version: '2.2.0'
        compile group: 'com.sun.xml.rpc', name: 'jaxrpc-impl', version: '1.1.3_01'
        compile group: 'com.rabbitmq', name: 'amqp-client', version: '3.6.5'
        testCompile group: 'junit', name: 'junit', version: '4.11'
        compile group: 'com.mashape.unirest', name: 'unirest-java', version: '1.3.1'
        compile fileTree(dir: 'local_lib', include: '*.jar')
}

从 $JAVA_HOME/jre/lib/ext/ 中删除 jar 并将其放入 gradle 后,我在尝试访问数据库后在 Catalina 日志中收到此错误:

database.BaseDbao.getConnection - We could not create any connection.
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot load JDBC driver class 'com.mysql.jdbc.Driver'
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1136)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
    at database.BaseDbao.getConnection(BaseDbao.java:116)
    at database.UserDbao.getAuthorizedResultBean(UserDbao.java:357)
    at database.Dbao.getAuthorizedResultBean(Dbao.java:3635)
    at AuthServlet.doPost(AuthServlet.java:71)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at servlets.filters.servletContextFilter.doFilter(servletContextFilter.java:11)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1130)
    ... 22 more
Dbao.getAuthorizationResultBean() Error - Cannot load JDBC driver class 'com.mysql.jdbc.Driver'
LoginFailed for :suburbantest:because ::10.0.0.22

任何见解都将受到高度赞赏!

【问题讨论】:

  • 如果我将 JAR 放在 Tomcat/lib 文件夹中,它可以工作。这当然与将 JAR 放在 ext 文件夹中存在相同的问题,因为它使 Web 应用程序依赖于特定的 Tomcat JAR。为什么它似乎在除了 Gradle 之外的所有地方都有效?
  • 你确定是mysql的jdbc驱动吗? jdk 附带一个 Apache derby jdbc 驱动程序。确保您复制了正确的文件。
  • lib/ext 已弃用,将在 Java 9 中移除,不要往里面放东西,和放 tomcat lib 文件夹是不一样的。

标签: java mysql jdbc gradle java-8


【解决方案1】:

您在 Tomcat 的配置中定义您的数据源,而不是将其放入您的应用程序配置中。

Tomcat 具有类加载器的层次结构。您可以在其website 上阅读有关它的信息,但长话短说,有三个有趣的类加载器:JDK 类加载器(引导程序)、Tomcat 类加载器(系统)和您的应用程序的类加载器(实际上还有更多,但让很简单)。

将驱动程序的 jar 放入 $JAVA_HOME/jre/lib/ext/ 时,将其添加到 JDK 类加载器。当你将它添加到 tomcat/lib 时,你将它添加到 Tomcat 类加载器。当您在应用程序的 gradle 中定义它时,您会将其添加到应用程序类加载器中。

由于您的案例中的数据源配置位于 Tomcat 的配置中,因此它将仅搜索 JDK 和 Tomcat 的类加载器。

一种解决方案是在您的应用程序中定义数据源配置(为什么在 Tomcat 中需要它?您是否有多个使用相同数据源的战争?)

【讨论】:

  • 我已经确认有多个 WAR 使用相同的数据源。那么我可以将那个 mysql JAR 扔到所有其他 WAR 中,然后在 Tomcat 中获取我们的数据源定义吗?
  • 这取决于您想要实现的目标。您希望每个 WAR 复制数据源还是希望它们重用它?
  • 如果你想重用它,你应该把它的配置留在Tomcat的配置中(和以前一样),把驱动留在Tomcat的类加载器(tomcat/lib)中。你不能把它放在应用程序的 gradle 文件中。
  • 我相信我们希望在迁移到 AWS 之前重复使用它。将 Tomcat 配置和类加载器保留在 tomcat/lib 中,同时保留 gradle 依赖项是否有意义?在我们当前使用共享 Tomcat 的环境中,gradle 依赖项将被忽略,但当我们迁移到云端时,gradle 依赖项将接管。
  • 它可能会毫无问题地工作,但可能会出现一些理论问题。 Tomcat 工作“最后一个父”,这意味着当你的应用程序寻找一个类时,它首先检查应用程序的类加载器,然后是共享的类加载器,最后是引导程序。因此,如果您的应用程序将从驱动程序的 jar 中创建类,它将与共享的类不同(注意我在这里谈论的是类,而不是对象)。由于您的应用不直接使用这些类,因此不会有问题,但如果它开始使用它们,可能会有问题。
猜你喜欢
  • 2018-05-04
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多