为什么会有RMI
一个系统中可能会有多个功能模块,不同的功能模块可能分布在不同的机器上面.不同的功能模块中可能存在着互相调用(比如支付调用账户模块的查询用户的功能).我们知道不同jvm是没法通过XX.XXX()的方式互相调用的.那么不同的功能模块是怎么互相调用的呢?我们会想到http协议.诚然,http确实也能解决我们的问题,但是http属于应用层协议,速度得不到保证,而且调用http怎么看都感觉不够优雅.有没有更快,更优雅(像我们平时XXX.XXX())的方法呢.基于TCP协议的rmi就是一个不错的选择.
RMI是什么
RMI:远程方法调用(Remote Method Invocation)。能够让在某个java虚拟机上的对象像调用本地对象一样调用另一个java 虚拟机中的对象上的方法。
RMI 的简单实例
功能: 服务端Server的HelloService有一个sayHello的方法,客户端Client通过RMI协议调用它.
定义一个远程接口类 :
/**
* 只有继承了Remote的接口类才具有被远程调用的资格
*/
public interface HelloService extends Remote {
/**
* 只有抛出RemoteException的类才具有远程调用的资格
* @param name
* @throws RemoteException
*/
void sayHello(String name) throws RemoteException;
}
定义实现类:
/**
* 远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,
* 该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,
* 而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,
* 而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。
* java.rmi.server.UnicastRemoteObject构造函数中将生成stub和skeleton
*/
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {
/**
* 必须有一个显示的构造函数,并且抛出RemoteException的异常
*/
public HelloServiceImpl()throws RemoteException{
super();
}
@Override
public void sayHello(String name) throws RemoteException {
System.out.println("name = " + name);
}
}
Server服务端 :
LocateRegistry.createRegistry(1099);
String url = "rmi://localhost:1099/HelloService";
// 生成stub和skeleton,并返回stub代理引用
// 本地创建并启动RMI Service,被创建的Registry服务将在指定的端口上侦听到来的请求
// 实际上,RMI Service本身也是一个RMI应用,我们也可以从远端获取Registry:
// public interface Registry extends Remote;
// public static Registry getRegistry(String host, int port) throws RemoteException;
Naming.rebind(url, new HelloServiceImpl());
Client客户端:
String url = "rmi://localhost:1099/HelloService";
HelloService helloService = (HelloService) Naming.lookup(url);
helloService.sayHello("huangzp");
先执行server代码,再执行client代码,server会输出name=huangzp
网友评论