【问题标题】:Overriding a class file from a library JAR in a Java web app在 Java Web 应用程序中覆盖库 JAR 中的类文件
【发布时间】:2012-01-11 20:03:55
【问题描述】:

在我的 Java Web 应用程序中,我有这些文件:

/WEB-INF/classes/com/example/Foo.class
/WEB-INF/lib/example.jar <-- contains the class "com.example.Foo"

是否会使用classes 目录中定义的类来代替example.jar 中定义的类?

谢谢。

【问题讨论】:

    标签: java jakarta-ee jar classpath


    【解决方案1】:

    答案取决于您的容器,它取决于容器。一般来说,/WEB-INF/classes 优先于 WEB-INF/lib 中的 jar 文件中的类。

    对于Tomcat,顺序如下:

    因此,从 Web 应用程序的角度来看,类或资源加载按以下顺序查看以下存储库:

    1. JVM 的引导类
    2. 系统类加载器类
    3. /WEB-INF/Web 应用程序的类
    4. /WEB-INF/lib/*.jar 您的 Web 应用程序
    5. 通用类加载器类

    但如果您使用不同的容器,则需要查阅该服务器的文档。

    【讨论】:

    • 而且我认为 example.jar 中的任何类仍然从 jar 文件中获取 Foo.class。
    • @AmirRaminfar 不,它应该始终使用相同版本的类,否则会发疯。
    • 所以你是说 example.jar 中的 Bar.class 导入 Foo.class 会在 web-inf/classes 中加载 Foo.class 吗?因为这听起来不对,我敢肯定这将是一个安全限制。
    • @AmirRaminfar 你是说需要调用 Bar.class (在 example.jar 中,并依赖于 Foo.class)的 Foo.class(在类中)的 Baz.class(在类中)将使用来自 example.jar 的 Foo.class 而不是已经加载的那个?我认为不会。
    • 不,我说的是 jar 文件中的 Bar.class! example.jar!/com/example/Bar.class 将在 example.jar/com/example/Foo.class 中加载 Foo.class
    【解决方案2】:

    所以只有一种方法可以找出答案。我写了一个测试:)

    ├── example
    │   ├── example.iml
    │   ├── pom.xml
    │   └── src
    │       ├── main
    │       │   └── java
    │       │       └── test
    │       │           ├── Bar.java
    │       │           └── Foo.java
    │       └── test
    │           └── java
    │               └── testexample
    │                   └── TestFoo.java
    ├── pom.xml
    ├── test.iml
    └── web
        ├── pom.xml
        ├── src
        │   ├── main
        │   │   └── java
        │   │       └── test
        │   │           └── Foo.java
        │   └── test
        │       └── java
        │           └── junittest
        │               └── TestFooInWeb.java
        └── web.iml
    
    16 directories, 11 files
    

    我的发现是在TestFoo.java 打印

    Hello from example.jar
    Hello from example.jar
    

    对于TestFooInWeb.java 打印

    Hello from web app
    Hello from web app
    

    两个测试在测试类中都有这个:

    public class TestFooInWeb/TestFoo {
        @Test
        public void testHello() {
            System.out.println(new Foo().sayHello());
        }
    
        @Test
        public void testHelloFromBar() {
            new Bar().sayHelloForFoo();
        }
    }
    

    所以最后,我的立场是正确的。您显然可以加载一个完全不同的类,并且所有 Jar 文件都将使用该新类。这是有道理的,因为ClassLoader 将首先查看类目录。我不确定我是否同意它,因为它听起来很可疑,而且我可以覆盖安全类。

    【讨论】:

    • 很详细的实验,谢谢!不过,我很确定您不能覆盖核心 Java 类。因此,例如,您不能创建一个java.lang.String 类并让它做一些讨厌的事情。顺便说一句,那些“.iml”文件是什么??
    • 那些 .iml 文件是 intellij ide。你是对的,你不能重写系统类。如果您查看 Mathew 写的内容,顺序是系统类路径,然后是 Web 类路径。
    猜你喜欢
    • 2023-04-03
    • 2015-03-31
    • 1970-01-01
    • 2012-08-08
    • 2012-09-12
    • 2013-04-12
    • 2013-10-03
    • 2016-02-07
    • 1970-01-01
    相关资源
    最近更新 更多