简体   繁体   English

如何使用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?

If the class to override is called com.example.FooServlet and this class is inside a jar WEB-INF/lib/foo.jar , how to override it with a class also called com.example.FooServlet in another jar, say bar.jar ? 如果要覆盖的类称为com.example.FooServlet并且此类位于jar WEB-INF/lib/foo.jar ,那么如何使用另一个jar中的com.example.FooServlet类来覆盖它,比如bar.jar

Or is there any way to make sure the one in bar.jar is loaded first? 或者有没有办法确保首先加载bar.jar中的bar.jar

Making bar.jar a module is no-go because the FooServlet imports tons of classes from many jars in WEB-INF/lib . 使bar.jar成为一个模块是不行的,因为FooServletWEB-INF/lib许多jar中导入了大量的类。


As I stated above, I tried to contain bar.jar in a module, but got class not found or no class def error (can't remember clearly) as FooServlet extends/implements some extra classes/interfaces which are in 3rd party jars in WEB-INF/lib. 正如我上面所说的,我试图在一个模块中包含bar.jar ,但是找不到类或没有类def错误(记不清楚)因为FooServlet扩展/实现了一些额外的类/接口,它们位于第三方jar中WEB-INF / lib目录下。

I'm not allowed to touch foo.jar or any of the jars that are already existing in WEB-INF/lib . 我不允许触摸foo.jarWEB-INF/lib中已存在的任何jar。

You said you cannot touch existing jars, and you seem to imply you can add a jar of yours to WEB-INF/lib . 你说你不能触摸现有的罐子,你似乎暗示你可以在WEB-INF/lib 添加你的罐子。

According to this : 根据这个

  • there is no specified order of precedence for jars under WEB-INF/lib/*.jar . WEB-INF/lib/*.jar下,jar没有指定的优先顺序。
    So if you add bar.jar in there, you don't know if it will be loaded before or after foo.jar . 因此,如果你在那里添加bar.jar ,你不知道它是否会在foo.jar之前或之后foo.jar
  • the servlet spec says classes under WEB-INF/classes must be loaded before anything under WEB-INF/lib/*.jar servlet规范说WEB-INF/classes classes下的WEB-INF/classes必须在WEB-INF/lib/*.jar之前加载

Assuming you can add a jar under WEB-INF/lib , you should be able to add a class (or several) under WEB-INF/classes , without touching the ones in place. 假设你可以在WEB-INF/lib添加一个jar,你应该能够在WEB-INF/classes下添加一个(或几个) WEB-INF/classes ,而不需要触及那些WEB-INF/classes
So, if you want the classes from bar.jar to be loaded first, you can unzip the contents of that jar under WEB-INF/classes instead (or just the class you want to be loaded in priority -- for example WEB-INF/classes/com/example/FooServlet.class ). 因此,如果您希望首先加载bar.jar的类,则可以在WEB-INF/classes下解压缩该jar的内容(或者只是要优先加载的类 - 例如WEB-INF/classes/com/example/FooServlet.class )。

look at JBoss modules and how to handle them through jboss-deployment-structure.xml deployment descriptors. 查看JBoss模块以及如何通过jboss-deployment-structure.xml部署描述符处理它们。

It is simple... 很简单...

For 2 different WAR files you can have 2 different modules having different com.example.FooServlet in different jars files each. 对于2个不同的WAR文件,您可以在不同的jars文件中使用不同的com.example.FooServlet。

You just need to take your foo.jar and boo.jar files out of WAR file and add them to the appropriate modules. 您只需要将您的foo.jar和boo.jar文件从WAR文件中取出并将它们添加到相应的模块中。

ClassLoader for WAR picks needed class(es) from modules you define in jboss-deployment-structure.xml and never clashes with other versions. WAR的ClassLoader从您在jboss-deployment-structure.xml定义的模块中选择所需的类,并且永远不会与其他版本冲突。

Java Agent Consideration Java代理注意事项

Assuming you have full control on how JBoss is being started, or at least you can change JBoss startup settings - the thing which comes to your help is Java agent. 假设您可以完全控制JBoss的启动方式,或者至少可以更改JBoss的启动设置 - 您的帮助就是Java代理。

In a nutshell Java agent is a custom 'plugin' jar to a JVM, and it can intercept loading of each and any class by that JVM. 简而言之,Java代理是JVM的自定义“插件”jar,它可以拦截该JVM对每个类和任何类的加载。 And - just what you need - it can perform substitution of byte code of any intercepted class. 并且 - 正是您需要的 - 它可以执行任何截获的类的字节代码的替换。 Further reading about Java agent concept 进一步阅读Java代理概念

The goal you're trying to achieve isn't brand new, and seems it has already been resolved at some level. 你想要实现的目标不是全新的,似乎已经在某种程度上得到了解决。 Check out this question as well as answer - it looks like there is almost full guide about writing the agent which replaces classes based on provided external jar with replacements. 看看这个问题以及答案 - 看起来几乎有关于编写代理的完整指南,该代理根据提供的外部jar替换类替换类。

The High-Level Plan 高级计划

  1. Have your java agent developed, its jar compiled and placed near your bar.jar (as agent will read bar.jar directly) 开发你的java代理,编译它的jar并放在你的bar.jar附近(代理将直接读取bar.jar)
  2. Edit JBoss startup command line to include -javaagent:/path/to/your/agent.jar 编辑JBoss启动命令行以包含-javaagent:/path/to/your/agent.jar
  3. Now during JBoss startup, your agent will replace each class by corresponding one if it is present in your provided bar.jar 现在,在JBoss启动期间,如果您提供的bar.jar中存在相应的类,则您的代理将替换每个类

The things may become a bit more complex depending on your JBoss version and deployment model, but there are some guides for popular agents installation which can be easily adapted to our case 根据您的JBoss版本和部署模型,事情可能会变得有点复杂,但有一些流行的代理安装指南可以很容易地适应我们的情况

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM