初识JavaRMI原理(转)

RMI (即 Remote Method Invoke  远程方法调用)。在 Java 中,只要一个类 extends java.rmi.Remote 接口,即可成为存在于服务器端的远程对象,供客户端访问并提供一定的服务。 JavaDoc 描述:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在 远程接口 (扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。 
 
注意:extends Remote 接口的类或者其他接口中的方法若是声明抛出了 RemoteException 异常,则表明该方法可被客户端远程访问调用。 
 
同时,远程对象必须实现 java.rmi.server.UniCastRemoteObject 类,这样才能保证客户端访问获得远程对象时,该远程对象将会把自身的一个拷贝以 Socket 的形式传输给客户端,此时客户端所获得的这个拷贝称为“存根”,而服务器端本身已存在的远程对象则称之为“骨架”。其实此时的存根是客户端的一个代理,用于与服务器端的通信,而骨架也可认为是服务器端的一个代理,用于接收客户端的请求之后调用远程方法来响应客户端的请求。 
 
RMI  框架的基本原理大概如下图,应用了代理模式来封装了本地存根与真实的远程对象进行通信的细节。
下面给出一个简单的RMI  应用,其中类图如下:其中 IService 接口用于声明服务器端必须提供的服务(即 service() 方法), ServiceImpl 类是具体的服务实现类,而 Server 类是最终负责注册服务器远程对象,以便在服务器端存在骨架代理对象来对客户端的请求提供处理和响应。
各个类的源代码如下:
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IService extends Remote {

	// 声明服务器端必须提供的服务
	public String service(String content) throws RemoteException;
}




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

//UnicastRemoteObject用于导出的远程对象和获得与该远程对象通信的存根。
public class ServiceImpl extends UnicastRemoteObject implements IService {

	private String name;

	protected ServiceImpl(String name) throws RemoteException {
		this.name = name;
	}

	@Override
	public String service(String content) throws RemoteException {

		System.out.println(content + " ---------  我被客户端调用了 ---------");
		return "server------>" + content;
	}

}



import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

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

public class Server {

	public static void main(String[] args) {
		try {

			// 实例化实现了IService接口的远程服务ServiceImpl对象
			IService service01 = new ServiceImpl("service01");

			// 初始化命名空间
			Context ct = new InitialContext();

			LocateRegistry.createRegistry(8888);

			// 将名称绑定到对象,即向命名空间注册已经实例化的远程服务对象
			ct.rebind("rmi://127.0.0.1:8888/service01", service01);

			System.out.println(">>>>>INFO:远程service对象绑定成功!>>>>>");

		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}
}



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

public class Client {

	public static void main(String[] args) {

		String url = "rmi://localhost:8888/";

		try {
			Context ct = new InitialContext();
			// 检索指定的对象 即找到服务器端相对应的服务对象存根
			IService service = (IService) ct.lookup(url + "service01");

			System.out.println(service + " is :" + service.getClass().getName()
					+ " instance");

			Class<?>[] sInterfaces = service.getClass().getInterfaces();

			for (Class<?> clazz : sInterfaces) {
				System.out.println(" interface is " + clazz.getName());
			}

			String str = service.service("你好");

			System.out.println(str);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


 
其实整个简单的 RMI  应用中各个类的交互时序如下图:
 
 推荐一篇更完善的文章:http://ryxxlong.iteye.com/blog/1560535
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值