RMI 入门

 

1、  RMI(Remote Method Invocation)概念

 

RMI是远程方法调用的简称,象其名称暗示的那样,它能够帮助我们查找并执行远程对象的方法。通俗地说,远程调用就象将一个class放在A机器上,然后在B机器中调用这个class的方法。

让某个java虚拟机上的对象调用另一个java虚拟机中的对象和方法。

 

 

 

2、RMI术语

在研究代码之前,我们来看看必须编写哪些代码:

 

·远程对象:Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在“远程接口”(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。

 

·远程对象实现:这是一个实现远程对象的类。如果实现了远程对象,就能够覆盖该对象中的所有方法,因此,远程对象的实现类将真正包含我们希望导出的方法的代码。

 

·远程服务器:这是一个作为服务器使用的类,它是相对于要访问远程方法的客户端而言的。它存储着绑定的字符串和对象。

 

·远程客户端:这是一个帮助我们访问远程方法提供帮助的类,它也是最终用户。我们将使用查找和调用远程方法的方法在该类中调用远程方法。

 

 

Stub(存根)和Skeleton(骨架)

   Stub和Skeleton是经过rmic命令生成的,我们的程序要通过远程调用,底层一定是套接字的字节传输,要一个对象序列化成为一个字节数组,传输到服务器或者客户端的对端之后,再把该对象反序列化成为对应的对象,这些网络传输的过程要求安全,稳定等等非常麻烦的操作,Stub驻留客户端,承担着代理远程对象的实现者的角色,Skeleton类帮助远程对象与Stub再RMI连接上进行通信。RMI的客户与Stub进行交换,Stub与Skeleton通信,Skeketon负责与服务器进行交互,因此有了Stub和Skeleton之后我们就不需要实现底层通信的细节,我们进行的远程调用,只需要通过接口对方法进行操作即可,使分布式调用实现了位置上的透明,即:远程调用就像本地调用一样。

 

下面这个例子是在网上搜的,觉得挺好的,这里就摘录 了

 

 

 

1. 创建远程接口及声明远程方法(ICal.java)

 

 

/**
 * 如果想要用 远程对象调用 接口必须要继承Remote或者类必须要实现Remote接口 
 */
public interface ICal extends Remote {
//接口定义的方法需要抛出RemoteException异常
	public int sum(int add1, int add2) throws RemoteException;

}

 

 2. 实现远程接口及远程方法(继承UnicastRemoteObject)(ICalImpl.java)

 

UnicastRemoteObject 类用于导出带 JRMP 的远程对象和获得与该远程对象通信的 stub,即使远程对象具有相应的存根,并使它能够远程客户的方法调用请求。该类实现了Serializable, Remote接口,可以实现底层的序列化对象网络传输的需求。

 

public class ICalImpl extends UnicastRemoteObject implements ICal {

	protected ICalImpl() throws RemoteException {
		super();
	}
	private static final long serialVersionUID = 1L;

	@Override
	public int sum(int add1, int add2) throws RemoteException {
		System.out.println("server : add1=" + add1 + ",add2=" + add2);
		return add1 + add2;
	}

}

 

public interface IHello extends Remote {

	public String sayHello(String name) throws RemoteException;
}

 

public class IHelloImpl extends UnicastRemoteObject implements IHello {
	private static final long serialVersionUID = 1L;

	protected IHelloImpl() throws RemoteException {
		super();
	}
	@Override
	public String sayHello(String name) throws RemoteException {
		System.out.println("server : " + name + " come here ");
		return "hello " + name;
	}

}

 

3. 启动RMI注册服务,并注册远程对象(Server.java)

public class Server {

	public static void main(String[] args) {
		//声明我要暴露的对象
		try {
			ICal    cal = new ICalImpl();
			IHello  hello = new IHelloImpl();
	        //本地主机上的远程对象注册表Registry的实例,并指定端口为 1100,
		//这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 
            LocateRegistry.createRegistry(1100); 
            Naming.bind("rmi://127.0.0.1:1100/IHello",hello);
            Naming.bind("rmi://127.0.0.1:1100/ICal",cal);
            
            System.out.println("Server already be started up ");
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (AlreadyBoundException e) {
			e.printStackTrace();
		}
		
	}

}

 

4. 客户端查找远程对象,并调用远程方法(RmiClient.java)

 

客户端只需要保有业务接口,不应该保有业务类的实现类。这样做的好处是一端服务器端业务实现发生了改变,而客户端可以通过RMI来获得改变的具体业务对象,所以这样我们可以在客户端执行大量的操作,可以只将持久化操作交由服务器。

 

public class RmiClient {

	public static void main(String[] args) {
		try {
			ICal cal = (ICal)Naming.lookup("rmi://127.0.0.1:1100/ICal");
			IHello hello = (IHello)Naming.lookup("rmi://127.0.0.1:1100/IHello");
			System.out.println(cal.sum(2, 3));
			System.out.println(hello.sayHello("kaobian"));
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		} catch (NotBoundException e) {
			e.printStackTrace();
		}
	}
	
}

 

 5. 执行程序:启动服务Server;运行客户端RmiClient进行调用

 

运行结果:

1、启动Server: Server already be started up 

2、启动RmiClient : 

Server :

server : add1=2,add2=3

server : kaobian come here 

Client:

5

hello kaobian

 

备注:RMI是线程同步的,即获取远程对象,执行其方法,server端如果一直没有返回值,则客户端一直等待返回的结果,可以使用debug模式测试一下。

 

lookup("Hello")默认为从本机 127.0.0.1的1099端口上查找Hello命令对象

lookup("192.168.1.105/Hello")与原语句是同等的,因为默认端口号就是1099。

HelloInterface hello = (HelloInterface)Naming.lookup("//192.168.1.105:1099/Hello");

 

  • 大小: 34.9 KB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值