如何用 JBoss EAP 中的另一个 jar 覆盖 WEB-INF/lib 中的一个 jar 中的一些 类?
How to override some classes in a jar in WEB-INF/lib with another jar in JBoss EAP?
如果要覆盖的 class 称为 com.example.FooServlet
并且此 class 在罐子 WEB-INF/lib/foo.jar
中,如何用 class 覆盖它在另一个罐子里叫 com.example.FooServlet
,说 bar.jar
?
或者有什么方法可以确保先加载 bar.jar
中的那个?
制作 bar.jar
模块是不行的,因为 FooServlet
从 WEB-INF/lib
.
中的许多 jar 中导入大量 classes
正如我上面所说,我试图在一个模块中包含 bar.jar
,但是没有找到 class 或者没有 class def 错误(记不清了)作为 FooServlet
extends/implements 一些额外的 classes/interfaces 位于 WEB-INF/lib.
的第 3 方罐子中
不允许我触摸 foo.jar
或 WEB-INF/lib
中已经存在的任何罐子。
查看 JBoss 模块以及如何通过 jboss-deployment-structure.xml
部署描述符处理它们。
很简单...
对于 2 个不同的 WAR 文件,您可以有 2 个不同的模块,每个模块在不同的 jars 文件中具有不同的 com.example.FooServlet。
您只需将 foo.jar 和 boo.jar 文件从 WAR 文件中取出,并将它们添加到适当的模块中。
WAR 的类加载器从您在 jboss-deployment-structure.xml
中定义的模块中选择需要的 class(es),并且从不与其他版本冲突。
你说你不能碰现有的罐子,你似乎在暗示你可以添加一个你的罐子到WEB-INF/lib
。
根据this:
WEB-INF/lib/*.jar
下的 jar 没有指定的优先顺序。
所以如果你在里面加上bar.jar
,你不知道是在foo.jar
之前还是之后加载。
- servlet 规范说 classes under
WEB-INF/classes
must be loaded before anything under WEB-INF/lib/*.jar
假设你可以在WEB-INF/lib
下添加一个jar,你应该能够在WEB-INF/classes
下添加一个class(或几个) , 没有接触到位的。
因此,如果您希望首先加载 bar.jar
中的 classes,您可以解压 WEB-INF/classes
下的那个 jar 的内容(或者只是您想要的 class优先加载 -- 例如 WEB-INF/classes/com/example/FooServlet.class
).
Java 代理考虑
假设您可以完全控制 JBoss 的启动方式,或者至少您可以更改 JBoss 启动设置 - 对您有帮助的是 Java 代理。
简而言之,Java 代理是 JVM 的自定义 'plugin' jar,它可以拦截该 JVM 对每个 class 的加载。并且 - 正是您所需要的 - 它可以执行任何截获的字节码的替换 class。
您要实现的目标不是全新的,似乎已经在某种程度上得到了解决。 查看此 as well as - 看起来几乎有关于编写代理的完整指南,该代理根据提供的外部 jar 替换 classes。
高层计划
- 已开发您的 java 代理,编译其 jar 并将其放置在您的 bar.jar 附近(因为代理将直接读取 bar.jar)
- 编辑 JBoss 启动命令行以包含
-javaagent:/path/to/your/agent.jar
- 现在,在 JBoss 启动期间,如果您提供的 bar.jar
中存在,您的代理将用相应的 class 替换每个代理
根据您的 JBoss 版本和部署模型,事情可能会变得有点复杂,但是有 some guides 可以轻松适应我们的情况的流行代理安装
如果要覆盖的 class 称为 com.example.FooServlet
并且此 class 在罐子 WEB-INF/lib/foo.jar
中,如何用 class 覆盖它在另一个罐子里叫 com.example.FooServlet
,说 bar.jar
?
或者有什么方法可以确保先加载 bar.jar
中的那个?
制作 bar.jar
模块是不行的,因为 FooServlet
从 WEB-INF/lib
.
正如我上面所说,我试图在一个模块中包含 bar.jar
,但是没有找到 class 或者没有 class def 错误(记不清了)作为 FooServlet
extends/implements 一些额外的 classes/interfaces 位于 WEB-INF/lib.
不允许我触摸 foo.jar
或 WEB-INF/lib
中已经存在的任何罐子。
查看 JBoss 模块以及如何通过 jboss-deployment-structure.xml
部署描述符处理它们。
很简单...
对于 2 个不同的 WAR 文件,您可以有 2 个不同的模块,每个模块在不同的 jars 文件中具有不同的 com.example.FooServlet。
您只需将 foo.jar 和 boo.jar 文件从 WAR 文件中取出,并将它们添加到适当的模块中。
WAR 的类加载器从您在 jboss-deployment-structure.xml
中定义的模块中选择需要的 class(es),并且从不与其他版本冲突。
你说你不能碰现有的罐子,你似乎在暗示你可以添加一个你的罐子到WEB-INF/lib
。
根据this:
WEB-INF/lib/*.jar
下的 jar 没有指定的优先顺序。
所以如果你在里面加上bar.jar
,你不知道是在foo.jar
之前还是之后加载。- servlet 规范说 classes under
WEB-INF/classes
must be loaded before anything underWEB-INF/lib/*.jar
假设你可以在WEB-INF/lib
下添加一个jar,你应该能够在WEB-INF/classes
下添加一个class(或几个) , 没有接触到位的。
因此,如果您希望首先加载 bar.jar
中的 classes,您可以解压 WEB-INF/classes
下的那个 jar 的内容(或者只是您想要的 class优先加载 -- 例如 WEB-INF/classes/com/example/FooServlet.class
).
Java 代理考虑
假设您可以完全控制 JBoss 的启动方式,或者至少您可以更改 JBoss 启动设置 - 对您有帮助的是 Java 代理。
简而言之,Java 代理是 JVM 的自定义 'plugin' jar,它可以拦截该 JVM 对每个 class 的加载。并且 - 正是您所需要的 - 它可以执行任何截获的字节码的替换 class。
您要实现的目标不是全新的,似乎已经在某种程度上得到了解决。 查看此
高层计划
- 已开发您的 java 代理,编译其 jar 并将其放置在您的 bar.jar 附近(因为代理将直接读取 bar.jar)
- 编辑 JBoss 启动命令行以包含
-javaagent:/path/to/your/agent.jar
- 现在,在 JBoss 启动期间,如果您提供的 bar.jar 中存在,您的代理将用相应的 class 替换每个代理
根据您的 JBoss 版本和部署模型,事情可能会变得有点复杂,但是有 some guides 可以轻松适应我们的情况的流行代理安装