读书人

设计方式感触之代理模式-远程代理

发布时间: 2012-06-27 14:20:08 作者: rapoo

设计模式感触之代理模式-远程代理

?

1 远程代理的意义

远程代理为一个位于不同的地址空间的对象提供一个局域代表对象,这个不同的地址空间可以是在本机器中,也可以是在另一台机器中,远程代理还有个酷炫的名字:大使。

2 远程代理的结构

远程代理是代理模式的经典应用,类似客户端/服务器模式,是远程通信的一个缩影。示意图示如下:

设计方式感触之代理模式-远程代理

?

3 代码示例:

我们需要对一家连锁店里的库存信息进行监控,以便准确的知道不同店的运行情况:

构建一个商店监视器,报告关于商店的位置和库存信息:

import java.rmi.RemoteException;public class StoreMonitor {    RemoteStore store;    public StoreMonitor(RemoteStore store) {        this.store = store;    }    public void report() throws RemoteException {        System.out.println("Store location: " + store.reportLocation());        System.out.println("Store count: " + store.reportCount());    }}

?

import java.rmi.Remote;import java.rmi.RemoteException;public interface RemoteStore extends Remote { public String reportLocation() throws RemoteException; public int reportCount() throws RemoteException;}

import java.rmi.RemoteException;import java.rmi.server.UnicastRemoteObject;public class DefaultRemoteStore extends UnicastRemoteObject implements RemoteStore { private static final long serialVersionUID = -6415918724751304895L; private int count; private String location; public DefaultRemoteStore(int count, String location) throws RemoteException { this.count = count; this.location = location; } @Override public String reportLocation() throws RemoteException { return location; } @Override public int reportCount() throws RemoteException { return count; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Remote location is: "); sb.append(location); sb.append("\n"); sb.append("Curret count is: "); sb.append(count); return sb.toString(); }}

import java.rmi.Naming;public class StoreTestDriver { public static void main(String[] args) { DefaultRemoteStore store = null; int count; if (args.length < 2) { System.out.println("..."); System.exit(1); } try { count = Integer.parseInt(args[1]); store = new DefaultRemoteStore(count, args[0]); Naming.rebind("//" + args[0] + "/store", store); } catch (Exception e) { e.printStackTrace(); } }}

import java.net.MalformedURLException;import java.rmi.Naming;import java.rmi.NotBoundException;import java.rmi.RemoteException;public class MonitorTestDriver { public static void main(String[] args) throws MalformedURLException, RemoteException, NotBoundException { String[] locations = { "rmi://localhost/store" }; StoreMonitor[] monitor = new StoreMonitor[locations.length]; for (int i = 0; i < locations.length; i++) { RemoteStore reporter = (RemoteStore) Naming.lookup(locations[i]); monitor[i] = new StoreMonitor(reporter); System.out.println(monitor[i]); } for (int i = 0; i < monitor.length; i++) { monitor[i].report(); } }}

?

代码很简单,下面说一下运行:

首先需要编译远程的服务:

>>rmic DefaultRemoteStore

有一点需要注意的是,如果是src和bin分开存放的话,rmic是针对编译之后的class文件的,此处将产生DefaultRemoteStore _Stub.class文件。

服务注册:

>>rmiregistry

此处需要注意的是:DefaultRemoteStore和DefaultRemoteStore_Stub虽然在同一路径下,但是stub不会直接加载,而是由DefaultRemoteStore在向rmi注册时,要求rmiregistry去加载DefaultRemoteStore _Stub的,也就是说生成的stub是为rmiregistry所用的。因此在执行rmiregistry之前,需要设置classpath使的stub能被识别。最简单的方式是进入到stub所在的目录再执行rmiregistry,这里应用了classpath中的当前目录“.”.

服务端提供服务:

>>java StoreTestDriver localhost 100

类似的,还可以添加一些其他的。

监视:

>>java MonitorTestDriver

将能取得注册的信息。

?

RMI现在直接使用的不多,但作为J2EE几大核心技术之一,仍应用在很多框架中。

?

读书人网 >软件开发

热点推荐