自定義RPC框架的簡單實現

package com.remote.service;

/**
 * Created by 79782 on 2018/7/22.
 */
public interface HelloService {
    public String sayHello(String name);
}
package com.remote.service;

/**
 * Created by 79782 on 2018/7/22.
 */
public class HelloServiceImpl implements HelloService {
    public String sayHello(String name) {
        return "hello:"+name;
    }
}
package com.remote.server;

/**
 * Created by 79782 on 2018/7/22.
 */
public interface Server {
    public void start();
    public void stop();
    public void register(Class server ,Class serviceImpl);
}
package com.remote.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by 79782 on 2018/7/22.
 */
public class ServerCenter implements Server {
    private static HashMap<String,Class> serviceRegiser=new HashMap();
    private static int port;
    private static ExecutorService executor= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private static boolean isRunning=false;
    public static void setPort(int port) {
        ServerCenter.port = port;
    }

    public void start() {
        isRunning=true;
        ServerSocket server=null;
        try {
            server=new ServerSocket();
            server.bind(new InetSocketAddress(9999));
        } catch (IOException e) {
            e.printStackTrace();
        }
        while(true){

            try {
                //等待客戶端連接 接受客戶端連接及請求
                Socket socket = server.accept();
                executor.execute(new ServiceTask(socket));

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public void stop() {
        isRunning=false;
        executor.shutdown();
    }

    public void register(Class server ,Class serviceImpl) {
        serviceRegiser.put(server.getName(),serviceImpl);
    }

    private static class ServiceTask implements Runnable{
        private Socket socket;

        public ServiceTask() {
        }

        public ServiceTask(Socket socket) {
            this.socket = socket;
        }

        public void run() {
            ObjectInputStream ois=null;
            ObjectOutputStream oos =null;
            try {
                //Object流有順序
                ois= new ObjectInputStream(socket.getInputStream());
                //因爲ObjectInputeStream對發送數據的數據嚴格要求,所以可以一個一個接受
                String serviceName=ois.readUTF();
                String methodName=ois.readUTF();
                Class[] paramType= (Class[]) ois.readObject();
                Object[] arguments= (Object[]) ois.readObject();
                //根據請求找到請求的接口
                Class serviceClass = serviceRegiser.get(serviceName);
                Method method = serviceClass.getMethod(methodName, paramType);
                Object result=method.invoke(serviceClass.newInstance(), arguments);
                oos= new ObjectOutputStream(socket.getOutputStream());
                oos.writeObject(result);
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(oos!=null){
                    try {
                        oos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(ois!=null){
                    try {
                        ois.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

package com.remote.client;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * Created by 79782 on 2018/7/22.
 */
public class Client {
    //獲取代表服務端接口的動態代理對象
    //serviceName:客戶端向服務端請求的接口名
    @SuppressWarnings("unchecked")
    public static <T> T getRemoteProxyObj(final Class serviceInterface, final InetSocketAddress addr){
        return (T)Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class<?>[]{serviceInterface}, new InvocationHandler() {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                ObjectOutputStream oos=null;
                ObjectInputStream ois=null;
                try{
                    Socket socket=new Socket();
                    socket.connect(addr);
                    oos= new ObjectOutputStream(socket.getOutputStream());
                    //接口名、接口方法名、方法類型,方法參數、
                    oos.writeUTF(serviceInterface.getName());
                    oos.writeUTF(method.getName());
                    oos.writeObject(method.getParameterTypes());
                    oos.writeObject(args);
                    //等待服務端處理
                    //服務端處理返回結果
                    ois= new ObjectInputStream(socket.getInputStream());
                    return ois.readObject();
                }catch (Exception e){
                    e.printStackTrace();
                    return null;
                }finally {
                    if(ois!=null){
                        ois.close();
                    }
                    if(oos!=null){
                        oos.close();
                    }
                }
            }
        });


    }
}
package com.remote.server;

import com.remote.service.HelloService;
import com.remote.service.HelloServiceImpl;

/**
 * Created by 79782 on 2018/7/22.
 */
public class ServerMain {
    /**
        服務端將可以提供的接口註冊到服務中心 通過map保存key:發佈接口的名字,value:接口的實現類
        服務端接收客戶端請求後,通過請求的接口名在服務中心的map中尋找對應的接口實現類。
        解析客戶端發送的方法名,接口名,解析完畢後通過反射技術將該方法執行
        執行完畢後將結果返回給客戶端

    */
    public static void main(String[] args) {
       new Thread(new Runnable() {
           public void run() {
               Server server=new ServerCenter();
               server.register(HelloService.class, HelloServiceImpl.class);
               server.start();
           }
       }).start();
    }
}
package com.remote.client;

import com.remote.service.HelloService;

import java.net.InetSocketAddress;

/**
 * Created by 79782 on 2018/7/22.
 */
public class ClientMain {
    public static void main(String[] args) throws ClassNotFoundException {
        /**
         * 客戶端通過socket請求服務端,並且通過字符串形式將請求的接口名發送給服務端
         * 動態代理:發送接口名,方法參數
         */

        HelloService helloService=Client.getRemoteProxyObj(
                Class.forName("com.remote.service.HelloService"),
                new InetSocketAddress("127.0.0.1",9999));
        System.out.println(helloService.sayHello("yanfang"));
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章