我想启用以下场景:
我的 web 应用程序(WAR 文件)是自己部署在 Tomcat 上的
我的 Web 应用程序以
IFace
接口(interface)和AbstractIFace
抽象基础实现的形式为扩展提供 API,其类文件部署在 WAR 文件中应用程序的扩展作为 JAR 文件交付,放置在类路径中的某个位置(即 WAR 外部)
我编译了一个 ConcreteIFace
类,它扩展了 AbstractIFace
并将其打包到一个 JAR 中。我将 JAR 放在 $TOMCAT_HOME/lib
中,并将 WAR 部署在 webapps
中。当我尝试从 WAR 中的 servlet 执行以下操作时:
Class clazz = Class.forName("ConcreteIFace");
我得到以下堆栈跟踪:
java.lang.NoClassDefFoundError: AbstractIFace
java.lang.ClassLoader.defineClass1(Native Method)
java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
java.lang.ClassLoader.defineClass(ClassLoader.java:615)
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
java.net.URLClassLoader.access$000(URLClassLoader.java:58)
java.net.URLClassLoader$1.run(URLClassLoader.java:197)
java.security.AccessController.doPrivileged(Native Method)
java.net.URLClassLoader.findClass(URLClassLoader.java:190)
java.lang.ClassLoader.loadClass(ClassLoader.java:306)
java.lang.ClassLoader.loadClass(ClassLoader.java:247)
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:247)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1698)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
java.lang.Class.forName0(Native Method)
java.lang.Class.forName(Class.java:169)
com.backbase.sample.DummyServlet.service(DummyServlet.java:14)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
如果 ConcreteIFace
直接实现 IFace
而不是通过 AbstractIFace
,则会显示类似的堆栈跟踪
我的问题是:
因为所有必需的类都在应用程序类路径中,为什么我有
NoClassDefFound
?是否有可能实现我一开始提出的场景?如果是,怎么办?
最佳答案
在网络应用程序中,类路径是隔离的。 Web 应用程序看不到彼此的类,Tomcat 看不到应用程序的类,应用程序看不到 Tomcat 的内部类(只有公开的接口(interface),如 Servlet API)。
Web 应用程序应该是自包含且独立于容器的。
最简单的方法是重新打包 war 文件以包含插件。
其他选项包括进入企业文件,这可能具有相互依赖性,或者将网络服务器嵌入到应用程序中(而不是相反)。
关于java - 从 lib 文件夹中的类扩展 WAR 中的抽象类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11518984/