最近公司项目完成了第一阶段,结束了天天加班的日子,终于有时间来补强自己的"知识架构"了.公司产品的系统架构中用到了EJB, 为了掌握每一种J2EE的架构设计,决定结合公司的产品(代码)和经典的《Master EJB》来学习。
注:J2EE有很多不同的组件,其架构就是根据业务的需求,选择合适的组件来组合成系统。当然根据不同的逻辑划分和分层,有不同的J2EE类型。关于这个问题,将会在另一篇文章中讨论。
介绍EJB的第一章:EJB基础开门见山地提到,java RMI-IIOP and JNDI是EJB的技术基础,要深刻得理解EJB,就要先掌握这两个技术。而java RMI-IIOP是java RMI和CORBA结合的产生物,掌握java RMI和CORBA的机制就变成了先决条件。本篇将会通过一些简单的代码samples(原创)来演示java RMI和 java RMI-IIOP的工作机制。
RMI(Remote Method Invocation),顾名思义就是一种Java远程方法调用的机制(类似于RPC),为开发分布式的应用程序服务。通过使用RMI,分布式应用可以实现跨进程调用,也就是一个jvm内的对象可以调用另一个jvm中对象的方法,而且使用的程序语法规则和在本地机上对象间的方法调用的语法规则一样。
它的好处是显而易见的:
1. 屏蔽了底层的TCP/Socket网络实现细节,简化了应用程序的开发,让开发者能集中所有的精力在业务逻辑的设计和实现上。
2. 继承了Java本身面向对象的特点,可以传递对象(该对象必须实现Java.io.Serializable Interface)。
3. 优化了分布式系统的设计。由于可以直接传递对象及其属性,可以应用面向对象的设计方式。
4. 提供了Java内置的安全机制,通过定义不同的policy授权文件来限制跨进程的程序调用,增强了体统的安全性。
而创建一个RMI应用程序需要以下5个步骤:
1.定义一个接口去直接或者间接继承java.rmi.Remote接口,该接口声明所有需要暴露给客户端的远程方法,而且每个声明的远程方法必须抛出java.rmi.Remote异常或者其父类(java.io.IOException,java.lang.Exception)。如果在远程调用过程中,发生网络错误,将会抛出Remote Exception.另外,该接口必须暴露给客户端,即意味着提供给客户端的jar文件中必须包括该class.
2.定义一个具体的类去实现该远程接口,实现所有暴露给客户端的远程方法。客户端不应该知道其的存在,不能直接调用它。该实现类通常继承java.rmi.server.UnicasRemoteObject类(顾名思义,是让客户机与服务器对象实例建立一对一的连接。),不然还得考虑怎么export远程对象去接收远程方法调用。 注意:该实现类还可以有其他没有暴露在远程接口的方法。
3.使用RMIC程序生成远程实现所需的存根(Stub)和骨架(Skeleton),该存根是一个名字为%步骤2中实现类的类名%_Stub.class 文件。在jdk1.4以上环境中,Skeleton不会显性地生成。
4.创建RMI server, 可以通过一个线程或者一个Servlet程序去启动该server. 该server去注册一个RMI服务,并且把远程对象绑定到RMI服务中。实际项目应用中,一定要记得在server中加入安全机制,不然该server就要变成菜市场了。
5.创建客户端程序,进行RMI调用。同样,这里也应该加入安全机制。
可运行的Sample代码由于贴出来比较长,加上是原创,已经压缩成文件上传到csdn了。http://download.csdn.net/source/1686205
要想运行成功,还有以下几点要注意,不然会让初次接触RMI者困惑不已。
1. 当运行server时,经常碰到提示说找不到Stub类,而Stub class明明就在那。其实,当你的server运行的时候,会去注册一个类到RMI服务器,自然RMI服务器必须要能找到你的stub类在哪,即jdk的rmiregistry 必须要能找到Stub类。解决方案有两种,通过-Djava.rmi..server.codebase这个运行参数来指定(推荐),或者把Stub类加到你的classpath中。
2. 客户端可直接运行。
3. 不管是服务器端还是客户端,如果加了安全机制,都必须提供安全授权文件。不然会碰到类似以下的异常:java.security.AccessControlException: access denied(java.net.SocketException IP:Port connect,resolve). 当然简单起见,你可以去修改jre的安全配置文件(%jdk目录%/jre/lib/security/java.policy),来开放权限。但实际项目中,不推荐该方式。在运行服务器或者客户端的时候使用运行参数:-Djava.security.policy=%安全配置文件全路径名%。例如:
Java -Djava.security.policy=test.policy CalculatorServer