Java RMI (1)
1. Java RMI
Java Remote Method Invocation(Java远程方法调用)允许程序员创建分布式Java技术为基础的应用,可以调用不同JVM远程对象上的远程方法。RMI使用对象序列化去marshal(编码),unmarshal(解码)参数进行,不截断类型,支持面向对象的多态性。
2. Stub
RMI相当于一个代理模式。客户对象想要调用远程服务对象上的远程方法,我们需要一些辅助对象。这些辅助的对象使客户就像在调用本地对象的方法一样。客户对象调用客户辅助对象上的方法,仿佛客户辅助对象就是真正的服务。而客户辅助对象负责为我们转发这些请求,但是客户辅助对象不是真正的远程服务。虽然操作很像,但是不具有真正远程服务对象的方法逻辑。在服务端,服务辅助对象从客户辅助对象中接受请求,将调用的信息解包,然后调用真正服务对象上的真正方法。服务辅助对象从服务中得到返回值,将它打包,然后返回客户辅助对象,客户服务对象对信息解包,最后将返回值交给客户端。
Stub(存根)就相当于这里的客户辅助对象。存根将所需要的参数进行编码后传递给远程方法,并将调用结果或者异常传递给客户端。从JDK1.5开始,存根类可以采用动态代理的方式自动生成。在这之前,必须使用rmic工具手动创建。
3. java.rmi.Remote
3.1 扩展java.rmi.Remote接口
Remote是一个标记接口,没有任何方法,所有远程服务对象必须间接或者直接的扩展Remote接口。由于远程服务对象可以被其他的JVM调用,所有可以实现一个或多个远程接口。如果远程服务对象被同时的访问,必须在其实现中保证线程的安全。
public interface MyRemote extends java.rmi.Remote{} public interface MyRemote extends Remote{ public String sayHello() throws RemoteException; }
public interface MyRemote extends Remote {public String sayHello() throws RemoteException;}public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{private static final long serialVersionUID = -3510887331988311760L;protected MyRemoteImpl() throws RemoteException {} //这里必须抛出RemoteException异常,因为超类会抛出这个异常@Overridepublic String sayHello() throws RemoteException {return "server say hello to client";}} public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{private static final long serialVersionUID = -3510887331988311760L;protected MyRemoteImpl() throws RemoteException {}@Overridepublic String sayHello() throws RemoteException {return "server say hello to client";}public static void main(String[] args) {try {MyRemote remote = new MyRemoteImpl();Naming.bind("myRemoteServer", remote);} catch (RemoteException e) {e.printStackTrace();} catch (MalformedURLException e) {e.printStackTrace();} catch (AlreadyBoundException e) {e.printStackTrace();}}}public class Client {public static void main(String[] args) {try {MyRemote remote = (MyRemote)Naming.lookup("rmi://127.0.0.1/myRemoteServer");System.out.println(remote.sayHello());} catch (MalformedURLException e) {e.printStackTrace();} catch (RemoteException e) {e.printStackTrace();} catch (NotBoundException e) {e.printStackTrace();}}}