java.rmi.Naming和java.rmi.registry.LocateRegistry的区别

java.rmi.Naming

Naming类提供存储和获得“远程对象注册表”上远程对象的引用的方法。

“class provides methods for storing and obtaining references to remote objects in a remote object registry. ”

Naming 类的每个方法都可将某个名称作为其一个参数,该名称是使用以下形式的 URL 格式(没有 scheme 组件)的 java.lang.String:
     //host:port/name

一个//ip:port/name可以唯一定位一个RMI服务器上的发布了的对象

“Each method of the Naming class takes as one of its arguments a name that is a java.lang.String in URL format (without the scheme component) of the form:
    //host:port/name”

其中 host 是注册表所在的主机(远程或本地),port 是注册表接受调用的端口号,name 是未经注册表解释的简单字符串。host 和 port 两者都是可选项。如果省略了 host,则主机默认为本地主机。如果省略了 port,则端口默认为 1099,该端口是 RMI 的注册表 rmiregistry 使用的“著名”端口。

方法摘要
static void bind(String name, Remote obj) 
          将指定 name 绑定到远程对象。
static String[] list(String name) 
          返回在注册表中绑定的名称所组成的数组。
static Remote lookup(String name) 
          返回与指定 name 关联的远程对象的引用(一个 stub)。
static void rebind(String name, Remote obj) 
          将指定名称重新绑定到一个新的远程对象。
static void unbind(String name) 
          销毁与远程对象关联的指定名称的绑定。

实际上,从源码中可以看出,Naming类中的上述方法都是通过Registry类对“远程对象注册表”进行操作的。

public interface Registry extends Remote;

    public static Remote lookup(String name)
	throws NotBoundException,
	    java.net.MalformedURLException,
	    RemoteException
    {
	ParsedNamingURL parsed = parseURL(name);
	Registry registry = getRegistry(parsed);

	if (parsed.name == null)
	    return registry;
	return registry.lookup(parsed.name);
    }

    public static void bind(String name, Remote obj)
	throws AlreadyBoundException,
	    java.net.MalformedURLException,
	    RemoteException
    {
	ParsedNamingURL parsed = parseURL(name);
	Registry registry = getRegistry(parsed);

	if (obj == null)
	    throw new NullPointerException("cannot bind to null");

	registry.bind(parsed.name, obj);
    }

    public static void unbind(String name)
	throws RemoteException,
	    NotBoundException,
	    java.net.MalformedURLException
    {
	ParsedNamingURL parsed = parseURL(name);
	Registry registry = getRegistry(parsed);

	registry.unbind(parsed.name);
    }

    public static void rebind(String name, Remote obj)
	throws RemoteException, java.net.MalformedURLException
    {
	ParsedNamingURL parsed = parseURL(name);
	Registry registry = getRegistry(parsed);

	if (obj == null)
	    throw new NullPointerException("cannot bind to null");

	registry.rebind(parsed.name, obj);
    }

注意: Naming类只是在“远程对象注册表”上进行存储和读取操作,该类并不能创建“远程对象注册表”。

java.rmi.registry.LocateRegistry

LocateRegistry 用于获取特定主机(包括本地主机)上的远程对象注册表的引用,或用于创建一个接受对特定端口调用的远程对象注册表。

“LocateRegistry is used to obtain a reference to a bootstrap remote object registry on a particular host (including the local host), or to create a remote object registry that accepts calls on a specific port.”

方法摘要
static Registry createRegistry(int port) 
          创建并导出接受指定 port 请求的本地主机上的 Registry 实例
static Registry createRegistry(int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) 
          在本地主机上创建并导出 Registry 实例,该本地主机使用的是与该实例通信的自定义套接字工厂。
static Registry getRegistry() 
          返回本地主机在默认注册表端口 1099 上对远程对象 Registry 的引用。
static Registry getRegistry(int port) 
          返回本地主机在指定 port 上对远程对象 Registry 的引用。
static Registry getRegistry(String host) 
          返回指定 host 在默认注册表端口 1099 上对远程对象 Registry 的引用。
static Registry getRegistry(String host, int port) 
          返回指定的 host 和 port 上对远程对象 Registry 的引用。
static Registry getRegistry(String host, int port, RMIClientSocketFactory csf) 
          返回本地创建的指定 host 和 port 上对远程对象 Registry 的远程引用。

所以,实际上通过LocateRegistry类方法获取到的是Registry对象引用(一个 stub),然后我们可以通过该Registry对象引用对“远程对象注册表”进行操作的。更进一步,没有Naming类照样可以进行所有的操作。

总结:

所以,java.rmi.Naming和java.rmi.registry.LocateRegistry的区别就比较明显了:

1. Naming类只是在“远程对象注册表”上进行存储和读取操作,该类并不能创建“远程对象注册表”;

2. LocateRegistry类可以获取“远程对象注册表”引用,或者创建本地主机上的“远程对象注册表”;

3. Naming类方法封装了Registry接口方法,只需要一个URL就能对“远程对象注册表”进行相关操作,比如:

IHello hello = new HelloImpl();
java.rmi.Naming.rebind("rmi://localhost:1099/hello", hello); /* URL和对象绑定 */

IHello hello = (IHello) Naming.lookup("rmi://localhost:1099/hello"); /* 通过URL获取对象引用 */

4. LocateRegistry类获取到Registry对象引用后,通过Registry类方法对“远程对象注册表”进行相关操作,比如:

<span style="font-weight: normal;"><span style="font-size:14px;">String hostName="192.168.1.22";//RMIService的地址
int port=33333;//RMIService监听的端口
Registry registry=LocateRegistry.getRegistry(hostName,port);
Hello hello=(Hello)registry.lookup("HelloServer");</span></span>

<span style="font-weight: normal;"><span style="font-size:14px;">int port = 33333;//RMIService监听的端口,自己指定!
registry = LocateRegistry.createRegistry(port);//在RMIServer上创建
registry.rebind("HelloServer", helloServer); //HelloServer就是对外暴露出的名称</span></span>

参考:

1. http://docs.oracle.com/javase/6/docs/api/java/rmi/Naming.html

2. http://download.oracle.com/technetwork/java/javase/6/docs/zh/api/java/rmi/Naming.html

3. http://stackoverflow.com/questions/8330295/difference-between-java-rmi-naming-and-java-rmi-registry-locateregistry





没有更多推荐了,返回首页