您的位置:首页 > 其它

RMI

2015-07-08 14:53 381 查看
转载自: http://haolloyin.blog.51cto.com/1177454/332426/
               http://lavasoft.blog.51cto.com/62575/91679/

      RMI(即Remote Method Invoke 远程方法调用)。基本的思路可以用一个经典比方来解释:A计算机想要计算一个两个数的加法,但A自己做不了,于是叫另外一台计算机B帮忙,B有计算加法的功能,A调用它就像调用这个功能是自己的一样方便。这个就叫做远程方法调用了。实际上RMI要得以实现还得意于Java一个很重要的特性,就是Java反射机制。

      在Java中,只要一个类extends了java.rmi.Remote接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。JavaDoc描述:Remote接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展java.rmi.Remote的接口)中指定的这些方法才可远程使用。 

      注意:extends Remote的类或者其他接口中的方法若是声明抛出了RemoteException异常,则表明该方法可被客户端远程访问调用。 

      同时,远程对象必须实现java.rmi.server.UniCastRemoteObject类,这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以Socket的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。 

      下面给出一个简单的RMI 应用,其中IService接口用于声明服务器端必须提供的服务(即service()方法),ServiceImpl类是具体的服务实现类,而Server类是最终负责注册服务器远程对象,以便在服务器端存在骨架代理对象来对客户端的请求提供处理和响应。

服务器端:
package com.zero;

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

public interface IService extends Remote {
// 声明服务器端必须提供的服务
String deal(String content) throws RemoteException;
}
package com.zero;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

//UnicastRemoteObject
//表明该具体服务对象可被导出给客户端
//用于导出的远程对象和获得与该远程对象通信的存根
public class ServiceImpl extends UnicastRemoteObject implements IService {

private String name;

/**
* 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,因此这里默认的构造方法必须写,
* 必须声明抛出RemoteException异常
*
* @throws RemoteException
*/
public ServiceImpl(String name) throws RemoteException {
this.name = name;
}

@Override
public String deal(String content) throws RemoteException {
// TODO Auto-generated method stub
return "RMI : " + this.name + " 处理----" + content;
}

}
package com.zero;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
* 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。
*
*/
public class Server {
public static void main(String[] args) throws NamingException {
try {
// 实例化实现了IService接口的远程服务ServiceImpl对象
IService service = new ServiceImpl("service");

// 本地主机上的远程对象注册表Registry的实例,并指定端口为8091,
// 这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上
LocateRegistry.createRegistry(8091);

// 把远程对象注册到RMI注册服务器上,并命名为myservice
// 绑定的URL标准格式为:rmi://host:port/name

Naming.bind("rmi://127.0.0.1:8091/myservice", service);

System.out.println("服务器向命名表注册了1个远程服务对象!");

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}
客户端:
package com.zero;

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

public interface IService extends Remote {
// 声明服务器端必须提供的服务
String deal(String content) throws RemoteException;
}
package com.zero;

import java.rmi.Naming;

import javax.naming.Context;
import javax.naming.InitialContext;

public class Client {
public static void main(String[] args) {
try {
Context namingContext = new InitialContext();
// 检索指定的对象。 即找到服务器端相对应的服务对象存根
// 这里是根据类名找的com.zero.IService,所以服务器端和客户端的相关包必须一致
IService service = (IService) Naming
.lookup("rmi://localhost:8091/myservice");

System.out.println(service.deal("你好!"));
} catch (Exception e) {
e.printStackTrace();
}
}

}
运行结果:
RMI : service 处理----你好
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: