• Java简单的RPC实现(一)


    RPC使用java最基本的,传输层使用Socket,序列化使用Serializable,java 动态代理模式,但是未实现消息注册等相关信息

    大道至简

    server端

      

     1 package com.rpc.entity;
     2 
     3 import java.io.Serializable;
     4 
     5 public class RpcObject implements Serializable{
     6     
     7     private static final long serialVersionUID = 1L;
     8     private Class<?> c;
     9     private String methodName;
    10     private Object[] args;
    11     
    12     public RpcObject() {
    13         
    14     }
    15     
    16     public RpcObject(Class<?> c, String methodName, Object[] args) {
    17         this.c = c;
    18         this.methodName = methodName;
    19         this.args = args;
    20     }
    21     
    22     public Class<?> getC() {
    23         return c;
    24     }
    25     
    26     public void setC(Class<?> c) {
    27         this.c = c;
    28     }
    29     
    30     public String getMethodName() {
    31         return methodName;
    32     }
    33     
    34     public void setMethodName(String methodName) {
    35         this.methodName = methodName;
    36     }
    37     
    38     public Object[] getArgs() {
    39         return args;
    40     }
    41     
    42     public void setArgs(Object[] args) {
    43         this.args = args;
    44     }
    45 }

    ConfMonitor

     1 package com.rpc.server;
     2 
     3 import java.util.HashMap;
     4 import java.util.Map;
     5 
     6 import com.rpc.service.impl.HelloImpl;
     7 
     8 /**
     9  * 模拟配置,实际的框架中大部分都是使用xml进行配置的,比如Hessian是配置在web.xml的servlet属性里的
    10  * @author cdwangzijian
    11  *
    12  */
    13 public class ConfMonitor {
    14     @SuppressWarnings("rawtypes")
    15     public static Map<String, Class> conf = new HashMap<String, Class>();
    16     
    17     static {
    18         conf.put("com.rpc.service.IHello", HelloImpl.class);
    19     }
    20 }

    RpcThread

      1 package com.rpc.server;
      2 
      3 import java.io.IOException;
      4 import java.io.ObjectInputStream;
      5 import java.io.ObjectOutputStream;
      6 import java.lang.reflect.InvocationTargetException;
      7 import java.lang.reflect.Method;
      8 import java.net.Socket;
      9 
     10 import com.rpc.entity.RpcObject;
     11 
     12 public class RpcThread extends Thread {
     13     
     14     private Socket s;
     15     
     16     public RpcThread(Socket s) {
     17         this.s = s;
     18     }
     19     
     20     @Override
     21     public void run() {
     22         
     23         ObjectInputStream is = null;
     24         ObjectOutputStream os = null;
     25         
     26         try {
     27             
     28             is = new ObjectInputStream(s.getInputStream());
     29             
     30             // 得到远程调用参数,包含了接口名,调用方法,方法参数
     31             RpcObject rpcObject = (RpcObject) is.readObject();
     32             
     33             System.out.println("Method:"+rpcObject.getMethodName());
     34             
     35             // 构建接口的实现类,然后通过反射调用方法
     36             Object o = getObject(rpcObject.getC());
     37             System.out.println("class:"+rpcObject.getC());
     38             
     39             
     40             Object reO = executeMethod(o, rpcObject.getMethodName(), rpcObject.getArgs());
     41             
     42             // 输出返回值
     43             os = new ObjectOutputStream(s.getOutputStream());
     44             os.writeObject(reO);
     45             os.flush();
     46         } catch (IOException e) {
     47             e.printStackTrace();
     48         } catch (ClassNotFoundException e) {
     49             e.printStackTrace();
     50         } finally {
     51             try {
     52                 if(is!=null){
     53                     is.close();
     54                 }
     55                 
     56                 if(os!=null){
     57                     os.close();
     58                 }                
     59             } catch (IOException e) {
     60                 e.printStackTrace();
     61             }
     62         }
     63     }
     64     
     65     /**
     66      * 通过反射技术执行方法,并返回返回值
     67      * @param o
     68      * @param methodName
     69      * @param args
     70      * @return
     71      */
     72     private Object executeMethod(Object o, String methodName, Object[] args) {
     73         Object objR = null;
     74         Class<?>[] cs = new Class[args.length];
     75         for (int i = 0; i < args.length; i++) {
     76             Object arg = args[i];
     77             cs[i] = arg.getClass();
     78         }
     79         try {
     80             Method m = o.getClass().getMethod(methodName, cs);
     81             objR = m.invoke(o, args);
     82         } catch (SecurityException e) {
     83             e.printStackTrace();
     84         } catch (NoSuchMethodException e) {
     85             e.printStackTrace();
     86         } catch (IllegalArgumentException e) {
     87             e.printStackTrace();
     88         } catch (IllegalAccessException e) {
     89             e.printStackTrace();
     90         } catch (InvocationTargetException e) {
     91             e.printStackTrace();
     92         }
     93         return objR;
     94     }
     95     
     96     /**
     97      * 根据接口名得到实例
     98      * @param c
     99      * @return
    100      */
    101     private Object getObject(Class<?> c) {
    102         Object o = null;
    103         try {
    104             
    105             System.out.println("c.getName:"+c.getName());
    106             
    107             o = ConfMonitor.conf.get(c.getName()).newInstance();
    108         } catch (InstantiationException e) {
    109             e.printStackTrace();
    110         } catch (IllegalAccessException e) {
    111             e.printStackTrace();
    112         }
    113         return o;
    114     }
    115 }

    StartUp

     1 package com.rpc.server;
     2 
     3 import java.io.IOException;
     4 import java.net.ServerSocket;
     5 import java.net.Socket;
     6 
     7 /**
     8  * RPC服务器启动
     9  * @author cdwangzijian
    10  *
    11  */
    12 public class StartUp {
    13     
    14     public static final int port = 9001;
    15     
    16     public static void main(String[] args) {
    17             exportRpc();
    18     }
    19     
    20     /**
    21      * 导出RPC接口
    22      */
    23     private static void exportRpc() {
    24         try {
    25             ServerSocket ss = new ServerSocket(port);
    26             while(true){
    27                 Socket s = ss.accept();
    28                 if(s!=null){
    29                     new RpcThread(s).start();
    30                 }
    31             }
    32         } catch (IOException e) {
    33             e.printStackTrace();
    34         }
    35     }
    36 }

    HelloImpl

     1 package com.rpc.service.impl;
     2 
     3 import com.rpc.service.IHello;
     4 
     5 public class HelloImpl implements IHello {
     6     @Override
     7     public String sayHello(String name) {
     8         return "hello:" + name;
     9     }
    10 }

    IHello

    1 package com.rpc.service;
    2 
    3 public interface IHello {
    4     String sayHello(String name);
    5 }

    客户端实现:

     ProxyFactory

     1 package com.zhy.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Proxy;
     5 
     6 public class ProxyFactory {
     7 
     8     @SuppressWarnings("unchecked")
     9     public static <T> T create(Class<T> c, String ip, int port) {
    10          
    11         InvocationHandler handler = new RpcProxy(ip, port, c);
    12         
    13         return (T) Proxy.newProxyInstance(c.getClassLoader(),new Class[] {c},handler);
    14     }
    15 }

    RpcProxy

     1 package com.zhy.proxy;
     2 
     3 import java.io.ObjectInputStream;
     4 import java.io.ObjectOutputStream;
     5 import java.io.Serializable;
     6 import java.lang.reflect.InvocationHandler;
     7 import java.lang.reflect.Method;
     8 import java.net.Socket;
     9 
    10 import com.rpc.entity.RpcObject;
    11 
    12 /**
    13  * 客户端接口代理
    14  * 当客户端接口方法被调用的时候,把方法名,方法参数作为参数。
    15  * 传送给远程服务执行,然后获取返回值
    16  * @author cdwangzijian
    17  *
    18  */
    19 public class RpcProxy implements InvocationHandler, Serializable{
    20     
    21     private String ip;
    22     private int port;
    23     private Class<?> c;
    24     
    25     private static final long serialVersionUID = 1L;
    26 
    27     public RpcProxy(String ip, int port, Class<?> c) {
    28         this.ip = ip;
    29         this.port = port;
    30         this.c = c;
    31     }
    32     
    33     /**
    34      * 动态代理类,当调用接口方法的时候转为调用此方法
    35      */
    36     @Override
    37     public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
    38         
    39         // 用作返回值
    40         Object o = null;        
    41         // 通过socket调用远程服务
    42         Socket s = new Socket(ip, port);
    43         
    44         // 组装为一个保留了要调用的类,方法名及参数的对象,然后序列化之后传给远程
    45         RpcObject rpcObject = new RpcObject(c, method.getName(), args);
    46         
    47         ObjectOutputStream os = null;
    48         ObjectInputStream is = null;
    49         
    50         try{
    51             os = new ObjectOutputStream(s.getOutputStream());
    52             os.writeObject(rpcObject);
    53             os.flush();
    54             
    55             // 从远程得到返回结果
    56             is = new ObjectInputStream(s.getInputStream());
    57             o = is.readObject();
    58             
    59         } catch (Exception e) {
    60             e.printStackTrace();
    61             
    62         } finally{
    63             
    64             if(os!=null){
    65                 os.close();
    66             }
    67             
    68             if(is!=null){
    69                 is.close();
    70             }
    71             
    72         }
    73         
    74         return o;
    75     }
    76     
    77 }

    RpcClient

     1 package com.zhy;
     2 
     3 import com.rpc.service.IHello;
     4 import com.zhy.proxy.ProxyFactory;
     5 
     6 public class RpcClient {
     7     public static void main(String[] args) {
     8         
     9         String ip = "localhost";
    10         int port = 9001;
    11         
    12         IHello hello = ProxyFactory.create(IHello.class, ip, port);
    13         
    14         System.out.println(hello.sayHello("小明"));
    15         
    16     }
    17 }

    输出结果:

     

  • 相关阅读:
    烂泥:KVM虚拟机windows系统增加硬盘
    烂泥:KVM虚拟机克隆
    烂泥:KVM快照的创建与恢复
    烂泥:【解决】word复制windows live writer没有图片
    烂泥:ubuntu中使用virt-manager图形化新建虚拟机
    烂泥:ubuntu安装KVM虚拟机管理virt-manager
    烂泥:【解决】ubuntu使用远程NFS报错
    烂泥:kvm安装windows系统蓝屏
    烂泥:ubuntu安装vmtools
    烂泥: KVM虚拟机Linux系统增加硬盘
  • 原文地址:https://www.cnblogs.com/csguo/p/7575372.html
Copyright © 2020-2023  润新知