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

发布于 2024-12-05 23:34:23 字数 1183 浏览 0 评论 0原文

是否有一种标准方法(即由某些 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁把谁当真 2024-12-12 23:34:23

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

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

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

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

值得注意的是,所有兼容 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 the lib 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:

A .ear file may contain a directory that contains libraries packaged in JAR files. The library-directory element of the .ear file’s deployment descriptor contains the name of this directory. If a library-directory element isn’t specified, or if the .ear file does not contain a deployment descriptor, the directory named lib is used. An empty library-directory element may be used to specify that there is no library directory.

All files in this directory (but not subdirectories) with a .jar extension must be made available to all components packaged in the EAR file, including application clients. These libraries may reference other libraries, either bundled with the application or installed separately, using any of the techniques described herein.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文