有哪位高手我愿意歌词一起开发 Application Server 吗

IBM Bluemix
点击按钮,开始云上的开发!
developerWorks 社区
这是本系列文章的第三部分,描述了在 IBM(R) WebSphere(R) Application Server V6 中的新的消息传递引擎来构建企业服务总线(Enterprise Service Bus,ESB),我们将设置消息驱动 bean 来监听 JMS 队列的消息并设置 J2EE 客户端应用程序来向那个 JMS 队列发送消息。我们还会看一下在应用程序服务器上通过消息总线发送 JMS 消息所必需的设置。
(), 高级 IT 咨询专家, EMC
Rachel Reinitz 是 IBM Software Services for WebSphere 中重点研究 Web 服务的高级 IT 咨询专家。Rachel 咨询客户和独立软件商关于怎样才能将面向服务的体系结构及 Web 服务用于达到他们的业务以及技术目标。她进行了 IBM 高级 Web 服务培训教程的开发并且经常作为会议的主持人。Rachel 同时也是有过 4 年 XP 实践、经验丰富的极限编程专家。她居住在加利福尼亚州的 Bay 区,喜爱徒步旅行、社会活动、以及国际旅行。
, 高级技术人员, EMC
Andre Tost 是 WebSphere Business Development 小组的一位高级技术人员,他在这个部门帮助 IBM 的战略联盟伙伴把他们的应用程序与 WebSphere 集成在一起。他的工作重点是贯穿整个 WebSphere 产品系列的 Web 服务技术。在开始从事他目前的工作之前,有十年的时间他在 IBM 软件开发工作中担任各种开发和体系结构方面的角色,最近他从事于 WebSphere Business Components 产品。他出生于德国,目前在美国明尼苏达州的罗切斯特居住和工作。在业余时间,他喜欢和他的家人在一起,只要有可能就去踢球或者看球。
引言 现在我们已经浏览了在 IBM WebSphere Application Server V6 中支持的消息传递资源的基础(在中),描述了我们将在本系列文章中使用的业务场景(Posts-R-Us 公司),并看到了如何创建消息传递总线的实例(在中),现在到了该做些实际工作的时候了!在第 3 部分中,我们将向您展示如何创建一个简单的点对点的基于 JMS 的消息传递的应用程序。这个应用程序由一个发送部分(在 J2EE(TM) 客户端应用程序内运行),和一个接收部分(以消息驱动 bean 为代表)组成。在创建此应用程序的过程中,我们将看到在应用程序服务器中通过消息总线发送 JMS 消息所必需的设置。JMS 和总线 在接下来的业务场景中,我们将假定无论包何时被传递给消费者,消息都必须发送给 Posts-R-Us 的主系统以便确认此传递。该确认消息异步传送,也就是,没有需要的响应,此消息简单地排列到主系统中用于处理。可能您现在认为,在 MDB 中发送消息给 JMS 队列,并从那儿进行接收是非常令人兴奋或新鲜的。您是对的。然而,它之所以有趣是基于以下事实:消息通过消息传递总线正确发送到目的地。它可以使我们使用中介来应用可选的消息传递的处理,比如过滤消息内容或者路由到其它不同的目的地,仅仅是命名几个而已。换句话说,总线在将消息传递到消费者之前就对它进行了控制,也就是 MDB,提供了在传统的 JMS 场景中无法获得的控制级别。在 WebSphere Application Server V6 中创建 JMS 资源
第一步,我们将在应用程序服务器中创建一些构件:JMS 连接工厂、JMS 队列(MDB 的激活规范)当然还有总线目的地。我们将从总线目的地开始,然后配置 JMS 资源:打开 WebSphere Application Server 管理控制台(服务器必须保持运行)。在左侧的导航面板中选择 Service Integration =& Buses。选择 TheBus,然后在下面的对话框中选择 Destinations。当前定义的总线目的地清单展示出来,选择 New。注意您可以创建几种类型的目的地。在我们的例子中,我们将使用 Queue 目的地。选择 Next。进入
PackageReceivedDestination 标志符, 然后选择 Next。再次点击 Next 接收总线成员,然后点击 Finish。保存您所作的修改,然后在列表中可以看到新总线,如图 1 所示。
图 1. 总线目的地现在准备创建 JMS 构件。在管理控制台的导航面板中,选择 Resources =& JMS Providers =& Default Messaging。我们将此作用范围定为 Node,为默认值。图 2 展示了此对话框。
图 2. 默认的消息传递提供者配置创建连接工厂,选择 JMS Connection Factory 链接,然后选 New。在创建对话框中,进入下列各项(图 3):
名称:TheConnectionFactoryJNDI 名称:jms/TheConncectionFactory总线名称:TheBus保持其它的默认值,然后点击 OK 保存您所做的修改。图 3. JMS 连接工厂接下来,在默认的消息传递提供者窗口(图 2)中选择 JMS Queue 链接并点击 New。进入下列各项(图 4):
名称:PackageReceivedQueueJNDI 名称:jms/PackageReceivedQueue总线名称:TheBus队列名称:PackageReceivedDestination保持其它的默认值,然后点击 OK 保存您所做的修改。图 4. JMS 队列 我们需做的最后一件事情是激活规范,它对于 J2EE 1.4 是新的,并且将 MDB 捆绑到队列中。在 MDB 的部署描述符中,您定义激活规范的 JNDI。对于激活规范本身,您确定 MDB 应该监听的队列。返回管理控制台的 Default Messaging Provider 窗口(图 2),选择 JMS activation specification,然后选择 New。
输入或选择下列值(图 5):
名称:PackageReceivedActivationSpecJNDI 名称: eis/PackageReceivedActivationSpec目的地类型:queue目的地 JNDI 名称:jms/PackageReceivedQueue总线名称:TheBus保持其它的默认值,然后点击 OK 保存您所做的修改。图 5. JMS 激活规范这些是我们发送消息到总线和从那儿到消息驱动 bean 需要的所有构件。接下来我们将看一下实际的 Java 代码。Java 代码 我们不会花费很多时间来描述即将用于本例的代码,因为它同其他任何规范的 JMS 代码真的没有区别(请参阅 JMS 的部分),而且您能在章节中下载我们所使用的代码,包括所需的 J2EE 部署描述符。发送者主要将发送一个约束传递包的数量的文本消息。因为发送者代码在 J2EE 客户端应用程序中运行,所以我们无法对所用的 JMS 资源的名称进行硬编码。我们使用 java:comp/env namespace 来代替。这两个名称,一个用于连接工厂,一个用于实际队列,在客户端应用程序部署描述符中利用资源引用它们被束缚起来。这里是客户端代码的摘录:清单 1 public class Main {
private final static String JMSCF_JNDI_NAME =
"java:comp/env/jms/TheConnectionFactory";
private final static String JMSQ_JNDI_NAME =
"java:comp/env/jms/PackageReceivedQueue";
private final static String messageText =
"Package Received - ";
public static void main(String[] args) throws Exception {
InitialContext initCtx = new InitialContext();
// Finding the WAS QueueConnectionFactory
javax.jms.ConnectionFactory qcf =
(javax.jms.ConnectionFactory) initCtx.lookup(JMSCF_JNDI_NAME);
// Finding the Queue Destination
Destination q = (Destination) initCtx.lookup(JMSQ_JNDI_NAME);
// Create JMS Connection
Connection connection = qcf.createConnection();
// Create JMS Session
Session session =
connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create MessageProducer and TextMessage
MessageProducer queueSender = session.createProducer(q);
TextMessage outMessage = session.createTextMessage();
outMessage.setText(messageText);
// Set type and destination and send
outMessage.setJMSType("package_received");
outMessage.setJMSDestination(q);
queueSender.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
queueSender.send(outMessage);
connection.close();
System.out.println("Send completed");
}对于 MDB,事情变得更简单了。每一个 MDB 有一个称为 onMessage() 的方法。一旦消息到达 MDB 监听的队列时,这个方法就被调用了。在我们例子中它是这样的:清单 2.public void onMessage(javax.jms.Message msg) {
if (!(msg instanceof TextMessage)) {
System.out.println("Received message is not a text message!");
throw new RuntimeException();
TextMessage textMsg = (TextMessage)
System.out.println("Received message : "+textMsg.getText());
// forward the received message to business logic for processing...
} catch (JMSException x) {
throw new RuntimeException(x);
}客户端应用程序和 MDB 两者都有部署描述符。在这里我们将快速浏览一遍。客户端部署描述符,在一个称为 application-client.xml 的文件中,包含对用于上述代码中 JMS 连接工厂和队列中 JNDI 名称的引用。如果您在 Application Server Toolkit 中打开客户端部署描述符,它将看起来更加简单,如图 6 所示。图 6. 客户端部署描述符在代码中,用到的 Name 值与 java:comp/env 名称空间结合一起。它在代码中用作名为 JMSCF_JNDI_NAME 的变量。WebSphere Bindings 下的输入展示了当它在应用程序服务器被部署时的资源的实际名称(记住我们早先创建的名为 jms/TheConnectionFactory 的 JMS 连接工厂)。MDB 的部署描述符包含对 JMS 激活规范(它与我们前面创建的 JMS 队列依次联合)的引用,如图 7 所示。
图 7. MDB 部署描述符我们为该 MDB 定义称为 package_received 的消息选择器,它能更进一步地过滤进来的消息。消息选择器在 JMS 消息的客户端代码上设置: outMessage.setJMSType("package_received");我们将客户端和 MDB 模块打包到 EAR 文件中,分别命名为 PackageReceivedClient.ear 和 PackageReceived.ear。在我们运行客户端之前,必须将 MDB 安装并部署到应用程序服务器中。我们接下来就进行操作。安装和运行 Java 代码 安装和部署 MDB:在管理控制台,在左侧的导航面板选择 Applications =& Enterprise Applications。选择 Install。选择 Local file system,进入包含 MDB 的 EAR 文件的名称和目录中,然后选择 Next。确保 Generate Default Bindings 已经核查过并选择 Next。在下面的窗口中,核查 Deploy enterprise beans,然后选择 Next。在接下来的两个对话框中选择 Next,没有任何修改。注意在下面的窗口中,您能重写激活规范的设定值,包括正被使用的 JMS 队列(图 8)。
图 8. 重写激活规范的性能我们在此不必修改任何东西,但这里展示了在 EAR 文件和部署描述符中应用程序开发者如何调整其设置值。选择 Next,然后是 Finish。当完成部署步骤时,保存您的修改。您的控制台浏览器窗口将看起来如图 9 所示。
图 9. 安装应用程序后的管理控制台注意新的应用程序已经安装,但并未被启动。要启动它,选择与应用程序相邻的检验栏,然后选择 Start。MDB 现在已经准备从总线接收消息。运行程序客户端发送消息到总线,打开命令提示窗口,改到您正使用的应用程序服务器概要的 \bin 目录下。举个例子,如果您的概要命名为 MyShippingCo 并且您所安装的 WebSphere Application Server 在 c:\WebSphere\AppServer6 目录下,那么 c:\WebSphere\AppServer6\profiles\MyShippingCo\bin 将是您所需要的目录。
通过调用 setupcmdline 实用程序设置合适的环境。现在,通过调用 launchclient 实用程序来开启客户端应用程序,传递客户端 EAR 文件作为参数,如图 10 所示。
图 10. 开启 launchclient 实用程序在 \logs\server1 目录下检查 SystemOut.log 文件。这是 MDB 输出的地方,而且它将展示图 11 中打印的消息。
图 11. SystemOut.log 文件输出的日志文件将包含有用的信息以防出现问题,因此检查它通常是一个很好的做法。结束语在本文中,我们描述了用
WebSphere Application Server V6 Messaging Resources 构建企业服务总线的通用场景。无论何时传递包,我们构建的服务器都会向总线发送确认消息,使用 JMS 作为与总线通信的协议。消息的接收者是消息驱动 bean,也使用 JMS 作为它的协议。在以后的文章中,我们将向您展示当消息从总线中经过时,如何利用中介进行操作。因此请耐心等待。
下载描述名字大小PackageReceived.ZIP
您可以参阅本文在 developerWorks 全球站点上的 。通过参加
而进入 developerWorks 社区。购买
developerWorks: 登录
标有星(*)号的字段是必填字段。
保持登录。
单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件。
在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。
所有提交的信息确保安全。
选择您的昵称
当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。昵称长度在 3 至 31 个字符之间。
您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。
标有星(*)号的字段是必填字段。
(昵称长度在 3 至 31 个字符之间)
单击提交则表示您同意developerWorks 的条款和条件。 .
所有提交的信息确保安全。
文章、教程、演示,帮助您构建、部署和管理云应用。
立即加入来自 IBM 的专业 IT 社交网络。
为灾难恢复构建应用,赢取现金大奖。
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=WebSphereArticleID=83665ArticleTitle=IBM WebSphere 开发者技术期刊 : 使用 WebSphere Application Server V6 构建企业服务总线——第 3 部分publish-date=[通译]WebSphere Application Server V7:理解类装入器 - Web前端当前位置:& &&&[通译]WebSphere Application Server V7:理解类装[通译]WebSphere Application Server V7:理解类装入器&&网友分享于:&&浏览:75次[翻译]WebSphere Application Server V7:理解类装入器
说明:从word导入到博客,调整格式太麻烦了,我就不调整了,如果需要可以下载附件或如下地址的pdf版
http://download.csdn.net/source/3384756
WebSphere Application Server V7:理解类装入器Java类装入器介绍 2WebSphere类装入器概述 5WebSphere扩展类装入器 5应用程序和Web模块类装入器 7处理JNI代码 8配置WebSphere的类装入器 8应用服务器类装入器策略 8类加载/委托模式 11共享库 12类装入器查看器 13通过实例学习类装入器 13第一步:简单的Web模块 14第二步:添加EJB模块和工具JAR 17第三步:改变WAR类装入器的委托模式 18第四步:使用共享库共享工具JAR 19参考资料 24说明 24修改纪录序号
作者(翻译)
备注1 所有 新建
upeepu 初始版本2
理解Java和WebSphere类装入器的工作方式对于打包和部署Java EE5的应用非常重要。错误地设置类装入器属性,在启动服务时很可能导致一系列臭名昭著的类加载异常(例如:ClassNotFoundException)。在本章中,我们将解释类装入器以及如何个性化设置WebSphere的类装入器以满足应用的特殊需求。本章最后会给出一些示例来说明这些概念。本章涉及到以下内容:? Java类装入器介绍? WebSphere类装入器概览? WebSphere类装入器配置? 类加载查看器? 通过实例学习类装入器Java类装入器介绍 类装入器帮助Java虚拟机(JVM)加载类。给出类的名字,类装入器会定位到这个类的定义。每个Java类都必须由类装入器加载。 当启动JVM时,你就在使用三个类装入器:引导程序(bootstrap)类装入器,扩展(extensions)类装入器和应用程序(application)类装入器:? 引导程序类装入器负责加载Java_home/jre/lib目录下的Java核心库。这个类装入器是核心JVM的一部分,由本地代码编写。? 扩展类装入器负责加载扩展目录中的代码(Java_home/jre/lib/ext目录或者其他由系统属性java.ext.dirs定义的目录)。该类装入器由sun.misc.Launcher$ExtClassLoader实现。? 应用程序类装入器负责加载java.class.path目录下的代码,该目录最终映射为系统环境变量CLASSPATH。该类装入器由sun.misc.Launcher$AppClassLoader实现。在处理类装入器时,首先需要理解父级委托模型(parent-delegation model)。它表示类装入器在加载类之前会委托父级类装入器来加载。父级类装入器可以是另一个自定义类装入器,也可以是引导程序类装入器。但重要的是,类装入器只能委托父级类装入器而不能委托子类装入器(它只能逐级向上而不能向下)。扩展类装入器是应用程序类装入器的父级类装入器,引导程序类装入器是扩展类装入器的父级类装入器。类装入器结构见图1.如果应用程序类装入器要加载一个类,它首先委托扩展类装入器,进而委托引导程序类装入器。如果父级类装入器不能加载该类,子类装入器尝试在自身库中加载。在这种情况下,类装入器只负责加载祖先类装入器无法加载的类。如果一个类是有类装入器树的非叶节点类装入器加载的,这种行为会导致一些有趣的问题。例1:类WhichClassLoader1加载类WhichClassLoader2,然后调用类WhichClassLoader3。图1 Java类装入器结构图例1:WhichClassLoader1 和 WhichClassLoader2 源代码public class WhichClassLoader1 {public static void main(String[] args) throws javax.naming.NamingException {// Get classpath valuesString bootClassPath = System.getProperty("sun.boot.class.path");String extClassPath = System.getProperty("java.ext.dirs");String appClassPath = System.getProperty("java.class.path");// Print them outSystem.out.println("Bootstrap classpath =" + bootClassPath + "\n");System.out.println("Extensions classpath =" + extClassPath + "\n");System.out.println("Application classpath=" + appClassPath + "\n");// Load classesObject obj = new Object();WhichClassLoader1 wcl1 = new WhichClassLoader1();WhichClassLoader2 wcl2 = new WhichClassLoader2();// Who loaded what?System.out.println("Object was loaded by " + obj.getClass().getClassLoader());System.out.println("WCL1 was loaded by " + wcl1.getClass().getClassLoader());System.out.println("WCL2 was loaded by " + wcl2.getClass().getClassLoader());wcl2.getTheClass();}}===================================================================public class WhichClassLoader2 {// This method is invoked from WhichClassLoader1public void getTheClass() {WhichClassLoader3 wcl3 = new WhichClassLoader3();System.out.println("WCL3 was loaded by " + wcl3.getClass().getClassLoader());}}如果所有的WhichClassLoaderX类已经放到应用程序类路径(application class path),那么这三个类就由应用程序类装入器加载,例子会正常运行。下载假设你将WhichClassLoader2.class打包到一个JAR文件中,并且将它放到Java_home/jre/lib/ext路径,你在例2中会看到如下输出。例2:NoClassDefFoundError exception traceBootstrap classpath=C:\WebSphere\AppServer\java\jre\lib\vm.C:\WebSphere\AppServer\java\jre\lib\core.C:\WebSphere\AppServer\java\jre\lib\charsets.C:\WebSphere\AppServer\java\jre\lib\graphics.C:\WebSphere\AppServer\java\jre\lib\security.C:\WebSphere\AppServer\java\jre\lib\ibmpkcs.C:\WebSphere\AppServer\java\jre\lib\ibmorb.C:\WebSphere\AppServer\java\jre\lib\ibmcfw.C:\WebSphere\AppServer\java\jre\lib\ibmorbapi.C:\WebSphere\AppServer\java\jre\lib\ibmjcefw.C:\WebSphere\AppServer\java\jre\lib\ibmjgssprovider.C:\WebSphere\AppServer\java\jre\lib\ibmjsseprovider2.C:\WebSphere\AppServer\java\jre\lib\ibmjaaslm.C:\WebSphere\AppServer\java\jre\lib\ibmjaasactivelm.C:\WebSphere\AppServer\java\jre\lib\ibmcertpathprovider.C:\WebSphere\AppServer\java\jre\lib\server.C:\WebSphere\AppServer\java\jre\lib\xml.jarExtensions classpath =C:\WebSphere\AppServer\java\jre\lib\extApplication classpath=.Exception in thread "main" java.lang.NoClassDefFoundError:WhichClassLoader3at java.lang.J9VMInternals.verifyImpl(Native Method)at java.lang.J9VMInternals.verify(J9VMInternals.java:59)at java.lang.J9VMInternals.initialize(J9VMInternals.java:120)at WhichClassLoader1.main(WhichClassLoader1.java:17)可以看到,程序出现了NoClassDefFoundError异常,听起来有些奇怪,因为WhichClassLoader3就在应用程序类路径上。问题是现在它在错误的类路径上。问题出在WhichClassLoader2是由扩展类装入器加载的。事实上,应用程序类装入器委托扩展类装入器加载类WhichClassLoader2,进而委托引导程序类装入器。因为引导程序类装入器无法找到这个类,所以类加载控制权返回给扩展类装入器。扩展类装入器在它的类路径找到这个类并加载了它。当一个类被一个类装入器加载后,该类需要的任何新类都用同一个类装入器加载(按照父级委托模型,追溯到结构上层)。所以当WhichClassLoader2要使用WhichClassLoader3时,首先请求扩展类装入器加载它。扩展类装入器先将请求委托给引导程序类装入器,引导程序类装入器找不到这个类,然后尝试自己加载,但是没有找到该类,因为WhichClassLoader3没在扩展类路径上,而是在应用程序类路径上。并且扩展类装入器不能把请求委托给应用程序类装入器(委托请求只能沿着模型结构向上,不能向下),所以NoClassDefFoundError异常就产生了。注意:开发者经常通过类加载机制使用如下语法加载配置文件Properties p = new Properties();p.load(MyClass.class.getClassLoader().getResourceAsStream("myApp.properties"));这意味着,如果类MyClass由扩展类装入器加载,并且myApp.properties只在应用程序类路径上,那么加载该配置文件会失败。WebSphere类装入器概述注意:在讨论下面的问题时,记住每个JVM都有自己的类装入器。在WebSphere多应用服务器(JVMs)环境下,这意味着JVMs的类装入器是完全独立的,即使他们运行在相同的物理机器上。WebSphere提供多种自定义可委托的类装入器,见图2:图2 WebSphere类装入器结构图最上面的方框代表Java(引导程序,扩展程和应用程序)类装入器。WebSphere在这里加载足够的类来使自身启动并初始化WebSphere扩展类装入器。WebSphere扩展类装入器WebSphere自身在WebSphere扩展类装入器加载。WebSphere V6.1版本之前,运行时由这个类装入器单独加载。然而,从V6.1开始,WebSphere被打包成一组OSGi包。每一个OSGi包由独立的类装入器加载。这个OSGi类装入器网络通过OSGi网关类装入器与扩展类装入器和类装入器层次结构中的其他类装入器相连。不管WebSphere加载自己类的方式如何改变,和你的应用程序相关的行为不会改变。他们仍然保持相同的可见性,相同的类加载选项。在V6.1之前,WebSphere运行时类文件存在install_root目录下的classes,lib,lib\ext和installedChannels目录中。由于使用OSGi打包方式,这些目录不再存在并且运行时类存在install_root\plugins目录中。扩展类装入器使用的类路径是从ws.ext.dirs系统属性中提取的,它最开始来源于setupCmdLine脚本中的WAS_EXT_DIRS环境变量。ws.ext.dirs默认值建例3.例3 ws.ext.dirs默认值SETWAS_EXT_DIRS=%JAVA_HOME%\%WAS_HOME%\%WAS_HOME%\%WAS_HOME%\installedC%WAS_HOME%\lib\%WAS_HOME%\web\%ITP_LOC%\plugins\com.ibm.etools.ejbdeploy\runtimews.ext.dirs环境变量中的每一个目录被加到WebSphere扩展类装入器类路径中,并且该路径中的每一个JAR文件和每个ZIP文件被加到类路径中。即使classes和installedChannels路径在install_root路径下不存在,setupCmdLine脚本也会把它们加到扩展类路径中。这意味着,如果你在原来的版本中在这些目录里加入了自己的JAR文件,扩展类装入器也会加载它们。然而,我们不建议这种方式,你应该从老版本迁移到新版本。另一方面,V6.1之前的版本,如果你开发Java应用依赖于install_root\lib目录下的JAR文件,你需要修改你的程序来保持兼容性。WebSphere Application Server专为这种应用程序提供了两个瘦客户端库(thin client libraries):一个是管理客户端库(administrative client library),一个是Web services客户端库。这些瘦客户端库可以在install_root\runtimes目录中找到:? com.ibm.ws.admin.client_7.0.0.jar? com.ibm.ws.webservices.thinclient_7.0.0.jar这些库提供了你的应用程序与WebSphere一起工作所需的所有东西。WebSphere Application Server V7为用户提供了限制访问WebSphere内部类的能力,所以你的应用程序不应该调用官方未发布的不被支持的API。在应用程序服务器设置中,这一项叫做“内部服务类访问(Access to internal server classed)”。默认设置是“允许(Allow)”,这意味着你的应用程序可以不受限制地访问未公开的内部WebSphere类。我们不建议使用该功能,并且在后续版本中将会禁止。因此,作为一个管理员,将该设置改为“限制(Restrict)”,然后程序是否运行正常是一个不错的想法。如果它们依赖与未公开的WebSphere内部类,你会收到ClassNotFoundException,在这种情况下,你可以再改回“允许”。开发人员应该修改它们的应用,不再调用未公开的WebSphere内部类,从而兼容WebSphere Application Server的后续版本。应用程序和Web模块类装入器Java EE5应用程序五个主要元素:Web模块,EJB模块,应用程序客户端模块,资源适配器(RAR文件),工具JAR包。EJB和servlets都会用到工具JAR包中的代码。类似于log4j的工具框架就是工具JAR的好例子。与一个应用程序相关的EJB模块,工具JAR包,资源适配器文件和共享库文件通常在一个类装入器中。这个类装入器叫做应用程序类装入器。依赖于类装入器策略,该类装入器可以在多个应用程序(EARs)间共享,或者默认被一个应用程序使用。默认地,Web模块有自己的类装入器,一个WAR类装入器,来加载WEB-INF/classes和WEB-INF/lib目录下的内容。你可以通过修改应用程序的WAR类装入器策略来改变默认的行为。策略设置可以在控制台中找到。应用程序-&WebSphere企业应用程序-&应用程序名称-&类装入和更新检测-&WAR类装入器策略。见图3.图3 WAR类装入器策略默认的是设置为“应用程序中每个WAR文件的类装入器”。这个设置在以前的版本中称为“模块”,在应用程序部署描述符中可以通过Rational Application Developer中看到。如果WAR类装入器策略设置为“应用程序的单个类装入器”,Web模块的内容和EJB,RAR,工具JAR,共享库一样由应用程序类装入器加载。应用程序类装入器是WAR类装入器的父级类装入器。这个设置在以前的版本中称为“应用程序”,在应用程序部署描述符中可以通过Rational Application Developer中看到。应用程序和WAR类装入器是可以重复加载的类装入器。它们监控应用程序代码的变化来自动重新加载变化的类。你可以在开发时改变这种行为。处理JNI代码因为JVM只有一个地址空间,本地代码在一个地址空间智能被加载一次,JVM规范指出在JVM中本地代码只能被一个类装入器加载。这会导致一个问题,如果你有一个应用程序(EAR文件)包括两个Web模块,并且它们都需要通过JNI加载相同的本地代码。那么,只有第一个被加载的库会成功。为了解决这个问题,你可以把加载本地代码的几行Java代码提出来,放到一个类中,然后让这个类由应用程序类装入器加载(放到一个工具JAR中)。然而,如果你在同一个应用服务器中部署了多个这样的应用程序(EAR文件),你不得不把这个类放到WebSphere的扩展类装入器上,以保证在每个JVM中本地代码只被加载一次。如果本地代码被放在可多次加载的类装入器上(例如:如应用程序类装入器和WAR类装入器),确保本地代码可以正确的卸载自身并且Java代码可以正确重新加载。WebSphere对本地代码无法控制,如果它无法正确卸载或加载,应用程序会失败。如果一个本地库依赖与另一个,问题变得更加复杂。想了解详情,请在信息中心查询“独立本地库”。配置WebSphere的类装入器在前面,我们学习了WebSphere类装入器和它们如何共同工作来加载类的。在WebSphere Application Server中有一些设置可以影响类加载行为。这一节,我们来讨论这些选项。应用服务器类装入器策略对于系统中的每一个应用服务器,类加载策略可以被设置成“单个(Single)”或“多个(Multiple)”。这些设置可以在管理控制台找到:服务器-&服务器类型-&WebSphere Application Server-&服务器名称。见图4.图4 应用服务器类装入器设置当应用程序服务器类加载策略设置为单个(Single)时,在应用程序服务器(JVM)中加载EJB,工具JAR和共享库时,会使用单独的应用程序类装入器。如果WAR类装入器策略被设置为“应用程序的单个类装入器”,这个特殊应用程序的Web模块内容也被这个单个类装入器加载。当应用服务器类加载策略默认情况下设置为“多个”时,每个应用程序加载EJB,工具JAR包和共享库时会得到它们自己的类装入器。如果WAR类装入器策略设置为“应用程序中每个WAR文件的类装入器”,Web模块将会收到自己的类装入器;如果设置为“应用程序的单个类装入器”,Web模块不会收到自己的类装入器。这里有个例子可以演示。假设你有两个应用程序,Application1和Application2,运行在同一个应用服务器。每个应用程序有一个EJB模块,一个工具JAR,和两个Web模块。如果应用程序服务器类装入器策略设置为“多个”,并且每个Web模块的类装入器策略设置为“应用程序中每个WAR文件的类装入器”,结果如图5所示。图5 类装入器策略:例1每个应用程序与其他应用程序相隔离,用一个应用程序中的Web模块也与其他Web模块相隔离。WebSphere默认的类装入器策略导致应用程序之间和模块之间的完全隔离。如果你将WAR2-2模块类装入器策略改变为“应用程序的单个类装入器”,解雇如图6所示。图6 类装入器策略:例2Web模块WAR2-2被Application2的类装入器所加载,例如:Util2.jar中的类可以看到WAR2-2的/WEB-INF/classes和/WEB-INF/lib目录下的类。在最后一个例子中,如果我们将应用服务器类装入器策略改为“单个”,并且将WAR2-1的类装入器策略改为“应用程序的单个类装入器”,结果如图7所示。图7 类装入器策略:例3现在,对于Application1和Application2只有一个应用程序类装入器。Util1.jar中的类可以看到EJB2.jar,Util2.jar,WAR2-1.war和WAR2-2.war中的类。应用程序类装入器加载的类仍然无法看到WAR1-1和WAR1-2模块中的类,因为类装入器只能找到层次结构上层的类,而不能找到下层的。类加载/委托模式WebSphere应用程序类装入器和WAR类装入器都有一个类装入器顺序的设置(参见图4)。该设置决定了类装入器顺序是否要遵照普通的Java类装入器的委托机制还是要覆盖它(在前面“Java类装入器介绍”中描述)。对类加载模式,这里有两个选项:? 类已装入并且是先使用父类装入器? 类已装入并且是先使用本地类装入器(父类最后)在以前的WebSphere版本中,这些设置分别称作父类优先(PARENT_FIRST)和父类最后(PARENT_LAST)。默认的类加载模式是“类已装入并且是先使用父类装入器”。这种模式导致类装入器在尝试本地类路径上加载类之前先委托父级类加载加载。这也是默认的Java类装入器策略。如果类加载策略设置为“类已装入并且是先使用本地类装入器(父类最后)”,类装入器会现在本地类路径上加载类,然后再委托父级类装入器。这种策略可以让应用程序类装入器为父级类装入器已经存在的类提供自己的版本。注意:管理控制台在这一点比较让人迷惑。Web模块的配置中也有“类已装入并且是先使用父类装入器”和“类已装入并且是先使用本地类装入器(父类最后)”。然而,这里的“本地类装入器”实际上是指WAR类装入器,所以“类已装入并且是先使用本地类装入器”应该是“类已装入并且是先使用WAR类装入器”。假设你有一个应用程序,类似于前面例子中的Application1,并且它使用流行的log4j在EJB模块和两个Web模块中记录日志。同时,假设每个模块有自己的log4j.properties。你可以将log4j配置成工具JAR,这样你就可以在EAR文件只有一个文件了。然而,如果你那么做,你会惊奇地发现,所有模块,包括Web模块都从EJB模块加载log4j.properties。原因是,当Web模块初始化log4j包时,log4j类由应用程序类装入器加载。Log4j被配置成工具JAR。Log4j然后在它的类路径上查找log4j.properties,结果在EJB模块找到了。即使你么有在EJB模块中使用log4j,EJB模块也没有log4j.properties文件,log4j也不会再Web模块中找到log4j.properties。因为类装入器只能沿着层次结构向上查找类,而不能向下。为了结果这个问题,你可以使用下面的方法:? 创建一个单独的文件,例如:Resource.jar,将它配置为工具JAR,将所有的log4j.properties从模块移动到这个文件中,并且使它们名称唯一(比如war1-1_log4j.properties,war1-2_log4j.properties和ejb1_log4j.properties)。当从每个模块初始化log4j的时候,告诉它加载正确的配置文件,而不是默认的log4j.properties。? 保持Web模块中的log4j.properties不变(/WEB-inf/classes),为每个Web模块(/WEB-INF/lib)添加log4j.jar并且设置Web模块的类加载模式为“类已装入并且是先使用本地类装入器(父类最后)”。当从Web模块初始化log4j的时候,它从Web模块自身加载log4j.jar,然后在本地类路径找到log4j.properties。当EJB模块初始化log4j时,它从应用程序类装入器加载,并且在相同的类路径找到log4j.properties,在EJB1.jar文件中。? 如果可能,合并所有的log4j.properties为一个文件,例如Resource.jar,并且把它放到应用程序类装入器。单例:单例模式用来保证类只初始化一次。然而,一次意味着每个类装入器一次。如果你有一个单例类在两个独立的Web模块中初始化,会创建两个独立的类的实例,每个WAR类装入器加载一个。所以,在多个类装入器环境下,实现单例时要特别小心。共享库共享库是一些被多个应用程序使用的文件。Apache Struts和log4j是共享库的常见例子。我们将共享库指向一组JAR包,然后把它们和应用程序,Web模块或者应用服务器类装入器相关联。当你有一个框架的多个版本要关联到不同的应用程序时,共享库尤其有用。共享库在管理工具中定义。它们包括一个名称,一个Java类路径和加载JNI库的本地路径。我们可以在单元,节点,服务器或集群级别定义它们。然而,只是简单地定义一个库,它是不会被加载的。你必须把它和应用程序,Web模块或者加载共享库中类的应用服务器类装入器相关联。将共享库和应用服务器类装入器相关联,使得服务器上的所有应用程序都可以使用这个库。注意:如果你将共享库和应用程序相关联,不要将相同的共享库和应用服务器类装入器相关联。你可以使用如下两种方法将共享库和应用程序相关联。? 你可以用管理控制台。在企业应用程序中的引用,可以通过共享库引用添加库。? 你可以使用应用程序和共享库的manifest文件。共享库中包括一个manifest,标记它为扩展功能。应用程序中的manifest文件通过列出库的扩展名来声明了对共享库的依赖。关于该方法的更多信息,可以在信息中心查找安装选项。通过管理工具,可以将共享文件和应用服务器类装入器相关联。设置可以在服务器项找到。展开“Java和进程管理”。选择“类装入器”,点击“新建”按钮来定义一个类装入器。定义新的类装入器后,你可以修改它,并且使用“共享库引用”链接把它与需要的共享库关联。参见“第四步:使用共享库共享工具JAR”获得更多信息。类装入器查看器如果类装入器服务没有开启,那么它只显示类装入器的层次结构和类路径,不会显示每个类装入器加载的类。这意味着类装入器查看器的查询功能是无法使用的。可以通过如下方式开启类装入器查看器服务,服务器-&服务器类型-&WebSphere Application Server-&服务器名称-&类装入器查看器服务(其他属性下面)-&选中在服务器启动时启动服务。重启应用服务器后,设置生效。下一节,我们会针对不同类装入器设置给出一些例子,然后我们通过类装入器查看器演示不同的结果。通过实例学习类装入器我们已经介绍了影响类装入器行为的不同选项。在这一节,我们举个例子来使用我们前面讨论的不同选项,这样你可以更好地评估你的应用程序的最佳方案。我们创建了一个非常简单的应用,一个servlet和一个EJB。它们都调用一个类,VersionChecker,如例4所示。这个类可以打印出类是由哪个类装入器加载的。VersionChecker有一个内部值,可以打印我们使用的类的版本。这个会用来演示同一个工具JAR的多个版本的使用。 例4 VersionChecker源代码package com.itso.public class VersionChecker {static final public String classVersion = "v1.0";public String getInfo() {return ("VersionChecker is " + classVersion + ". Loaded by " + this.getClass().getClassLoader());}}安装后,可以通过http://localhost:9080/ClassloaderExampleWeb/ExampleServlet来访问。访问后会调用ExampleServlet,然后调用VersionChecker并显示类装入器。VersionCheckerV1.jar包括VersionChecker类文件,返回版本号为1.0。下面的练习,如果没有特别说明,我们使用类装入器策略和加载模式的默认设置。换句话说,应用程序有一个类装入器,WAR文件有一个类装入器。它们的委托模式都设置为“类已装入并且是先使用父类装入器”。第一步:简单的Web模块我们假设工具类只有servlet使用。我们将VersionCheckerV1.jar放在Web模块的WEB-INF/lib目录下。提示:你来放置一个Web模块使用的JAR或者这个Web模块在WEB-INF/lib能看到的JAR。当我们在这种配置下运行程序的时候,我们得到结果如例5所示。例5 类装入器:例1VersionChecker called from ServletVersionChecker is v1.0.Loaded by[war:ClassloaderExample/ClassloaderExampleWeb.war]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExample.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheckerV1.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExample.ear\ClassloaderExampleWeb.warParent:[app:ClassloaderExample]Delegation Mode: PARENT_FIRST通过输出我们可以学到如下一些东西:1. WAR类装入器的类型:com.ibm.poundClassLoader2. 它按照如下顺序搜索类ClassloaderExampleWeb.war\WEB-INF\classesClassloaderExampleWeb.war\WEB-INF\lib\VersionCheckerV1.jarClassloaderExampleWeb.warWEB-INF/classes目录包括一些未打包的资源(例如servlet类,普通Java类和配置文件),当WEB-INF/lib包括一些打包的JAR。你可以选择将Java打包成JAR文件并把它们放到lib目录下,或者你可以不打包,直接把它们放到classes目录下。它们在同一个类路径上。由于我们的实例是在Rational Application Developer上开发的,导出程序时没有将Java类打包成JAR,所以servlet在calsses目录下。WAR文件的根目录是方式代码和配置文件的第二个地方,但是你不该那么做,因为那个目录是Web服务器(如果文件服务Servlet功能是开启的,这也是默认情况)的文档根目录,也就是说在浏览器中可以访问该目录的任意文件。根据Java EE5规范,WEB-INF是受保护的,所以classes和lib目录放在WEB-INIF下面。类装入器类路径在应用启动时动态创建。现在我们可以用类装入器查看器来显示类装入器。在管理控制台,选择故障诊断-&类装入器查看器。然后展开server1-&应用程序-&ClassloaderExample-&Web模块,然后点击ClassloaderExampleWeb.war,如图8所示。图8 类装入器查看器显示应用程序树当Web模块展开后,类装入器查看器显示出类装入器层次结构,JDK扩展和JDK应用程序类装入器在上面,中间是WAR类装入器,下面是组合类装入器,见图9。图9 类装入器查看器显示类装入器层次结构如果你展开com.ibm.poundClassLoader的类路径,你会看到和VersionChecker类打印结果相同的信息(参见例5)。注意:为了让类装入器查看器显示加载的类,需要开启类装入器查看器服务,可以参考“类装入器查看器”部分。类装入器查看器有一种表格视图可以在单独一页显示每个类加载器加载的类。表格视图同样可以显示委托模式。True表示类由父级类加载器先加载,false表示类由本地类加载器先加载(父类最后),或者Web模块下的WAR类装入器。见图10。图10 类装入器查看器表格视图你可以看到,正如我们所期望的,WAR类装入器已经加载了我们的例子servlet和VersionChecker类。类装入器查看器还有一个查找功能,在这里你可以查找类,JAR文件,目录等等。在你不知道你感兴趣的类是由哪个类装入器加载时,这个功能非常有用。这个查询功能大小写敏感,但是可以使用通配符,所以你在查找*VersionChecker*时,可以查到我们的VersionChecker类。第二步:添加EJB模块和工具JAR下一步,我们要在应用程序中添加EJB,它同样依赖于我们的VersionChecker JAR文件。在这个任务中,我们在EAR的根目录添加一个VersionCheckerV2.jar文件。在这个JAR文件中的VersionChecker类返回版本2.0。为了让它成为扩展类装入器上的工具JAR,我们在EJB模块的manifest文件中添加对它的引用,见例6。例6 更新EJB模块的MANIFEST.MFManifest-Version: 1.0Class-Path: VersionCheckerV2.jar现在我们在WEB-INF/classes目录下有一个包含servlet的Web模块,在WEB-INF/lib目录下有一个VersionCheckerV1.jar文件。同时,我们有一个EJB模块,引用了在EAR的根目录的VersionCheckerV2.jar。你认为Web模块会加载哪个版本的VersionChecker类?WEB-INF/lib目录下的版本1.0还是工具JAR中的版本2.0?测试结果见例7。例7 类装入器:例2VersionChecker called from ServletVersionChecker is v2.0.Loaded by[app:ClassloaderExampleV2]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\ClassloaderExampleEJB.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\VersionCheckerV2.jarParent: Delegation Mode: PARENT_FIRSTVersionChecker called from EJBVersionChecker is v2.0.Loaded by[app:ClassloaderExampleV2]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\ClassloaderExampleEJB.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\VersionCheckerV2.jarParent: Delegation Mode: PARENT_FIRST你可以看到,从EJB模块和Web模块调用的VersionChecker都是版本2.0。原因是WAR类装入将请求委托给父级类装入器,而不是自己加载。因此,不管是在servlet还是在EJB中调用的,工具JAR都是有同一个类装入器加载的。第三步:改变WAR类装入器的委托模式如果我们想让Web模块使用WEB-INF/lib目录下的VersionCheckerV1.jar呢?对于这个任务,我们需要将类装入器的委托模式从父类优先改成父类最后。通过以下步骤将委托模式改为父类最后(PARENT_LAST):1. 在导航栏选择WebSphere企业应用程序2. 选择ClassloaderExample应用3. 选择管理模块4. 选择ClassloaderExampleWeb模块5. 将类装入器顺序改为“类已装入并且是先使用本地类装入器(父类最后)”。记住,我们在“类加载/委托模式”一节讲过,这里其实应该叫做“类已装入并且是先使用WAR类装入器”。6. 点击确定7. 保存配置8. 重新启动应用程序WEB-INF/lib中的VersionCheckerV1返回类的版本为1.0。你可以在例8中看到WAR文件中使用的是哪个版本。例8 类装入器:例3VersionChecker called from ServletVersionChecker is v1.0.Loaded by[war:ClassloaderExampleV2/ClassloaderExampleWeb.war]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\ClassloaderExampleWeb.war\WEB-INF\C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheckerV1.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\ClassloaderExampleWeb.warParent:[app:ClassloaderExampleV2]Delegation Mode: PARENT_LASTVersionChecker called from EJBVersionChecker is v2.0.Loaded by[app:ClassloaderExampleV2]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\ClassloaderExampleEJB.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV2.ear\VersionCheckerV2.jarParent: Delegation Mode: PARENT_FIRST提示: 使用这种技术可以使得Web模块使用库的特定版本,例如Struts,或者覆盖WebSphere运行时的类。将普通版本放在层次结构的顶部,将特定版本放在WEB-INF/lib目录下。Java EE 5规范没有提供标准的选项来指定EAR文件中的委托模式。然而,使用WebSphere扩展EAR文件,你可以指定该设置就不用每次重新部署应用后来改变它了。如果你使用类装入器查看器的查找功能来查找“*VersionChecker*”,你会看到两个结果,见例9。例9: 类装入器查看器的查询功能WAS Module Compound Class Loader (WAR class loader):file: / C: / WebSphereV7 / AppServer / profiles / node40a /installedApps / Cell40 / ClassloaderExampleV2.ear /ClassloaderExampleWeb.war / WEB-INF / lib / VersionCheckerV1.jarWAS Module Jar Class Loader (Application class loader):file: / C: / WebSphereV7 / AppServer / profiles / node40a /installedApps / Cell40 / ClassloaderExampleV2.ear /VersionCheckerV2.jar第四步:使用共享库共享工具JAR在这种情况下,只有一个应用程序使用VersionCheckerV2.jar文件。如果你想在多个应用程序中共享它,该怎么做呢?当然,你可以在每个EAR文件中把它打包进去。但是,如果工具JAR改变了,需要重新部署所有应用。为了避免这个问题,你可以通过共享库发布全局工具JAR。共享库可以在单元,节点,应用服务器和集群级别定义。定义共享库后,你必须将它与应用服务器,应用程序或单独的Web模块的类装入器相关联。这依赖于共享库作用的目标,WebSphere会使用适当的类装入器来加载共享库。你可以定义任意多的共享库。你可以把多个共享库和应用程序,Web模块或者应用服务器相关联。在应用程序级别使用共享库定义一个共享库VersionCheckerV2_SharedLib,将它与我们的程序ClassloaderTest相关联,需要如下步骤:1. 在管理控制台,选择环境-&共享库2. 选择共享库的作用域,例如单元,点击新建3. 指定图11所示的属性图11 共享库配置
-名称:输入VersionCheckerV2_SharedLib-类路径:输入类路径上的项,每项间按回车。注意,如果你需要绝对路径,我们建议你使用WebSphere环境变量,例如%FRAMEWORK_JARS%/VersionCheckerV2.jar。确保该变量作用域和共享库相同。
-本地库路径:输入JNI使用的DLL和.so文件-(V7新增)如果你想在应用程序间共享的类只有一个实例,选择“为该共享库使用隔离的类装入器”。4. 点击确定5. 选择应用程序-&应用程序类型-&WebSphere企业应用程序6. 选择ClassloaderExample应用7. 在引用中,选择共享库引用8. 选择ClassloaderExample9. 选择引用共享库10. 选择VersionCheckerV2_SharedLib,然后点击&&按钮来移动到已选列,如果12所示。图12 选择一个共享库11. 点击确定12. ClassloaderExample共享库配置窗口如图13所示图13 ClassloaderExample程序设置共享库13. 点击确定,保存配置如果我们从EAR文件的根目录将VersionCheckerV2.jar移走,并从EJB模块的manifest文件中移除对它的引用,然后重新启动应用服务器,我们会看到如例10所示的结果。记住Web模块的类装入器顺序还是“类已装入并且是先使用本地类装入器(父类最后)”。例10 类装入器:例5VersionChecker called from ServletVersionChecker is v1.0.Loaded by[war:ClassloaderExampleV3/ClassloaderExampleWeb.war]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleWeb.war\WEB-INF\C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheckerV1.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleWeb.war Parent:[app:ClassloaderExampleV3]Delegation Mode: PARENT_LASTVersionChecker called from EJBVersionChecker is v2.0.Loaded by[app:ClassloaderExampleV3]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleEJB.C:\Documents andSettings\Administrator\My Documents\0-Working files\Admin andConfig\Downloads\VersionCheckerV2.jar Parent:Delegation Mode: PARENT_FIRST正如我们所期望的,由于Web模块的委托模式的存在,当servlet需要VersionChecker类时,加载了VersionCheckerV1.jar。当EJB需要VersionChecker类时,它是从共享库加载的,指向C:\henrik\VersionCheckerV2.jar。如果我们想让Web模块也使用共享库,我们只需要把Web模块类装入器的顺序改回默认值,“类已装入并且是先使用父类装入器”。在应用服务器级别使用共享库共享库也可以和应用服务器相关联。所有部署在该服务器上的应用都可以看到共享库的代码。要想将共享库和应用服务器关联,你必须为应用服务器先创建一个额外的类装入器,方法如下:1. 选择应用服务器2. 在服务器栏,展开Java和进程管理,选择类装入器3. 选择新建,然后为类装入器选择类装入器顺序,“类已装入并且是先使用父类装入器”或者“类已装入并且是先使用本地类装入器(父类最后)”。点击确定。4. 点击刚创建的类装入器5. 点击共享库引用6. 点击添加,选择你想和应用服务器关联的库。重复上面操作来关联多个库。在我们的例子中,我们选择VersionCheckerV2_SharedLib。7. 点击确定。8. 保存配置。9. 重新启动应用服务器,让配置生效。由于我们已经将VersionCheckerV2共享库和应用服务器的类装入器相关联,我们会得到如例11所示的结果。例11 类装入器:例6VersionChecker called from ServletVersionChecker is v1.0.Loaded by[war:ClassloaderExampleV3/ClassloaderExampleWeb.war]Local ClassPath:C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleWeb.war\WEB-INF\C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleWeb.war\WEB-INF\lib\VersionCheckerV1.C:\WebSphereV7\AppServer\profiles\node40a\installedApps\Cell40\ClassloaderExampleV3.ear\ClassloaderExampleWeb.war Parent:[app:ClassloaderExampleV3]Delegation Mode: PARENT_LASTVersionChecker called from EJBVersionChecker is v2.0.Loaded by [server:0]Local ClassPath: C:\Documents and Settings\Administrator\MyDocuments\0-Working files\Admin andConfig\Downloads\VersionCheckerV2.jarParent: Delegation Mode: PARENT_FIRST我们新建的类装入器叫做ExtJarClassLoader,当EJB模块请求时,它加载了VersionCheckerV2.jar。根据委托模式,WAR类装入器也会加载自己的版本。提示: 进一步的详细信息,可以参考IBM JDK6 诊断指南,在DeveloperWorks的如下地址可以找到:/developerworks/java/jdk/diagnosis/60.html参考资料原文地址:http://www./redpapers/pdfs/redp4581.pdf说明图片比较直观,因此文中图片采用英文原版图片,没有改成中文版。由于水平有限,翻译中出现错误在所难免,如果对本文有疑问请参考原文。欢迎提出宝贵意见,可以通过邮箱和我联系:
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有}

我要回帖

更多关于 我愿意 严艺丹 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信