本节commit源码地址:416bb92
客户端实现(动态代理)
由于在客户端这边我们并没有接口的具体实现类,就没有办法直接生成实例对象。这时,我们可以通过JDK动态代理的方式生成实例。(关于动态代理不太熟的小伙伴可以戳:动态代理详解)
public class RpcClientProxy implements InvocationHandler {
private String host;
private int port;
//传递host和port来指明服务端的位置
public RpcClientProxy(String host, int port){
this.host = host;
this.port = port;
}
//抑制编译器产生警告信息
@SuppressWarnings("unchecked")
public <T> T getProxy(Class<T> clazz){
//创建代理对象
return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
}
}
InvocationHandler
接口需要实现invoke()方法,来指明代理对象的方法被调用时的动作。在这里,我们显然就需要生成一个RpcRequest对象,发送出去,然后把从服务端返回的结果return即可。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//客户端向服务端传输的对象,Builder模式生成
RpcRequest rpcRequest = RpcRequest.builder()
.interfaceName(method.getDeclaringClass().getName())
.methodName(method.getName())
.parameters(args)
.paramTypes(method.getParameterTypes())
.build();
//进行远程调用的客户端
RpcClient rpcClient = new RpcClient();
return ((RpcResponse)rpcClient.sendRequest(rpcRequest, host, port)).getData();
}
Builder设计模式学习参考:https://blog.csdn.net/qq_38685503/article/details/113620036
具体的远程api调用逻辑利用RpcClient对象来实现,这个对象的作用,就是将一个对象发过去,并且接受返回的对象。
public class RpcClient {
private static final Logger logger = LoggerFactory.getLogger(RpcClient.class);
public Object sendRequest(RpcRequest rpcRequest, String host, int port) {
/**
* socket套接字实现TCP网络传输
* try()中一般放对资源的申请,若{}出现异常,()资源会自动关闭
*/
try (Socket socket = new Socket(host, port)) {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());
objectOutputStream.writeObject(rpcRequest);
objectOutputStream.flush();
return objectInputStream.readObject();
} catch (IOException | ClassNotFoundException e) {
logger.error("调用时有错误发生:" + e);
return null;
}
}
}
上面就是直接使用Java的序列化方式,通过Socket传输。创建一个Socket,获取ObjectOutputStream对象,然后把需要发送的对象传进去即可,接收时获取ObjectInputStream对象,readObject()方法就可以获得一个返回的对象。Socket原理如图:
本节结束……