行僧

参与开源,努力提升。 我的GitHub地址:https://github.com/playingjoker

基于Proxy模仿dubbo的RPC实现

    用于生成Class对象

    package com.liuzn.test.util;
    
    public class ClassFactory {
    
        @SuppressWarnings("unchecked")
        public static <T> Class<T> getClass(String className) {
            try {
                return (Class<T>) Class.forName(className);
      } catch (ClassNotFoundException e) {
                e.printStackTrace();
      }
            return null;
      }
    
    }
    

    请求代理对象,封装Method对象以及请求参数

    package com.liuzn.test.entity;
    
    import java.io.Serializable;
    
    public class ProxyRequest implements Serializable {
    
        private static final long serialVersionUID = 2358035686978399918L;
     private MethodEntity method;
     private Object[] args;
      /**
     * @return the method
     */  public MethodEntity getMethod() {
            return method;
      }
        /**
     * @param method the method to set
     */  public void setMethod(MethodEntity method) {
            this.method = method;
      }
        /**
     * @return the args
     */  public Object[] getArgs() {
            return args;
      }
        /**
     * @param args the args to set
     */  public void setArgs(Object[] args) {
            this.args = args;
      }
    
    }
    

    用于封装请求数据的Method实体,封装了调用的接口信息,参数信息,后续应该继续加入version信息等

    
    package com.liuzn.test.entity;
    
    import java.io.Serializable;
    
    public class MethodEntity implements Serializable {
    
        private static final long serialVersionUID = 8247122061445501661L;
    
     private String methodName;
     private Class[] parameterTypes;
    
      /**
     * @return the methodName
     */  public String getMethodName() {
            return methodName;
      }
    
        /**
     * @param methodName the methodName to set
     */  public void setMethodName(String methodName) {
            this.methodName = methodName;
      }
    
        /**
     * @return the parameterTypes
     */  public Class[] getParameterTypes() {
            return parameterTypes;
      }
    
        /**
     * @param parameterTypes the parameterTypes to set
     */  public void setParameterTypes(Class[] parameterTypes) {
            this.parameterTypes = parameterTypes;
      }
    
    }
    
    

    基于Proxy实现Server端代理对象

    package com.liuzn.test;
    
    import com.liuzn.test.entity.MethodEntity;
    import com.liuzn.test.entity.ProxyRequest;
    import com.liuzn.test.util.ClassFactory;
    
    import java.io.*;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Service {
    
        public static void main(String[] args) {
            String infcName = "com.liuzn.test.Interface";
      String implName = "com.liuzn.test.InterfaceImpl";
    
      ServerSocket socket = null;
    
     try {
                Class bean = ClassFactory.getClass(implName);
      Object o = bean.newInstance();
      socket = new ServerSocket(2129);
     while (true) {
                    Socket accept = socket.accept();
      InputStream inputStream = accept.getInputStream();
      OutputStream outputStream = accept.getOutputStream();
      BufferedInputStream bis = null;
      ObjectInputStream ois = null;
     try {
                        while (true) {
    
                            bis = new BufferedInputStream(inputStream);
      ois = new ObjectInputStream(bis);
      ProxyRequest request = (ProxyRequest) ois.readObject();
      MethodEntity method = request.getMethod();
      Object[] args2 = request.getArgs();
      String methodName = method.getMethodName();
    
      Class interfaceName = ClassFactory.getClass(infcName);
      Method declaredMethod = interfaceName.getDeclaredMethod(methodName, method.getParameterTypes());
    
      Object result = declaredMethod.invoke(o, args2);
      ByteArrayOutputStream bo = null;
      ObjectOutputStream oo = null;
     try {
                                bo = new ByteArrayOutputStream();
      oo = new ObjectOutputStream(bo);
      oo.writeObject(result);
     byte[] byteArray = bo.toByteArray();
    
      outputStream.write(byteArray);
      outputStream.flush();
      } catch (IOException e) {
                                e.printStackTrace();
      } finally {
                                if (bo != null) {
                                    bo.close();
      }
                                if (oo != null) {
                                    oo.close();
      }
    
                            }
    
                        }
    
                    } catch (IOException | IllegalAccessException e) {
                        // TODO Auto-generated catch block
    //                    e.printStackTrace();
      } finally {
                        if (bis != null) {
                            bis.close();
      }
                        if (ois != null) {
                            ois.close();
      }
                    }
    
                }
    
            } catch (IOException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (SecurityException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (InstantiationException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      } catch (IllegalAccessException e) {
                e.printStackTrace();
      } finally {
                try {
                    socket.close();
    
      } catch (IOException e) {
                    // TODO Auto-generated catch block
      e.printStackTrace();
      }
            }
    
        }
    
    }
    

    基于Proxy实现client端代理远端API接口调用

    
    package com.liuzn.test;
    
    import com.liuzn.test.entity.MethodEntity;
    import com.liuzn.test.entity.ProxyRequest;
    import com.liuzn.test.util.ClassFactory;
    
    import java.io.*;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.net.Socket;
    
    class ProxyInvocationHandler implements InvocationHandler {
    
        private Socket client = null;
    
     private InputStream inputStream = null;
     private OutputStream outputStream = null;
    
      ProxyInvocationHandler() {
            try {
                if (client == null) {
                    client = new Socket("127.0.0.1", 2129);
      }
                if (inputStream == null) {
                    inputStream = client.getInputStream();
      }
                if (outputStream == null) {
                    outputStream = client.getOutputStream();
      }
            } catch (IOException e) {
                // TODO Auto-generated catch block
      e.printStackTrace();
      }
        }
    
        @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            ProxyRequest req = new ProxyRequest();
      MethodEntity methodEntity = new MethodEntity();
      methodEntity.setMethodName(method.getName());
      Class[] parameterTypes = method.getParameterTypes();
      methodEntity.setParameterTypes(parameterTypes);
      req.setMethod(methodEntity);
    
      req.setArgs(args);
      ByteArrayOutputStream bos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(bos);
      oos.writeObject(req);
      oos.flush();
    
      outputStream.write(bos.toByteArray());
      outputStream.flush();
    
      BufferedInputStream bis = new BufferedInputStream(inputStream);
      ObjectInputStream ois = new ObjectInputStream(bis);
      Object readObject = ois.readObject();
      oos.flush();
      bos.flush();
      oos.close();
      bos.close();
    
     return readObject;
      }
    
        public void clear() {
    
            try {
                if (client != null) {
                    client.close();
      }
                if (outputStream != null) {
                    outputStream.close();
      }
                if (inputStream != null) {
                    inputStream.close();
      }
    
            } catch (IOException e) {
                e.printStackTrace();
      }
        }
    
    }
    
    class ProxyTest {
    
        public void proxy() {
         // 1.获取 interface 名称
      String className = "com.liuzn.test.Interface";
    
      // 2. 取得接口反射对象
      Class clazz = ClassFactory.getClass(className);
     if (clazz == null) {
                System.out.println(className+"未找到");
     return;  }
            ClassLoader classLoader = clazz.getClassLoader();
    
      // 3.代理实现类
      InvocationHandler h = new ProxyInvocationHandler();
    
      Interface inter = (Interface) Proxy.newProxyInstance(classLoader, new Class[] { clazz }, h);
    //        while (true) {
      Integer len = inter.test("test");
      System.out.println("长度为" + len);
      String str = inter.testString("test");
      System.out.println(str);
      Response res = inter.testResponse("test");
      System.out.println(res.getName());
    
    //            try {
    //                Thread.sleep(5000);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
    //        }
      }
    
    }
    
    public class Test {
    
        public static void main(String[] args) {
            ProxyTest pt = new ProxyTest();
      pt.proxy();
      }
    
    }
    
    

    测试接口

    package com.liuzn.test;
    
    public interface Interface{
        Integer test(String testName);
      String testString(String testString);
      Response testResponse(String name);
    }
    

    测试接口实现

    package com.liuzn.test;
    
    public class InterfaceImpl implements Interface {
    
        @Override
      public Integer test(String testName) {
            return testName.length();
      }
    
        @Override
      public String testString(String testString) {
            String result = "service: "+testString;
     return result;
      }
    
        @Override
      public Response testResponse(String name) {
            Response response = new Response();
      response.setName(name);
     return response;
      }
    
    }
    
    评论
    validate