我有几个第三方JAR将由我的webapps使用。这些JAR文件实际上有不同的版本。
E.g。
版本1.0 JAR
/opt/lib/third-party-jars/1.0/3rdparty1.jar
/opt/lib/third-party-jars/1.0/3rdparty2.jar
2.0版JAR
/opt/lib/third-party-jars/2.0/3rdparty1.jar
/opt/lib/third-party-jars/2.0/3rdparty2.jar
是否可以在加载servlet之前动态加载不同版本的库?是否有任何框架能够在不更改现有代码的情况下执行此操作?
public class Servlet1 extends HttpServlet {
protected void doPost(....) {
MyBusinessLogic businessLogic = new MyBusinessLogic();
businessLogic.run() // My business logic spawns here which will start involving third-party classes
}
}
或者,在调用业务逻辑之前,是否可以在代码中动态加载版本1.0或2.0库?我可以提出的一种方法是使用自定义类加载器和"setContextClassLoader"
,但这需要使用反射来重构我的所有业务逻辑。这将是一项巨大的努力。我试图不改变现有的业务逻辑代码。
答案 0 :(得分:1)
Java支持多个版本的同一个jar。两个选项:
然而,这两者都会使事情变得不必要地复杂化。我建议引入一些由多个提供商实现的SPI。所以:
public interface BusinessLogic { .. }
然后是两个罐子,有两个实施 - com.foo.FooBL
和com.bar.BarBL
。然后配置所需的那个,并使用Class.forName(..).newInstance(..)
答案 1 :(得分:0)
一般来说,你想要的是非常难以做到的:servlet容器已经包含复杂的类加载器层次结构,并且尝试混合使用另一个层次结构通常会导致不必要的痛苦,应该避免。但是,看看JCL:它可能会做你想要的。
答案 2 :(得分:0)
据我所知,你无法控制使用哪个类加载器加载web.xml中定义的servlet。
在JavaEE 6中,您可以使用ServletContext.addServlet()添加从您自己的类加载器获取的类的servlet。所以你可以有一个虚拟的'bootstrap'servlet(或者是监听器或过滤器 - 只要在启动时加载):
我在这里完全不符合规范,我没有测试它,也不知道它是否真的有效。
答案 3 :(得分:0)
正如其他几个人已经提到的那样,做你提出的建议远非微不足道。您可以帮助您进一步解释为什么需要加载不同版本的JAR,以及触发此决策的条件。了解这一点可能有助于其他人为您的问题提出不同的解决方案。
例如,是否可以为每个捆绑WAR / EAR中相应第三方JAR的版本创建多个WAR或EAR程序集?在独立的WAR / EAR中捆绑第三方JAR将确保您正在寻找的类加载器可见性。这不应该需要太多/任何新的编码,只需要一些重组。或者,如果捆绑第三方JAR不是一个选项并且您使用的是应用程序服务器(如WAS),则可以利用共享库,以便其中一个WAR引用1.0版本的JAR,另一个引用2.0版本