这是什么意思?
首先我们来看看java.lang.ClassNotFoundException的含义:
当应用程序尝试通过其字符串名称加载类时抛出:
-
Class 类中的 forName 方法。
-
ClassLoader 类中的 findSystemClass 方法。
-
ClassLoader 类中的 loadClass 方法。
但找不到具有指定名称的类的定义。
通常,在尝试以这种形式手动打开连接时会发生这种情况:
String jdbcDriver = "...'; //name of your driver
Class.forName(jdbcDriver);
或者当你引用一个属于外部库的类时,奇怪当应用服务器尝试部署应用时,这个类无法加载。
让我们看看java.lang.NoClassDefFoundError的含义(强调我的):
如果 Java 虚拟机或 ClassLoader 实例尝试加载类的定义(作为正常方法调用的一部分或作为使用 new 表达式创建新实例的一部分)并且没有定义可以找到类。
在编译当前执行的类时,搜索到的类定义存在,但找不到该定义。
最后一部分说明了一切:该类在编译时存在,即当我通过我的 IDE 编译应用程序时,但它在运行时不可用,即在部署应用程序时。
我该如何解决?
在 Java Web 应用程序中,您的应用程序使用的所有第三方库都必须放在 WEB-INF/lib 文件夹中。确保所有必要的库(罐子)都放在那里。您可以轻松检查:
- <webapp folder>
- WEB-INF
- lib
+ jar1
+ jar2
+ ...
- META-INF
- <rest of your folders>
此问题通常出现在 JDBC 连接 jar(MySQL、Derby、MSSQL、Oracle 等)或 Web MVC 框架库(如 JSF 或 Spring MVC)中。
考虑到一些第三方库依赖于other第三方库,所以你必须在WEB-INF/lib中添加所有的才能使申请工作。一个很好的例子是 RichFaces 4 库,where you have to download and add the external libraries manually。
Maven 用户注意:除非您将库设置为 provided、test 或 system,否则不会遇到这些问题。如果设置为provided,您有责任在类路径中的某处添加库。您可以在此处找到有关依赖范围的更多信息:Introduction to the Dependency Mechanism
如果库必须在将部署在您的应用服务器上的多个应用程序之间共享,例如两个应用程序的 MySQL 连接器,还有另一种选择。不要部署两个带有各自 MySQL 连接器库的 war 文件,而是将此库放在服务器应用程序的公共库文件夹中,这将使该库位于所有已部署应用程序的类路径中。
此文件夹与应用服务器不同。
- Tomcat 7/8:
<tomcat_home>/lib
- JBoss 7/Wildfly:
<jboss_home>/standalone/lib