Java 从lib文件夹中的类扩展WAR中的抽象类

Java 从lib文件夹中的类扩展WAR中的抽象类,java,tomcat,web-applications,servlets,classloader,Java,Tomcat,Web Applications,Servlets,Classloader,我想启用以下场景: 我的web应用程序(WAR文件)单独部署在Tomcat上 我的web应用程序以IFace接口和AbstractIFace抽象基实现的形式为扩展提供API,其类文件部署在WAR文件中 应用程序的扩展以JAR文件的形式交付,放置在类路径的某个位置(即WAR外部) 我编译了一个concretiface类,该类扩展了AbstractIFace,并将其打包到一个JAR中。我将JAR放在$TOMCAT_HOME/lib中,并在webapps中部署了WAR。当我在战争中从servlet

我想启用以下场景:

  • 我的web应用程序(WAR文件)单独部署在Tomcat上

  • 我的web应用程序以
    IFace
    接口和
    AbstractIFace
    抽象基实现的形式为扩展提供API,其类文件部署在WAR文件中

  • 应用程序的扩展以JAR文件的形式交付,放置在类路径的某个位置(即WAR外部)

我编译了一个
concretiface
类,该类扩展了
AbstractIFace
,并将其打包到一个JAR中。我将JAR放在
$TOMCAT_HOME/lib
中,并在
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应用程序中,类路径是隔离的。web应用程序看不到彼此的类,Tomcat看不到应用程序的类,应用程序看不到Tomcat的内部类(只有Servlet API之类的公开接口)

Web应用程序应该是自包含的,并且独立于容器

最简单的方法是重新打包war文件,使其也包含插件


其他选项包括转到企业存档,这可能具有相互依赖性,或者将web服务器嵌入到应用程序中(与其他方式相反)。

您的API类位于WAR中,并且$TOMCAT_HOME/lib中的类无法访问。
一个建议是将您的API-a IFace和AbstractIFaceClass分开,以分开jar,并将其放置在$TOMCAT_HOME/lib中。

如果您能够清晰地将这些部分分开,那么这是可行的。但是,如果AbstractIFaceClass依赖于web应用程序中的许多其他内容(您也必须移动所有这些可传递的依赖项),则不会很好地工作。如果您不能分离这些内容,则说明您的设计很糟糕。我理解这一点,谢谢。但很明显,应用程序可以访问容器类,而问题恰恰相反:查看错误,它是关于
AbstractIFace
,意思是
ConcreteIFace
确实被找到并正在加载。是吗?是的,应用程序可以看到(一些)容器类,但不能看到其他的容器类。ConcreteIFace是容器的一部分(现在您已将其移动到lib),因此它无法看到其父类(它是应用程序的一部分)。当你编译它的时候,你也必须让它访问应用程序中的类,对吗?如果你想使用TOMCAT_HOME/lib,你必须像@Slavus建议的那样,把所有的东西分解成一个jar文件。