12
返回列表 发新帖
楼主: petutor

[转载] 如何在WebSphere中解决jar包冲突

[复制链接]
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
11#
 楼主| 发表于 2007-3-16 22:46 | 只看该作者
图9:WebSphere Admin Console中选择需要配置的应用程序
步骤二:点击进入应用程序,设置类加载器的委托模式为Parent_Last。注意:在配置完成后,要保存配置,最后启动应用程序。如图10所示:

image018.jpg (28.29 KB, 下载次数: 20)

image018.jpg

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
12#
 楼主| 发表于 2007-3-16 22:47 | 只看该作者
图10:WebSphere Admin Console中为应用程序设置类加载器委托模式
通过上面的配置,即使xerces的其它版本已经存在于系统中,应用程序在运行时,其类加载器也会首先查找并加载指定的共享库中的xerces版本。这样我们就通过使用共享库的方式,解决了jar包版本冲突问题。

打包到Web模块中解决jar包冲突

共享库的方式,只是在应用程序的层次上,在多个应用程序之间解决了共享jar包造成的版本冲突问题,如果一个应用程序的内部,其中一个Web模块使用了一个jar包的A版本,而另一个Web模块使用这个jar包的B版本,在这种情况下造成的jar包冲突,共享库的方式是无法解决的,我们可以考虑将其中一个在多个应用程序间共享的jar包版本,比如A版本,定义成共享库,或者放在"WebSphere lib/app Class loader"类加载器路径上供多个应用程序使用,而将B版本的jar包打包到使用它的Web模块中的方式来解决冲突。

其次,目前很多在线的系统是WAS v4的遗留系统,其上运行的应用程序已经使用了"WebSphere lib/app Class loader"类加载器,将jar包放在$(WAS_HOME)/lib/app目录下进行共享。如果由于其中某个应用程序的升级或者新增加某个应用程序,需要使用某个共享jar包的其它版本,在这种情况下,为了减少对系统的影响,也可以考虑将这个共享jar包的新版本打包到升级(或新增)的应用程序中的方式来解决jar包冲突。

由于Web模块的WebContent/WEB-INFO/lib目录在应用程序Web模块的类加载器查找路径上,因此,我们可以把jar包放在这个目录下,Web模块的类加载器将自动查找并加载这个jar包中的类。

步骤一:在WSAD IE集成开发环境中,将冲突jar包放在Web模块的WebContent/WEB-INFO/lib目录下。如图11所示:

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
13#
 楼主| 发表于 2007-3-16 22:48 | 只看该作者
图11:WSAD IE中为Web模块添加库

image020.jpg (17.03 KB, 下载次数: 22)

image020.jpg

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
14#
 楼主| 发表于 2007-3-16 22:49 | 只看该作者
步骤二:在Admin console中,将应用程序部署到WebSphere server上之后,进入Applications > Enterprise Applications,选择相应的应用程序,并确认应用程序不在运行状态(参见前面章节中选择应用程序的步骤)。点击进入应用程序,确认应用程序的类加载器的委托模式为Parent_First,应用程序的类加载器策略为Module。如图12所示:


图12:WebSphere Admin Console中应用程序属性配置页面

image022.jpg (29.71 KB, 下载次数: 37)

image022.jpg

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
15#
 楼主| 发表于 2007-3-16 22:49 | 只看该作者
步骤三:在同一个页面上,选择 Web Modules,点击进入。如图13所示

image024.jpg (33 KB, 下载次数: 19)

image024.jpg

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
16#
 楼主| 发表于 2007-3-16 22:50 | 只看该作者
步骤四:点击相应的包含冲突jar包的Web模块,设置Web模块的类加载器的委托模式为Parent_Last。注意:在设置完成后要保存服务器配置,并启动应用程序。如图14所示:

image026.jpg (29.05 KB, 下载次数: 18)

image026.jpg

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
17#
 楼主| 发表于 2007-3-16 22:51 | 只看该作者
