Java通过Socket和动态代理实现简易RPC框架
本文转自Dubbo作者梁飞大神的CSDN(https://javatar.iteye.com/blog/1123915),代码简洁,五脏俱全.
1.首先实现RpcFramework,实现服务的暴露与引用功能.
1 package com.zxd.dubbo.learning.rpc.framework; 2 3 import java.io.IOException; 4 import java.io.ObjectInputStream; 5 import java.io.ObjectOutputStream; 6 import java.lang.reflect.InvocationHandler; 7 import java.lang.reflect.Method; 8 import java.lang.reflect.Proxy; 9 import java.net.ServerSocket; 10 import java.net.Socket; 11 12 /** 13 * @Project DubboLearning 14 * @Package com.zxd.dubbo.learning.rpc.framework 15 * @Author:zouxiaodong 16 * @Description: 17 * @Date:Created in 14:32 2018/10/24. 18 */ 19 public class RpcFramework { 20 21 /** 22 * @FileName RpcFramework.java 23 * @ClassName RpcFramework 24 * @MethodName export 25 * @Desc 暴露服务 26 * @author zouxiaodong 27 * @date 2018/10/24 15:06 28 * @Params [service 服务实现, port 服务端口] 29 * @return void 30 */ 31 public static void export(final Object service,int port) throws IOException { 32 if(service == null){ 33 throw new IllegalArgumentException("service instance == null"); 34 } 35 if(port < 0 || port > 65535){ 36 throw new IllegalArgumentException("Invalid port " + port); 37 } 38 System.out.println("Export service :" + service.getClass().getName() + " on port " + port); 39 ServerSocket serverSocket = new ServerSocket(port); 40 while (true){ 41 try { 42 final Socket socket = serverSocket.accept(); 43 new Thread(new Runnable() { 44 @Override 45 public void run() { 46 ObjectInputStream input = null; 47 ObjectOutputStream output = null; 48 try { 49 input = new ObjectInputStream(socket.getInputStream()); 50 String methodName = input.readUTF(); 51 Class<?>[] parameterTypes = (Class<?>[]) input.readObject(); 52 Object[] arguments = (Object[]) input.readObject(); 53 output = new ObjectOutputStream(socket.getOutputStream()); 54 Method method = service.getClass().getMethod(methodName,parameterTypes); 55 Object result = method.invoke(service,arguments); 56 output.writeObject(result); 57 } catch (Exception e) { 58 System.err.println("1."+e.getMessage()); 59 }finally { 60 try { 61 if(output != null){ 62 output.close(); 63 } 64 if(input != null){ 65 input.close(); 66 } 67 if(socket != null){ 68 socket.close(); 69 } 70 } catch (IOException e) { 71 System.err.println("2."+e.getMessage()); 72 } 73 } 74 } 75 }).start(); 76 }catch (Exception e){ 77 78 } 79 } 80 } 81 82 /** 83 * @FileName RpcFramework.java 84 * @ClassName RpcFramework 85 * @MethodName refer 86 * @Desc 引用服务 87 * @author zouxiaodong 88 * @date 2018/10/24 15:32 89 * @Params [interfaceClass 接口类型, host 服务器主机名, port 服务器端口] 90 * @return T 远程服务 91 */ 92 public static <T> T refer(final Class<T> interfaceClass,final String host,final int port){ 93 if(interfaceClass == null){ 94 throw new IllegalArgumentException("Interface class == null"); 95 } 96 if(!interfaceClass.isInterface()){ 97 throw new IllegalArgumentException("The " + interfaceClass.getName() + " must be interface class!"); 98 } 99 if (host == null || host.length() == 0) { 100 throw new IllegalArgumentException("Host == null!"); 101 } 102 if (port <= 0 || port > 65535) { 103 throw new IllegalArgumentException("Invalid port " + port); 104 } 105 System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port); 106 return (T)Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() { 107 @Override 108 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 109 Socket socket = new Socket(host,port); 110 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); 111 output.writeUTF(method.getName()); 112 output.writeObject(method.getParameterTypes()); 113 output.writeObject(args); 114 ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); 115 try { 116 Object result = input.readObject(); 117 if(result instanceof Throwable){ 118 throw (Throwable)result; 119 } 120 return result; 121 }finally { 122 input.close(); 123 output.close(); 124 socket.close(); 125 } 126 } 127 }); 128 } 129 }
2.编写接口HelloService.java与实现类HelloServiceImpl.java
1 package com.zxd.dubbo.learning.rpc.framework; 2 3 /** 4 * @Project DubboLearning 5 * @Package com.zxd.dubbo.learning.rpc.framework.api 6 * @Author:zouxiaodong 7 * @Description: 8 * @Date:Created in 15:50 2018/10/24. 9 */ 10 public interface HelloService { 11 String hello(String name); 12 }
1 package com.zxd.dubbo.learning.rpc.framework; 2 3 4 /** 5 * @Project DubboLearning 6 * @Package com.zxd.dubbo.learning.rpc.framework.impl 7 * @Author:zouxiaodong 8 * @Description: 9 * @Date:Created in 15:51 2018/10/24. 10 */ 11 public class HelloServiceImpl implements HelloService { 12 @Override 13 public String hello(String name) { 14 return "Hello "+name; 15 } 16 }
3.编写提供者(暴露服务)
1 package com.zxd.dubbo.learning.rpc.framework; 2 3 import java.io.IOException; 4 5 /** 6 * @Project DubboLearning 7 * @Package com.zxd.dubbo.learning.rpc.framework 8 * @Author:zouxiaodong 9 * @Description: 10 * @Date:Created in 15:54 2018/10/24. 11 */ 12 public class RpcProvider { 13 public static void main(String[] args) throws IOException { 14 HelloService helloService = new HelloServiceImpl(); 15 RpcFramework.export(helloService,12345); 16 } 17 }
4.编写消费者(引用服务)
1 package com.zxd.dubbo.learning.rpc.framework; 2 3 /** 4 * @Project DubboLearning 5 * @Package com.zxd.dubbo.learning.rpc.framework 6 * @Author:zouxiaodong 7 * @Description: 8 * @Date:Created in 15:55 2018/10/24. 9 */ 10 public class RpcConsumer { 11 public static void main(String[] args){ 12 HelloService helloService = RpcFramework.refer(HelloService.class,"127.0.0.1",12345); 13 String result = helloService.hello("CoderZZ"); 14 System.out.println(result); 15 } 16 }