从servlet加载不同版本的jar lib

时间:2011-09-19 01:54:22

标签: java servlets

我有几个第三方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",但这需要使用反射来重构我的所有业务逻辑。这将是一项巨大的努力。我试图不改变现有的业务逻辑代码。

4 个答案:

答案 0 :(得分:1)

Java支持多个版本的同一个jar。两个选项:

  • 扩展tomcat的类加载器以提供自定义加载逻辑
  • 使用OSGi。 Virgo是一个基于OSGi的servlet容器

然而,这两者都会使事情变得不必要地复杂化。我建议引入一些由多个提供商实现的SPI。所以:

public interface BusinessLogic { .. }

然后是两个罐子,有两个实施 - com.foo.FooBLcom.bar.BarBL。然后配置所需的那个,并使用Class.forName(..).newInstance(..)

进行实例化

答案 1 :(得分:0)

一般来说,你想要的是非常难以做到的:servlet容器已经包含复杂的类加载器层次结构,并且尝试混合使用另一个层次结构通常会导致不必要的痛苦,应该避免。但是,看看JCL:它可能会做你想要的。

答案 2 :(得分:0)

据我所知,你无法控制使用哪个类加载器加载web.xml中定义的servlet。

在JavaEE 6中,您可以使用ServletContext.addServlet()添加从您自己的类加载器获取的类的servlet。所以你可以有一个虚拟的'bootstrap'servlet(或者是监听器或过滤器 - 只要在启动时加载):

  • 使用适当版本的JAR
  • 创建自定义类加载器
  • 从自定义类加载器创建真正的 servlet类(不应在web.xml中指定此servlet类)
  • 使用ServletContext.addServlet()
  • 注册此类

我在这里完全不符合规范,我没有测试它,也不知道它是否真的有效。

答案 3 :(得分:0)

正如其他几个人已经提到的那样,做你提出的建议远非微不足道。您可以帮助您进一步解释为什么需要加载不同版本的JAR,以及触发此决策的条件。了解这一点可能有助于其他人为您的问题提出不同的解决方案。

例如,是否可以为每个捆绑WAR / EAR中相应第三方JAR的版本创建多个WAR或EAR程序集?在独立的WAR / EAR中捆绑第三方JAR将确保您正在寻找的类加载器可见性。这不应该需要太多/任何新的编码,只需要一些重组。或者,如果捆绑第三方JAR不是一个选项并且您使用的是应用程序服务器(如WAS),则可以利用共享库,以便其中一个WAR引用1.0版本的JAR,另一个引用2.0版本