强制为 WAR 文件使用自定义类加载器?
是否有一种标准方法(即由某些 Java/J2EE/等规范定义)为 Java Servlet 容器提供自定义类加载器,该容器应用于加载 WAR 文件?
在一个新项目中,我们正在使用 Web 服务扩展大型商业 Java 软件包 (Foo),这需要一定的部署灵活性(作为单独的服务等)。特别是,我们希望避免在每个 WAR 文件中包含所有 Foo 软件依赖项 Jar 文件,因为它们数量众多、体积庞大,并且会随着我们开发的补丁/错误修复版本而变化。同样,非常不希望将所有依赖项复制到每个 Servlet 容器的“lib”目录中。
理想情况下,我想告诉 Java 应用程序服务器必须使用自定义类加载器加载这些 WAR 文件,我将提供该类加载器,该类加载器自动包含 Foo 软件依赖项 Jars。像这样的东西(在 Java 伪代码中):
public class MyWarFileClassLoader extends ClassLoader {
protected URLClassLoader urlcl;
public MyWarFileClassLoader(File warFile) {
File installDir = System.getEnv("FOO_HOME");
List<File> fooEntries = new File(installDir, "jars").listFiles("*.jar");
fooEntries.add(new File(installDir, "resources"));
fooEntries.add(warFile);
this.urlcl = new URLClassLoader(fooEntries);
}
public Class<?> findClass(String name) {
return this.urlcl.findClass(name);
}
}
如果没有标准方法来做到这一点,是否有一种简单的方法可以为多个 WAR 文件实现相同的目标,而不管目标 Servlet 容器如何?
[编辑]
换句话说:是否有一个通用模式允许 WAR 文件在运行时管理它们自己的依赖项,而不是依赖 Servlet 容器配置?当然,我可以让 WAR 文件清单包含一个 Class-Path 属性,但这些条目仍然在构建时“硬编码”,而不是在运行时自动检测。
Is there a standard way (i.e. defined by some Java/J2EE/etc. spec) to provide a custom class loader to a Java Servlet Container which should be used to load a WAR file?
On a new project we are extending a large commercial Java software package (Foo) with web services which requires some flexibility of deployment (as separate services, etc). In particular, we want to avoid the necessity to include in each WAR file all of the Foo software dependency Jar files as they are numerous, large, and will be changing with patch/bugfix releases as we develop. Similarly, it is highly undesirable to have to copy all of the dependencies into each Servlet container's "lib" directory.
Ideally, I would like to tell the Java application server that these WAR files must be loaded using a custom class loader which I will provide which automatically includes the Foo software dependency Jars. Something like this (in Java-pseudocode):
public class MyWarFileClassLoader extends ClassLoader {
protected URLClassLoader urlcl;
public MyWarFileClassLoader(File warFile) {
File installDir = System.getEnv("FOO_HOME");
List<File> fooEntries = new File(installDir, "jars").listFiles("*.jar");
fooEntries.add(new File(installDir, "resources"));
fooEntries.add(warFile);
this.urlcl = new URLClassLoader(fooEntries);
}
public Class<?> findClass(String name) {
return this.urlcl.findClass(name);
}
}
If there is no standard way to do this, is there a straightforward way to achieve the same goal for several WAR files, regardless of the target Servlet Container?
[Edit]
To put it another way: is there a common pattern for allowing WAR files to manage their own dependencies at runtime instead of relying on the Servlet Container configuration? I could, of course, have the WAR file manifest include a Class-Path
attribute but then the entries are still "hardcoded" at build time rather than detected automatically at runtime.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
没有标准方法可以强制在 Java EE 应用程序中使用特定的自定义类加载器来从预定义的源加载类。然而,可以在 Java EE 应用程序中捆绑库,以便多个模块(包括驻留在 WAR 中的 Web 模块)可以加载和访问捆绑库中的类。
Java EE 规范允许企业应用程序部署(
.ear
文件)将库捆绑到库部署目录中;默认情况下,这是.ear
文件中的lib
目录。然后,这些库可以由.ear
文件根目录中的多个 Web 模块(位于不同的.war
文件中)使用。 Java EE 6 规范的相关部分是 EE 8.2.1 节,其中规定了以下内容:值得注意的是,所有兼容 Java EE 的应用程序服务器(WebLogic/WebSphere/JBoss 等)都将支持使用捆绑库部署 EAR 文件。然而,有些 servlet 容器(如 Tomcat 和 Jetty)并不符合整个 Java EE 规范;此类容器不支持 EAR 文件的部署。
如果 servlet 容器中的多个 Web 模块需要访问这些库(由于容器的选择或由于对 WAR 文件的偏好),您应该依赖 servlet 容器对共享库的支持在没有库的情况下部署 WAR 文件。 Java EE 规范在这方面没有强制要求有关使用已安装库的任何要求。某些容器通过支持版本化共享库(其中部署的应用程序可能仅使用多个版本中的一个版本)来比其他容器更好地支持共享库,而其他容器(如 Tomcat)则不支持。
There is no standard way to enforce the use of a particular custom classloader in a Java EE application, to load classes from a predefined source. There is however the ability to bundle libraries within a Java EE application, so that multiple modules (including web-modules residing in WARs) can load and access classes in the bundled libraries.
The Java EE specification allows an Enterprise application deployment (a
.ear
file) to bundle libraries in a library deployment directory; by default this is thelib
directory within a.ear
file. These libraries may then be used by multiple web-modules (located in different.war
files) within the root of the.ear
file. The relevant part of the Java EE 6 specification is Section EE 8.2.1, where the following is stated:It is important to note that all Java EE compliant application servers (WebLogic/WebSphere/JBoss et al) will support deployment of EAR files with bundled libraries. However, there are servlet containers (like Tomcat and Jetty) which do not comply with the entire Java EE specification; such containers will not support deployment of EAR files.
In the event where the libraries are required to be accessed by multiple web modules in a servlet container (either due to the choice of the container or due to a preference for WAR files), you ought to rely on the servlet container support for shared libraries to deploy the WAR files without the libraries. The Java EE specification does not mandate any requirement in this area concerning the use of installed libraries. Some containers support shared libraries better than others, by supporting versioned shared libraries (where deployed applications may use only one version among several), while others (like Tomcat) do not.