Java动态代理rpc

尽意
2024-08-23 / 0 评论 / 22 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年08月23日,已超过152天没有更新,若内容或图片失效,请留言反馈。
Java 动态代理在远程过程调用(RPC)中非常有用,可以隐藏网络通信的复杂性,使得远程调用看起来像是本地方法调用。

场景说明

假设我们有一个简单的服务接口 CalculatorService,它提供了加法和减法的功能。我们希望客户端可以通过动态代理的方式调用这个服务接口,实际上这些调用会通过网络发送到远程的服务端进行计算。

1. 定义服务接口

首先定义一个服务接口 CalculatorService

// 服务接口
public interface CalculatorService {
    int add(int a, int b);
    int subtract(int a, int b);
}

2. 实现服务端

服务端实现了 CalculatorService 接口,并在远程提供服务:

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

// 服务端实现类
public class CalculatorServiceImpl implements CalculatorService {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    @Override
    public int subtract(int a, int b) {
        return a - b;
    }

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(8080);
        System.out.println("服务端启动,等待连接...");

        while (true) {
            Socket clientSocket = serverSocket.accept();
            ObjectInputStream input = new ObjectInputStream(clientSocket.getInputStream());
            String methodName = input.readUTF();
            int a = input.readInt();
            int b = input.readInt();

            ObjectOutputStream output = new ObjectOutputStream(clientSocket.getOutputStream());
            CalculatorService service = new CalculatorServiceImpl();
            if (methodName.equals("add")) {
                output.writeInt(service.add(a, b));
            } else if (methodName.equals("subtract")) {
                output.writeInt(service.subtract(a, b));
            }
            output.flush();
            clientSocket.close();
        }
    }
}

3. 实现客户端动态代理

客户端使用动态代理调用远程服务:

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

// 动态代理处理器
public class RpcInvocationHandler implements InvocationHandler {

    private String host;
    private int port;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Socket socket = new Socket(host, port);
        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
        output.writeUTF(method.getName());
        for (Object arg : args) {
            output.writeObject(arg);
        }

        ObjectInputStream input = new ObjectInputStream(socket.getInputStream());
        Object result = input.readObject();
        input.close();
        output.close();
        socket.close();
        return result;
    }
}

// 客户端代码
public class RpcClient {
    @SuppressWarnings("unchecked")
    public static <T> T getProxy(Class<T> serviceClass, String host, int port) {
        return (T) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class<?>[]{serviceClass}, new RpcInvocationHandler(host, port));
    }

    public static void main(String[] args) {
        CalculatorService service = RpcClient.getProxy(CalculatorService.class, "localhost", 8080);
        int result1 = service.add(10, 5);
        int result2 = service.subtract(10, 5);

        System.out.println("加法结果: " + result1);
        System.out.println("减法结果: " + result2);
    }
}

4. 运行说明

  1. 服务端:运行 CalculatorServiceImpl,它将开启一个 TCP 服务器,在 8080 端口等待客户端请求。
  2. 客户端:运行 RpcClient,通过动态代理获得 CalculatorService 的代理对象,并调用 addsubtract 方法。这些方法调用将通过网络发送到服务端,由服务端处理并返回结果。

5. 执行结果

运行客户端后,输出如下:

加法结果: 15
减法结果: 5

6. 解析

  • 服务端:简单实现了一个 TCP 服务器,通过 ObjectInputStreamObjectOutputStream 来接收和发送请求。
  • 客户端:使用 JDK 动态代理,通过 RpcInvocationHandler 拦截方法调用,将方法名和参数序列化后发送给服务端,再从服务端获取结果。
1

评论 (0)

取消