我使用 Java 开发了一个 Web 应用程序。当我将它部署到我的应用程序服务器(Jetty、Tomcat、JBoss、GlassFish 等)时会引发错误。我可以在堆栈跟踪中看到此错误消息:
java.lang.ClassNotFoundException
或者
java.lang.NoClassDefFoundError
这是什么意思,我该如何解决?
这是什么意思?
首先,让我们看看 的含义java.lang.ClassNotFoundException
:
当应用程序尝试通过其字符串名称加载类时抛出:
- 类中的
forName
方法Class
。- 类中的
findSystemClass
方法ClassLoader
。- 类中的
loadClass
方法ClassLoader
。但找不到具有指定名称的类的定义。
通常,在尝试以这种形式手动打开连接时会发生这种情况:
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)中。
考虑到某些第三方库依赖于其他第三方库,因此您必须将它们全部添加到 WEB-INF/lib 中才能使应用程序正常工作。一个很好的例子是 RichFaces 4 库,您必须在其中手动下载和添加外部库。
Maven用户注意:除非您将库设置为provided
、test
或,否则不会遇到这些问题system
。如果设置为provided
,您有责任在类路径中的某处添加库。您可以在此处找到有关依赖范围的更多信息:依赖机制简介
如果必须在将部署在您的应用程序服务器上的多个应用程序之间共享该库,例如两个应用程序的 MySQL 连接器,还有另一种选择。不要部署两个带有各自 MySQL 连接器库的 war 文件,而是将此库放在服务器应用程序的公共库文件夹中,这将使该库位于所有已部署应用程序的类路径中。
此文件夹与应用程序服务器不同。
<tomcat_home>
/lib<jboss_home>
/独立/lib该类必须存在于 WEB-INF/classes 下或位于 WEB-INF/lib 下的 .jar 文件中。确保确实如此。
同样的问题发生在我身上。
可能您的一个库正在使用一些不可用的内部类
在您的 lib 或 maven 依赖项 pom.xml 中。
这意味着您已经分析了错误日志并识别了这些类,然后将所有依赖项导入 maven 或 lib 文件夹中。
我用同样的方法修复了这个错误。
因为我的一些库在内部使用了 activation.jar 和 json.jar。