手RPC框架实现运程调用 (简易版)BIO

因为是远程调用,所以要用动态代理,然后客户端用socket发送我需要调用类名、方法的名字和数据类型,服务端根据获取的类名、方法名字和类型基于反射invoke进行调用,然后把调用的结果再socket传回给客户端

简单的讲发送调用的类的名称+方法到另外一个服务中,拿到类和方法名之后通过反射调用,把数据返回,这就是远程调用。

手RPC框架实现运程调用 (简易版)BIO

①.创建RPCsenver和RPCclient 工程

senver定义两个模块(api模块和实现模块proveder.

1在api模块中定义一个接口.比如Hello.然后在实现模块里实(把api模块Pom 复制到 provider. 否则实现不了)把api模块install到本地仓库

public interface IHelloService {    
    String sayHello(String a);}
public class RpcRequest implements Serializable {

    /**
     * 类名
     */
    private String className;
    /**
     * 方法名
     */
    private String methodName;
    /**
     * 传递的参数
     */
    private Object[] parameters;
    /**
     * 参数类型
     */
    private Class[] types;

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getMethodName() {
        return methodName;
    }

    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    public Object[] getParameters() {
        return parameters;
    }

    public void setParameters(Object[] parameters) {
        this.parameters = parameters;
    }

    public Class[] getTypes() {
        return types;
    }

    public void setTypes(Class[] types) {
        this.types = types;
    }
}

2)在client工程中添加api的Pom 这时候就有了之前写的Hello当然这时候还不能远程调用.因为还没有发布服务,所以在server中写一个发布服务 RPCProxyServer.

public class RpcProxyServer {

    private final ExecutorService executorService =Executors.newCachedThreadPool();
    public void publisher(Object service,int port){

        try (ServerSocket serverSocket = new ServerSocket(port)) {
            while (true){
                //开启监听
                final Socket socket = serverSocket.accept();
                executorService.execute(new ProcessorHandler(socket,service));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
public class ProcessorHandler implements Runnable{
    Socket socket;
    Object service;

    public ProcessorHandler(Socket socket, Object service) {
        this.socket = socket;
        this.service = service;
    }

    @Override
    public void run() {
        ObjectInputStream inputStream=null;
        ObjectOutputStream outputStream=null;
        try {
            inputStream=new ObjectInputStream(socket.getInputStream());
            //需要哪些信息
            //反序列化
            RpcRequest rpcRequest=(RpcRequest)inputStream.readObject();
            Object inovke = inovke(rpcRequest);
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            outputStream.writeObject(inovke);
            //刷盘
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //TODO 关闭流
        }
    }

    private Object inovke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class c=Class.forName(rpcRequest.getClassName());
        //反射通过方法名和参数类型 获取方法
        Method method = c.getMethod(rpcRequest.getMethodName(), rpcRequest.getTypes());
        //invoke执行
        Object result = method.invoke(service, rpcRequest.getParameters());
        return result;
    }
}
public class HelloServerImpl implements IHelloService{
    @Override
    public String sayHello(String content) {
        return "hello  恭喜调用成功 content"+content;
    }
}

public class App 
{
    public static void main( String[] args ) {
        HelloServerImpl server = new HelloServerImpl();
        RpcProxyServer rpcProxyServer = new RpcProxyServer();
        rpcProxyServer.publisher(server,8088);
        System.out.println( "Hello World!" );
    }
}

②server发布服务并监听端口后.在client端写接收.
1.写一个动态代理类

public class RpcProxyClient {

//    JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
//    CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
//
//    区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。

    public <T> T clientProxy(final Class<T> interfaceCls,final String host,final int port){
        return (T) Proxy.newProxyInstance(interfaceCls.getClassLoader(),
                new Class<?>[]{interfaceCls},new RemoteInovcationHandler(host,port));
    }
}
public class RemoteInovcationHandler implements InvocationHandler {

    private String host;
    private int port;

    public RemoteInovcationHandler(String host, int port) {
        this.host = host;
        this.port = port;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("触发了调用的代码");
        RpcRequest request=new RpcRequest();
        request.setClassName(method.getDeclaringClass().getName());
        request.setMethodName(method.getName());
        request.setParameters(args);
        request.setTypes(method.getParameterTypes());
        RpcNetTransport rpcNetTransport=new RpcNetTransport(host,port);
        Object result=rpcNetTransport.send(request);
        return result;
    }
}
public class RpcNetTransport {

    private String host;
    private int port;

    public RpcNetTransport(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public Object send(RpcRequest request){
        Socket socket;
        ObjectInputStream inputStream=null;
        ObjectOutputStream outputStream=null;
        try {
            socket=new Socket(host,port);
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            outputStream.writeObject(request);
            outputStream.flush();

            inputStream=new ObjectInputStream(socket.getInputStream());
            return inputStream.readObject();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}
public class App {
    public static void main(String[] args) {
        RpcProxyClient client = new RpcProxyClient();
        IHelloService iHelloService = client.clientProxy(IHelloService.class, "localhost", 8088);
        String s = iHelloService.sayHello("aaa");
        System.out.println(s);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值