基于动态代理的远程服务:
服务类:
实现接口具体方法 工厂类:
发布服务代理服务 服务端:
指定端口,发布服务 客户端
建立通信,获取代理,传输数据,获取结果
过程原理:
基于动态代理和网络传输的远程服务,包含以下部分:
服务类:实现具体的功能操作;
工厂端:提供两个功能,一是为服务器端提供实时监听服务,通过指定端口建立Socket通信,获取从客户端传来的参数和方法名,然后执行服务器端指定的对象的方法,获取结果后通过Socket传输回客户端;二是为客户端提供动态代理,为客户端创建代理对象,并将客户端的方法绑定到动态代理上,当客户端执行对应方法时,实际上并没有真正执行,而是执行的绑定的动态代理中的操作,即将客户端中的方法名、参数通过Socket通信传递到服务器,等待服务器接收参数并执行后回传返回值,将返回值作为执行结果返回给客户端,从而实现了远程代理服务。
服务器:创建服务类对象,通过工厂类的方法将创建监听等客户端连接
客户端:创建服务类实例,指向工厂类的动态代理,服务类实例通过动态代理来执行方法,并通过动态代理来获取返回值。
说明:关于动态代理的原理,需要通过JVM的类加载机制和反射机制来深入分析,将会在另作说明。
实现过程:
服务类:
定义接口
public interface Hello {
public String hello(String world);
public String others(String o);
}
重写方法
public class HelloImpl implements Hello{
@Override
public String hello(String world){
return "hello "+world;
}
@Override
public String others(String o) {
return "success..."+o;
}
}
工厂类:
发布服务
public static void publish(Object service,int port) throws IOException{
//打开服务
ServerSocket server = new ServerSocket(port);
//建立多个通道
while(true){
Socket socket =server.accept();
new Thread(new Runnable(){
public void run() {
try {
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
//获取方法名
String method =input.readUTF();
//获取方法参数
Class<?>[] params =(Class<?>[])input.readObject();
//获取方法实参
Object[] arguments = (Object[])input.readObject();
//调用方法 返还
Method m =service.getClass().getMethod(method, params);
Object result=m.invoke(service, arguments);
output.writeObject(result);
output.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
//关闭
socket.close();
} catch (IOException e) {
}
}
}
}).start();
}
}
代理服务:
服务端:
指定端口,发布服务
public class RpcPublish {
public static void main(String[] args) throws IOException {
Hello hello=new HelloImpl();
RPCFactory.publish(hello , 1234);
}
}
客户端
监听接口,获取实例,实现功能
public class RpcSubscribe {
public static void main(String[] args) {
Hello hello=RPCFactory.subscribe("localhost", 1234, Hello.class);
System.out.println(hello.hello("aaaa"));
System.out.println(hello.others("aaaa"));
}
}