将冲突jar包打包到Web模块中,并设置相应Web模块的类加载器的委托模式为Parent_Last,应用程序在运行过程中加载类的时候,这个Web模块的类加载器会首先查找 WebContent/WEB-INFO/lib目录下的jar包进行类的加载;而对于其它的Web模块,由于其类加载器的委托模式仍然为缺省的Parent_First,它们的类加载器仍然首先从应用程序的共享库或者WebSphere的共享路径上加载jar包中的类,从而解决了jar包冲突的问题。

命令行运行方式解决jar包冲突

不论是设置共享库,还是将冲突jar包打包到应用程序中,其解决的问题都是在应用程序的一个Web模块中只使用了冲突jar包的一个版本的情况。我们在开发中曾经遇到过这样的情况:应用程序的Web模块中已经使用了1.4版本的xerces.jar,由于Web功能的扩展,在这个模块中又引入一个新的第三方工具,而这个第三方工具需要使用2.0版本的xerces.jar才能正常工作,这种情况下的jar包冲突如何解决呢?

在前面类加载器的部分已经介绍过,每个应用程序的一个Web模块最多只能有一个类加载器,而Web模块的类加载器中加载的类的生命周期为整个应用程序的运行期,也就是说,Web模块加载器不可能同时加载一个类的两个版本,同时,Web模块的类加载器的委托模式也是在应用程序运行前设置的,在应用程序运行期内无法改变的,因此,上面描述的在一个Web模块中同时使用两个版本的jar包的问题,象前两种方法那样配置运行在一个JVM内的类加载器的设置的方法是无法解决的。

唯一的解决办法就是在应用程序运行的JVM外,启动另外一个JVM来运行调用冲突jar包的代码,因为两个不同的JVM可以加载各自的类,从而解决jar包冲突问题。

这种情况下,原来使用jar包的老版本的方式(包括jar包放置路径,共享库设置方式,类加载器的委托模式等)不变,将对jar包新版本的调用通过命令行运行方式实现。具体做法是:将对jar包新版本内功能的调用,封装到一个可以单独运行的类中,在Web模块中以命令行方式运行这个类。同时把这个类以及jar包的新版本放在任意一个was可访问的路径上(比如/usr/WebSphere),在命令行的classpath参数中包含这个路径(比如/usr/WebSphere)。

下面通过举例说明命令行运行方式的编程过程,在本例中,假设TestEar应用程序的Web模块TestWar中,已经使用了conflict_v1.jar,由于新添功能需要使用conflict_v2.jar中的exampleCall()功能。

冲突jar包conflict_v2.jar提供的功能:


代码1:冲突jar包conflict_v2.jar功能
Package com.ibm.conflict;Public class ConflictClass{    …….Public static String exampleCall(string param){    String rs;    ……;    Return rs;}……}



不存在冲突问题时的编码举例:

如果没有jar包冲突问题,则对这个功能的调用是简单的,只需要将conflict_v2.jar放在应用程序自身或者其父类加载器的查找路径上,然后在Web模块中直接调用即可,如下:


代码2:不存在冲突时的调用方式
Public String methodA(String param){   ……   String rs = ConflictClass.exampleCall(param);   ……   Return rs;}



存在冲突后的命令行运行方式编码举例

针对jar包冲突问题,我们需要在Web模块中做如下的修改:

步骤一:将冲突jar包放在was可访问的路径上,比如/usr/WebSphere/conflict_v2.jar。
步骤二:将对包含冲突代码的调用封装到一组可单独运行的类中,它们将调用冲突jar包的功能,并将结果以系统输出的方式打印到系统标准输出上。 将这些类封装到一个单独的jar文件中,比如workAroundConflict.jar,并将其放在was可访问的路径上,比如/usr/WebSphere/workAroundConflict.jar。

