我想启用以下方案:
我的Web应用程序(WAR文件)已自行部署在Tomcat上
我的Web应用程序以IFace
接口和AbstractIFace
抽象基础实现的形式提供扩展API,其类文件部署在WAR文件中
应用程序的扩展作为JAR文件提供,放置在类路径中的某个位置(即WAR外部)
我编译了一个ConcreteIFace
类,它扩展了AbstractIFace
并将其打包成JAR。我将JAR放在$TOMCAT_HOME/lib
中,并在webapps
中部署了WAR。当我从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
?
甚至可以实现我在开始时提出的场景吗?如果是这样,怎么样?
答案 0 :(得分:2)
在Web应用程序中,类路径是隔离的。 Web应用程序无法看到彼此的类,Tomcat无法看到应用程序的类,应用程序无法看到Tomcat的内部类(只有Servlet API等公开的接口)。
Web应用程序应该是独立的,并且与容器无关。
最简单的方法是重新打包war文件以包含插件。
其他选项包括上升到企业档案,这些档案可能具有相互依赖性,或者将Web服务器嵌入应用程序中(而不是相反)。
答案 1 :(得分:0)
您的API类位于WAR中,$ TOMCAT_HOME / lib中的类无法访问它们。 一个建议是将您的API-a IFace和AbstractIFaceClass分开来分隔jar并将它放在$ TOMCAT_HOME / lib。