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 }

 

posted @ 2019-07-31 09:59  CoderZZZ  阅读(855)  评论(0编辑  收藏  举报