SimpleClient客户端通过HelloService代理类来调用SimpleServer
服务器端的HelloServiceImpl 对象的方法。客户端的HelloService 代理类也实现了
HelloService 接口,这可以简化SimpleClient 客户端的编程。对于SimpleClient 客户端而言,与远程服务器的通信的细节被封装到HelloService代理类中。SimpleClient客户端可以按照以下方式调用远程服务器上的HelloServiceImpl对象的方法:
//创建HelloService 代理类的对象
HelloService helloService1=new HelloServiceProxy(connector);//通过代理类调用远程服务器上的HelloServiceImpl 对象的方法
System.out.println(helloService1.echo("hello"));
从以上程序代码可以看出,SimpleClient客户端调用远程对象的方法的代码与调用
本地对象的方法的代码很相似,由此可以看出,代理类简化了客户端的编程。
Connector 类负责建立与远程服务器的连接,以及接收和发送Socket对象。如例程
10-17 所示是Connector 类的源程序。
例程10-17 Connector.java
package reflection.proxy.dynamic;
import java.io.*;
import java.net.*;
//Connector 类负责建立与远程服务器的连接,以及接收和发送Socket对象
public class Connector {
private String host;
private int port;
private Socket skt;
private InputStream is;
private ObjectInputStream ois;
private OutputStream os;
private ObjectOutputStream oos;
public Connector(String host, int port) throws Exception {
this.host = host;
this.port = port;
connect(host, port);
}
public void send(Object obj) throws Exception { // 发送对象
oos.writeObject(obj);
}
public Object receive() throws Exception { // 接收对象
return ois.readObject();
}
public void connect() throws Exception { // 建立与远程服务器的连接
connect(host, port);
}
public void connect(String host, int port) throws Exception { // 建立与远程服务器的连接
skt = new Socket(host, port);
os = skt.getOutputStream();
oos = new ObjectOutputStream(os);
is = skt.getInputStream();
ois = new ObjectInputStream(is);
}
public void close() { // 关闭连接
try {
} finally {
try {
ois.close();
oos.close();
skt.close();
} catch (Exception e) {
System.out.println("Connector.close: " + e);
}
}
}
}
HelloService代理类有两种创建方式:一种方式是创建一个HelloServiceProxy静态
代理类,如例程10-18 所示;还有一种方式是创建HelloService的动态代理类,如例程
10-19 所示ProxyFactory 类的静态getProxy()方法就负责创建HelloService 的动态代理类,并且返回它的一个实例。
例程10-18 HelloServiceProxy.java(静态代理类)
package reflection.proxy.dynamic;
import java.rmi.RemoteException;
import java.util.Date;
public class HelloServiceProxy implements IHelloService {
private String host;
private int port;
public HelloServiceProxy(String host, int port) {
this.host = host;
this.port = port;
}
public String echo(String msg) throws RemoteException {
Connector connector = null;
try {
connector = new Connector(host, port);
Call call = new Call("reflection.proxy.dynamic.IHelloService",
"echo", new Class[] { String.class }, new Object[] { msg });
connector.send(call);
call = (Call) connector.receive();
Object result = call.getResult();
if (result instanceof Throwable)
throw new RemoteException("", (Throwable) result); // 把异常都转换为RemoteException
else
return (String) result;
} catch (Exception e) {
throw new RemoteException("", e); // 把异常都转换为RemoteException
} finally {
if (connector != null)
connector.close();
}
}
public Date getTime() throws RemoteException {
Connector connector = null;
try {
connector = new Connector(host, port);
Call call = new Call("reflection.proxy.dynamic.IHelloService",
"getTime", new Class[] {}, new Object[] {});
connector.send(call);
call = (Call) connector.receive();
Object result = call.getResult();
if (result instanceof Throwable)
throw new RemoteException("", (Throwable) result); // 把异常都转换为RemoteException
else
return (Date) result;
} catch (Exception e) {
throw new RemoteException("", e); // 把异常都转换为RemoteException
} finally {
if (connector != null)
connector.close();
}
}
}
例程10-19 ProxyFactory.java(负责创建动态代理类及其实例)
package reflection.proxy.dynamic;
import java.lang.reflect.*;
import java.rmi.RemoteException;
public class ProxyFactory {//动态代理
public static Object getProxy(final Class classType, final String host,
final int port) {
InvocationHandler handler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object args[])
throws Exception {
Connector connector = null;
try {
connector = new Connector(host, port);
Call call = new Call(classType.getName(), method.getName(),
method.getParameterTypes(), args);
connector.send(call);
call = (Call) connector.receive();
Object result = call.getResult();
if (result instanceof Throwable)
throw new RemoteException("",(Throwable) result); // 把异常都转换为RemoteException
else
return result;
} finally {
if (connector != null)
connector.close();
}
}
};
return Proxy.newProxyInstance(classType.getClassLoader(),
new Class[] { classType }, handler);
}
}
无论HelloService 的静态代理类还是动态代理类,都通过Connector 类来发送和
接收Call 对象。ProxyFactory 工厂类的getProxy()方法的第一个参数classType 指定代理类实现的接口的类型,如果参数classType 的取值为HelloService.class,那么
getProxy()方法就创建HelloService 动态代理类的实例。如果参数classType 的取值为Foo.class,那么getProxy()方法就创建Foo动态代理类的实例。由此可见,getProxy()
方法可以创建任意类型的动态代理类的实例,并且它们都具有调用被代理的远程对象
的方法的能力。
如果使用静态代理方式,那么对于每一个需要代理的类,都要手工编写静态代理
类的源代码;如果使用动态代理方式,那么只要编写一个动态代理工厂类,它就能自
动创建各种类型的动态代理类,从而大大简化了编程,并且提高了软件系统的可扩展
性和可维护性。
如例程10-20 所示的SimpleClient类的main()方法中,分别通过静态代理类和动态
代理类去访问SimpleServer 服务器上的HelloServiceImpl对象的各种方法。
例程10-20 SimpleClient.java简单的客户端:
package reflection.proxy.dynamic;
public class SimpleClient {
public static void main(String args[]) throws Exception {
// 创建静态代理类实例
IHelloService helloService1 = new HelloServiceProxy("localhost", 8888);
System.out.println(helloService1.echo("hello"));
System.out.println(helloService1.getTime());
// 创建动态代理类实例
IHelloService helloService2 = (IHelloService) ProxyFactory.getProxy(
IHelloService.class, "localhost", 8888);
System.out.println(helloService2.echo("hello"));
System.out.println(helloService2.getTime());
}
}
服务器端:
package reflection.proxy.dynamic;
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.reflect.*;
public class SimpleServer {
private Map remoteObjects = new HashMap(); // 存放远程对象的缓存
/** 把一个远程对象放到缓存中 */
public void register(String className, Object remoteObject) {
remoteObjects.put(className, remoteObject);
}
public void service() throws Exception {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务器启动......");
while (true) {
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(in); // 读取对象
OutputStream out = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(out);
Call call = (Call) ois.readObject(); // 接收客户发送的Call 对象
System.out.println(call); // toString()方法
call = invoke(call); // 调用相关对象的方法
oos.writeObject(call); // 向客户发送包含了执行结果的Call 对象
ois.close();
oos.close();
socket.close();
}
}
public Call invoke(Call call) {
Object result = null;
try {
String className = call.getClassName();
String methodName = call.getMethodName();
Object[] params = call.getParams();
Class classType = Class.forName(className);
Class[] paramTypes = call.getParamTypes();
Method method = classType.getMethod(methodName, paramTypes);
Object remoteObject = remoteObjects.get(className); // 从缓存中取出相关的远程对象
if (remoteObject == null) {
throw new Exception(className + "的远程对象不存在");
} else {
result = method.invoke(remoteObject, params);
}
} catch (Exception e) {
result = e;
}
call.setResult(result); // 设置方法执行结果
return call;
}
public static void main(String args[]) throws Exception {
SimpleServer server = new SimpleServer();
// 把事先创建的HelloServiceImpl 对象加入到服务器的缓存中
server.register("reflection.proxy.dynamic.IHelloService", new HelloServiceImpl());
server.service();
}
}
先运行命令“java proxy1.SimpleServer”,再运行命令“java proxy1.SimpleClient”,
SimpleClient端的打印结果如下::