Java 为WAR文件强制自定义类加载器?

Java 为WAR文件强制自定义类加载器?,java,jakarta-ee,classloader,war,Java,Jakarta Ee,Classloader,War,是否有一种标准方法(即,由一些Java/J2EE/etc.spec定义)为Java Servlet容器提供一个自定义类加载器,该容器应用于加载WAR文件 在一个新项目中,我们正在使用web服务扩展一个大型商业Java软件包(Foo),这需要一些部署灵活性(作为单独的服务等)。特别是,我们希望避免在每个WAR文件中包含所有Foo软件依赖项Jar文件的必要性,因为它们数量众多、很大,并且随着补丁/错误修复版本的开发而不断变化。类似地,必须将所有依赖项复制到每个Servlet容器的“lib”目录中是非

是否有一种标准方法(即,由一些Java/J2EE/etc.spec定义)为Java Servlet容器提供一个自定义类加载器,该容器应用于加载WAR文件

在一个新项目中,我们正在使用web服务扩展一个大型商业Java软件包(Foo),这需要一些部署灵活性(作为单独的服务等)。特别是,我们希望避免在每个WAR文件中包含所有Foo软件依赖项Jar文件的必要性,因为它们数量众多、很大,并且随着补丁/错误修复版本的开发而不断变化。类似地,必须将所有依赖项复制到每个Servlet容器的“lib”目录中是非常不可取的

理想情况下,我想告诉Java应用服务器,这些WAR文件必须使用我将提供的自定义类加载器加载,该加载器将自动包含Foo软件依赖项JAR。类似这样的内容(在Java伪代码中):

公共类MyWarFileClassLoader扩展了ClassLoader{
受保护的URLClassLoader urlcl;
公共MyWarFileClassLoader(文件warFile){
文件installDir=System.getEnv(“FOO_HOME”);
List fooEntries=新文件(installDir,“jars”).listFiles(“*.jar”);
添加(新文件(installDir,“资源”);
fooEntries.add(warFile);
this.urlcl=新的URLClassLoader(fooEntries);
}
公共类findClass(字符串名称){
返回此.urlcl.findClass(名称);
}
}
如果没有标准的方法来实现这一点,那么是否有一种简单的方法来实现多个WAR文件的相同目标,而不考虑目标Servlet容器

[编辑]


换句话说:是否有一种通用模式允许WAR文件在运行时管理自己的依赖项,而不是依赖Servlet容器配置?当然,我可以让WAR文件清单包含一个
类路径
属性,但是这些条目在构建时仍然是“硬编码”的,而不是在运行时自动检测到的。

没有标准方法强制在Java EE应用程序中使用特定的自定义类加载器,从预定义的源加载类。但是,可以在JavaEE应用程序中绑定库,以便多个模块(包括驻留在WAR中的web模块)可以加载和访问绑定库中的类

JavaEE规范允许企业应用程序部署(一个
.ear
文件)在库部署目录中捆绑库;默认情况下,这是
.ear
文件中的
lib
目录。然后,这些库可由
.ear
文件根目录下的多个web模块(位于不同的
.war
文件中)使用。Java EE 6规范的相关部分是第EE 8.2.1节,其中说明了以下内容:

.ear
文件可能包含一个目录,其中包含打包在JAR文件中的库。
.ear
文件的部署描述符的
库目录
元素包含此目录的名称。如果未指定
库目录
元素,或者
.ear
文件不包含部署描述符,则使用名为
lib
的目录。空的
库目录
元素可用于指定没有库目录

此目录(但不是子目录)中扩展名为
.jar
的所有文件必须可用于EAR文件中打包的所有组件,包括应用程序客户端。这些库可以使用本文描述的任何技术引用与应用程序捆绑或单独安装的其他库

需要注意的是,所有符合JavaEE的应用服务器(WebLogic/WebSphere/JBoss等)都将支持使用捆绑库部署EAR文件。但是,有些servlet容器(如Tomcat和Jetty)不符合整个JavaEE规范;此类容器不支持EAR文件的部署


如果servlet容器中的多个web模块需要访问这些库(由于容器的选择或对WAR文件的偏好),那么您应该依赖servlet容器对共享库的支持来部署WAR文件,而不使用这些库。JavaEE规范在这方面没有强制要求使用已安装的库。一些容器比其他容器更好地支持共享库,因为它们支持版本化的共享库(部署的应用程序可能只使用多个版本中的一个版本),而其他容器(如Tomcat)则不支持共享库。

谢谢您提供的信息,Vinet,非常有趣。我将细化我的问题,特别提到Servlet容器,因为我们不需要一个完整的AppServer。@maerics,我的答案将继续是一样的,只是您可能依赖于Thajar清单中的
扩展列表
属性来允许加载共享库(仍将以适用于每台服务器的方式安装在服务器中)。您可能需要阅读JavaEE6规范中关于库支持的完整部分(第8.2节)。