使用RMI和EJB的童鞋,都知道EJB有客户端存根,和服务端骨架的说法。客户端调用服务其实是调用客户端的存根,客户端的存根调用相关的代理,代理向服务端发送请求,服务端响应请求,并将请求信息发送给代理,代理将结果返回给存根的。
封装请求信息的类:
package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.io.*;
/**
* 关于远程访问协议的信息
* 用于封装请求中各种信息
* @author longgangbai
*
*/
public class Call implements Serializable{
private String className; //表示类名
private String methodName; //表示方法名
private Class[] paramTypes; //表示方法参数类型
private Object[] params; //表示方法参数值
private Object result; //表示方法的返回值或者方法抛出的异常
public Call(){}
public Call(String className,String methodName,Class[] paramTypes,
Object[] params){
this.className=className;
this.methodName=methodName;
this.paramTypes=paramTypes;
this.params=params;
}
public String getClassName(){return className;}
public void setClassName(String className){this.className=className;}
public String getMethodName(){return methodName;}
public void setMethodName(String methodName){this.methodName=methodName;}
public Class[] getParamTypes(){return paramTypes;}
public void setParamTypes(Class[] paramTypes){this.paramTypes=paramTypes;}
public Object[] getParams(){return params;}
public void setParams(Object[] params){this.params=params;}
public Object getResult(){return result;}
public void setResult(Object result){this.result=result;}
public String toString(){
return "className="+className+" methodName="+methodName;
}
}
处理客户端的信息:
package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.io.*;
import java.net.*;
/**
* 关于客户端的连接信息
*
* 客户端的处理的信息
*
* @author longgangbai
*
*/
public class Connector {
//客户端的主机ip
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);
}
/**
* 设置对象序列化对象
* @param obj
* @throws Exception
*/
public void send(Object obj)throws Exception{
oos.writeObject(obj);
}
/**
* 获取序列化对象
* @return
* @throws Exception
*/
public Object receive() throws Exception{
return ois.readObject();
}
public void connect()throws Exception{
connect(host,port);
}
/**
* 连接客户端
* @param host
* @param port
* @throws Exception
*/
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);
}
}
}
}
远程访问的代理工厂 获取代理的对象
package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.lang.reflect.*;
/**
* 远程访问的代理工厂
*
* 获取代理的对象
* @author longgangbai
*
*/
public class ProxyFactory {
/**
* 获取远程访问的bean 对象
* @param classType
* @param host
* @param port
* @return
*/
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);
else
return result;
}finally{
if(connector!=null)
connector.close();
}
}
};
//客户端返回执行代理
return Proxy.newProxyInstance(classType.getClassLoader(),
classType.getInterfaces(),handler);
}
}
服务端代理工厂:
package com.easyway.space.basic.network.sockets.remoting.proxy;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import com.easyway.space.basic.patterns.proxys.HelloServiceImpl;
/**
* 远程代理的服务处理类
* @author Owner
*
*/
public class ServiceProxyExporterServer {
//用于缓存服务端的实例对象
private Map<String,Object> remoteObjects=new HashMap<String,Object>();
/**
* 注册服务端的实例对象
* @param className
* @param remoteObject
*/
public void register(String className,Object remoteObject){
remoteObjects.put( className,remoteObject);
}
/**
* 处理相关的客户端请求的信息
* @throws Exception
*/
public void service()throws Exception{
//服务端的网络的对象
ServerSocket serverSocket = new ServerSocket(8000);
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();
System.out.println(call);
//获取远程调用的方法
call=invoke(call);
//将执行结果写入到序列化对象中
oos.writeObject(call);
//关闭相关的资源
ois.close();
oos.close();
socket.close();
}
}
/**
* 获取服务端响应的结果的信息,并封装返回结果
*
* @param call
* @return
*/
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 {
ServiceProxyExporterServer server=new ServiceProxyExporterServer();
server.register("com.easyway.space.basic.patterns.proxys.HelloService",new HelloServiceImpl());
server.service();
}
}
客户端调用:
package com.easyway.space.basic.network.sockets.remoting.proxy;
import com.easyway.space.basic.patterns.proxys.HelloService;
public class RemoteProxyClient {
public static void main(String args[])throws Exception {
//创建动态代理类实例
HelloService helloService2=
(HelloService)ProxyFactory.getProxy(HelloService.class,"localhost",8000);
System.out.println(helloService2.getClass().getName());
System.out.println(helloService2.echo("hello"));
System.out.println(helloService2.getTime());
}
}