解决组件间类引用的问题
你的应用可能用到许多不同的Java类,如enterprise beans、servlets、JSP、启动类、工具类和第三方工具包。WebLogic部署应用,使每个应用具有独立的类装载器,以维持应用的独立性,便于动态再部署和卸载部署。因此,必须打包应用类,通过这种方式使每个组件可以访问到它所依赖的类。有些情况下,你必须在多个应用或组件内包括同一组类。本节讨论了WebLogic Server如何利用多个类装载器使用户可以成功准备应用。
类装载器概述
类装载器是一个JAVA类,它可以定位和装载被请求的类到Java虚拟机(JVM)中。类装载器通过搜寻classpath指定的目录和JAR文件解决类引用问题。多数Java程序拥有单一的类装载器,即缺省的JVM启动时创建的系统类装载器。WebLogic Server在部署应用时创建额外的类装载器,因此可以通过销毁(destory)这些类装载器来卸载应用。这允许WebLogic Server不须重新启动系统即可重新部署修改过后的应用。
类装载器具有分层目录结构。当启动WebLogic Server时,Java的系统类装载器被激活,它是WebLogic
Server后续创建的类装载器的父类。类装载器在查找自己的classpath之前,总是首先向自己的父类请求类。但是父类并不向子类做类搜寻的请求。
由于类装载器总是向上请求类查找,因此子类装载器不能定位找到同级别类装载器中的类。
查找协议也阐明了Java中同名类是怎么处理的。与子装载器classpath中的同名类相比,系统classpath中可以找到的类总是具有较高的优先
级。因此,在启动WebLogic Server之前,要避免将应用中的类放入系统的Java
classpath中。由于启动时创建的类装载器不能被destory,因此除非重启WebLogic Server,它包含的类将不能被重新部署。
关于应用的类装载器
当WebLogic
Server部署应用时,它创建两个新的类装载器:一个被EJB应用使用,一个被Web应用使用。EJB类装载器是系统类装载器的子类,Web类装载器是
EJB类装载器的子类。这导致Web应用中的类可以定位EJB类,但是EJB类不能定位Web应用中的类。这种层次结构的类装载器的积极的副作用是
Servlet和JSP可以直接访问EJB的实现类。因为EJB的客户端和实现类在同一个JVM中,WebLogic
Server可以绕过中间的RMI类。
如果应用包含了使用enterprise bean的servlet和JSP,则:
n 在.war文件中打包servlet和JSP
n 在.jar文件中打包enterprise bean
n 将.war和.jar文件打包到.ear文件中
n 部署.ear文件
虽然可以独立部署.war和.jar文件,但是在一个.ear文件中作为整体部署保证类装载器允许JSP和servlet可以直接访问到EJB类。如果分
开部署.war和.ejb文件,则WebLogic
Server将为他们创建同级别的类装载器。这样则需要在.war文件中包含EJB的本地和远程接口,对EJB的调用,WebLogic
Server也必须使用RMI 的stub和skeleton类,就如同EJB客户端和实现类在不同的JVM中。
关于资源适配器类
确定在你的WebLogic
Server系统classpath里没有资源适配器特定的类。如果你需要在组件(例如EJB或者Web应用)中使用资源适配器特定的类,你必须把这些类
打包到相应的归档文件(例如,在.war文件的/calsses目录下被servlets使用,在.jar文件的/classes目录下被EJB使用)
中。
一般工具类和第三方类的打包
如果创建或者获得了在多个应用中都要使用到的工具类,则必须在每个应用中都打包这个类。另一个可选的方法是改变WebLogic Server运行脚本中的java命令,将这些类添加进系统的classpath中。如果你需要修改工具类,而这些类在系统的classpath中,则必须在修改后重新启动WebLogic Server使其生效。
WebLogic Server启动时用到的Java类必须位于系统的classpath中。例如,用于连接池的JDBC驱动在WebLogic Server启动时必须处于系统的classpath中。再次强调,如果你需要修改了系统classpath中的类或修改classpath本身,则必须在修改后重新启动WebLogic Server使其生效。
处理启动类和应用之间的交互问题
启动类被创建用来在WebLogic Server启动时执行。因为启动类通过java系统classpath被定位,所以必须在启动WebLogic
Server之前,把它们放到系统classpath中。同样,启动类需要的类也必须包含在系统的classpath当中。
如果启动类使用到了应用中的类(如EJB接口),则这些类也必须包括到系统classpath当中。然而不幸的是,这意味着不重新启动系统就不能修改这些类。
使用应用对象的启动类在企图访问应用对象之前,必须等待WebLogic
Server部署应用完毕。例如,如果启动类使用了EJB,则必须在系统classpath当中包含EJB的本地和远程接口;同时还必须保证启动类在完成
部署EJB应用之前,不会创建任何的EJB实例。
宠物商店的例子中有一个启动类,验证了启动类可以等待应用完成部署。启动类com.bea.estore.startup.StartBrowser显示
了进入宠物商店应用的初始URL,在Windows中它还启动浏览器访问这个URL。StartBrowser通过执行一段while循环直到应用
deploy完毕和server开始接受连接请求。
这里给出了说明类如何工作的一段引用:
while (loop) {
try {
socket = new Socket(host, new Integer(port).intValue());
socket.close();
//launch browser
String[] cmdArray = new String[3];
cmdArray[0] = "beaexec.exe";
cmdArray[1] = "-target:browser";
cmdArray[2] = "-command:\"http://"+host+":"+port+"\"";
try {
Process p = Runtime.getRuntime().exec(cmdArray);
p.getInputStream().close();
p.getOutputStream().close();
p.getErrorStream().close();
}
catch (IOException ioe) {
}
loop = false;
} catch (Exception e) {
try {
Thread.sleep(SLEEPTIME); // try every 500 ms
} catch (InterruptedException ie) {}
finally {
try {
socket.close();
} catch (Exception se) {}
}
}
}
如果系统创建socket失败,或者BEA提供的beaexec.exe工具返回错误,类在重新进入循环之前休眠500毫秒。如果启动类需要创建EJB的实例,可以使用类似技巧,即通过循环等待,直到EJB的create方法成功。