Java RMI 远程方法调用 基础

来源:互联网 发布:整型数据占几个字节 编辑:程序博客网 时间:2024/05/17 20:39

目录:

一、简介

二、RIMI 相关类系统了解

三、RMI 基础实践

四、RMI 与 Spring 实践


一、简介

RMI:Remote Method Invocation(远程方法调用),允许程序调用虚拟机中另一个进程(服务)方法或远程主机上的某个进程(服务)的方法。它是EJB的基础。

RPC:Remote Procedure Call Protocol(远程过程调用协议),和RMI 类似,区别主要有两点:

1、调用方式的差异。RMI 是通过签名(即远程服务类注册时所绑定的访问名称)访问的,而RPC 不需要绑定,是通过类似"类名.方法名"的形式调用的,当匹配到类名与方法名后,即调用执行;

2、适用范围的不同。RMI 是java 语言的一部分,只适用于java 的应用程序。RPC 支持多语言。

上面的理解可能有误,也可理解为RPC 是泛指远程调用框架,RMI 是其Java 语言的实现。一些PRC 框架:RMI 、Hessian、Dubbo。


二、RMI 相关类系统了解


首先看下相关包与类:java.rmi 包

java.rmi.activation包:java1.2起,为远程对象的激活提供支持,即使远程对象的访问是持久的(暂时不作多了解);

java.rmi.dgc包:DGC(distribution garbage collection)类,用于垃圾传送集合算法的服务端;Lease类,请求并授予契约给远程对象,里面包含了VM标识符与契约时间;VMID,虚拟机独特ID。所以此包主要定义了远程访问的时间。

java.rmi.server包:里面我们只关注几个类:RemoteObject 与 RemoteServer抽象类、UnicastRemoteObject 类。

java.registry包:绑定服务相关的类。



从编程步骤理解几个主要的类:

1、Remote 接口(远程服务)

定义远程对象类,即定义我们的远程服务类。

继承关系:UnicastRemoteObject实现类——>继承RemoteServer抽象类——>继承RemoteObject抽象类(实现了Serilazible接口)——>实现了Remote接口(空接口)。

远程对象类(服务类)都需继承Remote 的实现类,常用UnicastRemoteObject 类,但具体的业务逻辑可单独定义在实现了Remote 的接口中(必须直接或间接实现Remote),并在自己的服务类中实现自己的服务接口。

UnicastRemoteObject .java

public class UnicastRemoteObject extends RemoteServer {    //暴露此服务到哪个端口    private int port = 0;    //客户端的Socket工厂(如果有的话)    private RMIClientSocketFactory csf = null;    //服务端的Socket工厂(如果有的话)    private RMIServerSocketFactory ssf = null;    //jdk1.1     private static final long serialVersionUID = 4974527148936298033L;    //暴露此服务,同时设置通信的端口    protected UnicastRemoteObject() throws RemoteException    {        this(0);//端口为0将使用匿名(anonymous)端口1099    }    protected UnicastRemoteObject(int port) throws RemoteException;    //jdk1.2 起    protected UnicastRemoteObject(int port,RMIClientSocketFactory csf,RMIServerSocketFactory ssf)throws RemoteException;    public Object clone() throws CloneNotSupportedException;    @Deprecated    public static RemoteStub exportObject(Remote obj)throws RemoteException;    public static Remote exportObject(Remote obj, int port)throws RemoteException    public static Remote exportObject(Remote obj, int port,RMIClientSocketFactory csf,RMIServerSocketFactory ssf) throws RemoteException;    public static boolean unexportObject(Remote obj, boolean force)throws java.rmi.NoSuchObjectException;}

2、Registry 接口(注册与绑定远程对象的接口)

绑定某个远程对象到某个地址。

Registry 接口定义:

public interface Registry extends Remote{    //默认注册在1099 端口    public static final int REGISTRY_PORT = 1099;    //lookup    public Remote lookup(String name)throws RemoteException, NotBoundException, AccessException;    //bind    public void bind(String name, Remote obj)throws RemoteException, AlreadyBoundException, AccessException;    //unbind    public void unbind(String name)throws RemoteException, NotBoundException, AccessException;    //rebind    public void rebind(String name, Remote obj)throws RemoteException, AccessException;    //list    public String[] list() throws RemoteException, AccessException;}

3、LocateRegistry (final 工具类):

用于获得上面的Registry 接口对象。即获得远程对象的与某个主机与端口关联的注册对象。

public final class LocateRegistry{    //此处只展示公有属性与方法    //返回localhost 的1099 端口的注册对象    public static Registry getRegistry();    //返回localhost指定端口的注册对象    public static Registry getRegistry(int port);    //返回某个主机的1099 端口的注册对象    public static Registry getRegistry(String host)throws RemoteException;//端口默认1099    public static Registry getRegistry(String host, int port)throws RemoteException    //还指定通信使用的对象    public static Registry getRegistry(String host, int port, RMIClientSocketFactory csf)throws RemoteException    //在本地创建一个注册对象并暴露,并指定只接受哪个端口的请求。port:仅来源于该port 的请求能访问该注册对象上注册的    //远程服务。暴露过程就类似 UnicastRemoteObject.exportObject(Remote,int)被调用一样    public static Registry createRegistry(int port) throws RemoteException    public static Registry createRegistry(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws       RemoteException}

3、Naming 工具类(final 类工具类)

上面的LocalRegistry 类用户获得注册对象,而该类用于在注册对象上绑定与获得远程对象(Remote 对象)。

public final class Naming{    //name:URL 格式的名字,返回一个Remote 对象的参考。即在注册机处查找远程服务。    public static Remote lookup(String name) throws NotBoundException,RemoteException;    //name:同上。obj:远程对象。    public static void bind(String name,Remote obj) throws AlreadyBoundException,RemoteException;    //解绑定    public static void unbind(String name)throws NotBoundException,RemoteException;    //重新绑定(重新指为某个名字绑定新的远程对象,该名字对应的所有旧的绑定都将被该绑定替换)    public static void rebind(String name,Remote obj) throws RemoteException,java.net.MalformedURLException;    //查找登记处已绑定的所有名字    public static String[] list(String name) throws RemoteException,java.net.MalformedURLException;}
说明:

通过源码可知,Naming 类的方法是首先通过传入的name 参数(URL)查找在该URL 主机与端口上注册的注册对象,然后通过调用该注册对象的lookup、unbind 等方法实现将Remote 对象绑定与解绑的。即可通过Naming 发布远程服务,而不需通过Registry 对象。


疑问:UnicastRemoteObject .java 的 exportObject 方法与 Naming 类的bind 方法有什么区别?

前者仅用于将远程对象(服务对象)注册到localhost 的某个端口,而后者除了可以注册到本地某端口,也可注册到某个主机某端口,同时还可进行解绑,重新绑定等操作。


小结:

Remote 接口:提供远程服务的对象;

Registry 接口:绑定远程服务对象的接口;

LocalRegistry 类:创建并暴露与某个主机某个端口绑定的Registry 对象的工具类;

Naming 类:绑定Remote 服务到某个URL(实际还是调用了LocalRegistry 获得Registry ,最终通过Registry 实现绑定的);

UnicastRemoteObject 类:Remote 接口的实现类,所有的远程服务类都必须继承该类或另外一个类(Activatable 类)。该类可以将自己绑定到某个端口,而不需通过Naming 等类。


注:

以URL 形式的参数作为绑定name:http://localhost:1099/remoteObjName


三、RMI 基础实践


四、RMI 与 Spring 实践






原创粉丝点击