您的位置:首页 > 编程语言 > Java开发

Java分布式通信之RMI

2016-04-28 16:50 513 查看
RMI概述

在Java中实现远程调用的方式主要有两种技术,一个是RMI,一个是webservice,本次主要讲解RMI技术。RMI是Remote Method Invocation缩写,是Java用于透明远程调用的重要机制,它使客户机上运行的程序可以调用远程服务器上的对象,在远程调用中,客户端只要拥有服务端提供的接口,通过此接口实现对远程服务端的调用,它的目的在于对开发人员屏蔽横跨不同JVM和网络连接等细节,使得分布在不同JVM上的对象像是存在于一个统一的JVM中一样,可以很方便的互相通讯。

实现机制

RMI 服务端通过启动注册对象监听在某一端口上对外提供服务的接口,接口的实现类在注册对象上注册并命名。客户端通过代理的访问实现对服务端接口的访问,即在客户端需持有该接口,客户端将要访问服务端的对象的命名、方法名和参数封装成一个对象,序列化后传输到服务端,服务端接受到请求后解析对象的命名、方法和参数,通过命名从已在服务端注册的对象里查找,之后结合要访问的方法,利用反射技术找到对应的对象实例,传入参数完成对服务端实例的调用。

使用RMI时服务端的接口要实现remote接口,接口里的每个方法必须抛出RemoteException,服务端的业务类实现此接口来提供相关的业务功能,然后通过UnicastRemoteObject.exportObject讲此对象绑定至某个端口,最后将此对象注册至本地的LocateRegistry并命名,下面举个简单例子。

示例代码

服务端接口

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Business extends Remote
{
public String action(String arg)throws RemoteException;

}


注意接口必须继承Remote接口,接口里的方法必须抛出RemoteException!

服务端实现类

public class BusinessImpl implements Business
{

@Override
public String action(String arg)
{
System.out.println("your  request has been received!!!:"+arg);
return  arg;
}


这里偷个懒写的简单些。。。,意思到了。。。

服务端注册类

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;

public class Server
{
public static void main(String[] args) throws RemoteException
{

//注册命名
String name="BusinessName";
Business business=new BusinessImpl();
//注册类
UnicastRemoteObject.exportObject(business, 0);
//注册监听端口
Registry registry=LocateRegistry.createRegistry(1099);
registry.rebind(name, business);
}
}


注:绑定服务的默认端口为1099,如果使用了这个端口,则可以直接使用,当然你也可以自定义端口。

客户端

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

public class Client
{
public static void main(String[] args) throws Exception
{
//如果使用自定义端口,则调用LocateRegistry.getRegistry(String host,int port)
Registry registry=LocateRegistry.getRegistry("localhost");
String name="BusinessName";
Business business=(Business)registry.lookup(name);
business.action("哈哈,我是RMI客户端");
}
}


LocateRegistry方法摘要:

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 的远程引用。


然后运行server类,在运行client类,控制台输出客户端发送的并经过服务端处理的参数:

your  request has been received!!!:哈哈,我是RMI客户端


总结

从上面的过程来看,RMI对服务器的IP地址和端口依赖很紧密,但是在开发的时候不知道将来的服务器IP和端口如何,但是客户端程序依赖这个IP和端口。这也是RMI的局限性之一。这个问题有两种解决途径:一是通过DNS来解决,二是通过封装将IP暴露到程序代码之外。

RMI的局限性之二是RMI是Java语言的远程调用,两端的程序语言必须是Java实现,对于不同语言间的通讯可以考虑用Web Service或者公用对象请求代理体系(CORBA)来实现.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: