java分布式调用入门 自定义基于反射 Scoket JKD动态代理 RPC框架

使用工具IDEA, Myeclipse

编写服务端接口 HelloService 在这里插入图片描述
服务端实现类
在这里插入图片描述
编写服务端的调用类
package whu;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import java.lang.reflect.Method;

import java.net.ServerSocket;
import java.net.Socket;

public class RpcFramework {
//注册开始方法
public static void export(Object service, Class interfaceClazz, int port) throws Exception {

    if (service == null) {
        throw new IllegalAccessException("service instance == null");
    }
    if (port < 0 || port > 65535) {
        throw new IllegalAccessException("Invalid port " + port);
    }
    System.out.println("Export service " + service.getClass().getName() + " on port " + port);
    //服务端socket
    ServerSocket server = new ServerSocket(port);
    //死循环达到不断监听 使用while(true)也一样
    for (;;) {
        final Socket socket = server.accept();//阻塞等待客户端连接
        try {
            new Thread(new Runnable() {//多线程

                @Override
                public void run() {
                    try {
                        try {
                            //获取客户端传来的流对象
                            ObjectInputStream input = new ObjectInputStream(socket.getInputStream());

                            try {
                                String interfaceName = input.readUTF();//获取客户端传来需要调用的接口名
                                String methodName = input.readUTF();//客户端传来需要调用的方法
                                Class<?>[] parameterTypes = (Class<?>[]) input.readObject();//客户端传来需要调用的方法的参数类型
                                Object[] arguments = (Object[]) input.readObject();//调用方法的参数
                                ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());//返回客户端的留流对象

                                try {
                                    //判断客户端需要调用的接口在服务端是否存在
                                    if (!interfaceName.equals(interfaceClazz.getName())) {
                                        throw new IllegalAccessException("Interface wrong, export:" + interfaceClazz
                                                + " refer:" + interfaceName);
                                    }
                                    Method method = service.getClass().getMethod(methodName, parameterTypes);//通过反射获取服务端的方法
                                    Object result = method.invoke(service, arguments);//执行服务端方法
                                    output.writeObject(result);//返回给客户端
                                } catch (Throwable t) {
                                    output.writeObject(t);
                                } finally {
                                    output.close();
                                }
                            } finally {
                                input.close();
                            }
                        } finally {
                            socket.close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();//开启线程
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

}

我这里是直接传入一个对象 你们也可以写一个map用来注册多个对象
服务端启动类

package whu;

public class out {

public static void main(String[] args) throws Exception {
    HelloService service = new HelloServiceImpl();
    RpcFramework.export(service, HelloService.class, 9000);
}

}

客户端调用类

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import java.net.Socket;

public class Rpcfrowd {

/**
 * @param args
 */
 @SuppressWarnings("unchecked")//屏蔽黄线
 public static <T> T refer(final Class<T> interfaceClass, final String host, final int port) throws Exception {
      
	
        //System.out.println("Get remote service " + interfaceClass.getName() + " from server " + host + ":" + port);
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[] { interfaceClass },
                new InvocationHandler() {//jdk 动态代理 

                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        Socket socket = new Socket(host, port);//建立客户端socket 传入服务端ip 和端口
                        System.out.println("socket通过");
                        try {
                            ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());//向服务端写入流对象

                            try {
                                output.writeUTF(interfaceClass.getName());//需要调用的接口名
                                output.writeUTF(method.getName());//需要调用的方法名
                                output.writeObject(method.getParameterTypes());//需要调用的参数类型
                                output.writeObject(args);//需要调用的参数
                                System.out.println("发送成功");
                                ObjectInputStream input = new ObjectInputStream(socket.getInputStream());//接收服务端的返回信息

                                try {
                                    Object result = input.readObject();//接收服务端的返回信息
                                    System.out.println("接收成功"+result);
                                    if (result instanceof Throwable) {
                                        throw (Throwable) result;
                                    }
                                    return result;//返回
                                } finally {
                                    input.close();
                                }

                            } finally {
                                output.close();
                            }

                        } finally {
                            socket.close();
                        }
                        
                    }
                });
    }

}
注意第一个return是返回 生成的代理类对象 第二个是返回调用方法的返回值

客户端启动类
import whu.HelloService;

public class clid {

public static void main(String[] args) throws Exception {
	HelloService  service = (HelloService)Rpcfrowd.refer(Class.forName("whu.HelloService"), "127.0.0.1", 9000);
    String result = service.hello("rod---");
    System.out.println(result);
}

}

运行服务端启动类
在这里插入图片描述
运行客户端启动类
在这里插入图片描述
简单的rpc远程调用就实现了 这里提一下服务端需要接口和实现类 客户端只需要接口就行

猜你喜欢

转载自blog.csdn.net/qq_28422443/article/details/90055742