Package com.ibm.test;Import com.ibm.ConflictClass;Public class WorkAround{Public static void main(String[] args){    String param1=args[0];    String returnStr=ConflictClass.exampleCall ();    System.out.println("<RTStr>"+returnStr+"</RTStr>";    Return;}}



代码3:将对冲突代码的调用写入一个单独的类WorkAround
步骤三:在Web模块中通过命令行方式调用封装的类,通过classpath指定所有依赖的jar包和类路径。运行封装类,从系统标准输出中取得运行结果。

Public static String methodA (String param){    ……    String rtStr = "";    String lStr="<RTStr>";    String rStr="<RTStr>";    //put all the dependency jar here    String classPath="/usr/WebSphere/conflict_v2.jar; /usr/WebSphere/workaroundConflict.jar;……";    String className="com.ibm.test.WorkAround";    String cmdLine="java -classpath " +classPath +" " +className + " "+ param;    Try{        Process process = Runtime.getRuntime().exec(cmdLine,null);        process.waitFor();        BufferedReader br= new BufferedReader(                  new InputStreamReader(process.getInputStream()));        while ((s = br.readLine())!=null) {            if (null == out)                out=s;            else                out+=s;}//get result from outif (null != out){    int lIndex = out.lastIndexOf(lStr);    int rIndex = out.lastIndexOf(rStr);    rsStr = out.substring(lIndex+lStr.length, rIndex);}    } catch (Exception e){        e.printStackTrace();}…….return rsStr;}



代码4:在应用程序中通过命令行方式运行WorkAround

命令行运行方式通过启动另外一个JVM的方式运行冲突代码,在一个不同的JVM中加载冲突的类,从而解决了jar包冲突问题。

但是命令行运行方式毕竟不是一个很好的方式,它存在以下的弊端:

命令行运行方式只适用于对冲突jar包的使用只是运行一段代码,或者只要求返回简单的字符串结果的情况。对于复杂的交互,命令行方式无法做到。但是如果在别无他法的情况下,可以适当地划分封装对冲突代码调用的jar包的包含范围,尽量将命令行运行的代码接口简单化。
命令行运行方式因为启动了另外一个JVM来运行,降低了WebSphere的性能。
因此,命令行方式只适用于一些极为特殊的情况下解决jar包冲突问题。




  




结论

本文对基于WebSphere的大型项目开发中遇到的jar包冲突问题,结合WebSphere中类加载器的概念,给出了三种解决办法以及相应的操作步骤和实现代码,并分析了各种方式所适用的具体情况。

项目开发过程中的jar包冲突,主要存在以下三种情况:

多个应用程序间的jar包冲突
应用程序内多个Web模块间的jar包冲突
应用程序内同一个Web模块内部jar包冲突
通过对类加载器的分析我们知道,解决jar包冲突问题的根本在于合理配置类加载器。在深入理解WebSphere中类加载器的层次结构的基础上,我们给出了"共享库解决jar包冲突"以及"打包到Web模块中解决jar包冲突"的办法,通过合理地配置WebSphere中类加载器及其委托模式,可以解决大多数的jar包冲突问题。但是由于这个层次结构中类加载器只配置到Web模块,因此,对于Web模块内部的jar包冲突问题,类加载器的配置是无法解决的,为此我们给出了"命令行运行方式解决jar包冲突"的办法。

表2中列出了在不同的WAS版本下,三种解决jar包冲突问题的办法所适用的jar包冲突情况。


表2:Jar包冲突解决办法适用的jar包冲突情况总结

table2.gif (5.11 KB, 下载次数: 23)

table2.gif

使用道具 举报

回复
论坛徽章:
1
会员2007贡献徽章
日期:2007-09-26 18:42:10
18#
 楼主| 发表于 2007-3-16 22:51 | 只看该作者
作者简介



郝爱丽是一位IBM CSDL的软件工程师,目前从事企业电子商务应用的开发。您可以通过 haoaili@cn.ibm.com 和她联系。




常红平是一位IBM CSDL的软件工程师,目前从事企业电子商务应用的开发。您可以通过 changhp@cn.ibm.com 和他联系。

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表