找回密码
 立即注册
首页 业界区 业界 用远程代理模式轻松实现远程服务调用,打开编程新大门 ...

用远程代理模式轻松实现远程服务调用,打开编程新大门

布相 2025-6-6 14:44:03
通过远程代理来实现一个简易的远程过程调用实例。带你打开新的大门。
Socket 远程代理服务案例

基于 Socket 的远程服务,我们需要完成以下步骤:

  • 服务端实现:创建一个远程服务,通过 Socket 接受客户端请求并提供计算服务。
  • 客户端实现:客户端通过代理类访问远程计算服务,代理通过网络与服务器交互。
  • 代理类:代理类会通过网络与服务器建立连接,转发请求并返回响应。
看下案例类图应该就明白了
案例类图

1.png

客户端和服务端都共有服务接口RemoteCalculationService,服务端实现了该接口的具体处理逻辑,客户端通过socket来完成具体服务的调用。
在这里必须明确理解的一个点就是,客户端的远程代理类。这个远程代理类是一个实现了共有服务接口RemoteCalculationService的实现类,但是在真实的场景中,这个代理类不需要我们手工动去实现,一般由所依赖的底层去实现(比如Apache CXF),我们要做的事情是配置IP和端口等操作,然后调用接口内的方法即可。
客户端在这个过程中只需要关注这个服务接口RemoteCalculationService有什么方法可以使用、具体传什么参数和返回值是什么即可,给开发者的感觉就像是调用本地方法一样
具体代码实现如下:
远程服务接口

我们首先定义一个远程计算服务接口,它提供加法和减法功能:
  1. // 远程接口
  2. public interface RemoteCalculationService {
  3.     int add(int a, int b);
  4.     int subtract(int a, int b);
  5. }
复制代码
远程服务实现

然后实现该接口,模拟一个远程计算服务。此服务将被远程调用:
  1. public class RemoteCalculationServiceImpl implements RemoteCalculationService {
  2.     @Override
  3.     public int add(int a, int b) {
  4.         return a + b;
  5.     }
  6.     @Override
  7.     public int subtract(int a, int b) {
  8.         return a - b;
  9.     }
  10. }
复制代码
远程服务处理器

该类负责处理来自客户端的请求,它从网络中读取数据并返回计算结果:
  1. import java.io.*;
  2. import java.net.*;
  3. public class RemoteCalculationServiceHandler implements Runnable {
  4.     private Socket socket;
  5.     public RemoteCalculationServiceHandler(Socket socket) {
  6.         this.socket = socket;
  7.     }
  8.     @Override
  9.     public void run() {
  10.         try (
  11.                 ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
  12.                 ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())
  13.         ) {
  14.             // 读取请求的操作
  15.             String operation = (String) inputStream.readObject();
  16.             int a = inputStream.readInt();
  17.             int b = inputStream.readInt();
  18.             RemoteCalculationServiceImpl service = new RemoteCalculationServiceImpl();
  19.             int result = 0;
  20.             System.out.println("执行的操作:"+operation);
  21.             // 根据操作执行相应的计算
  22.             if ("add".equals(operation)) {
  23.                 result = service.add(a, b);
  24.             } else if ("subtract".equals(operation)) {
  25.                 result = service.subtract(a, b);
  26.             }
  27.             System.out.println("执行结果:"+result);
  28.             // 发送结果回客户端
  29.             outputStream.writeInt(result);
  30.             outputStream.flush();
  31.         } catch (IOException | ClassNotFoundException e) {
  32.             e.printStackTrace();
  33.         } finally {
  34.             try {
  35.                 socket.close();
  36.             } catch (IOException e) {
  37.                 e.printStackTrace();
  38.             }
  39.         }
  40.     }
  41. }
复制代码
远程Socket服务
  1. public class RemoteServer {
  2.     // 服务器端启动
  3.     public static void main(String[] args) {
  4.         try (ServerSocket serverSocket = new ServerSocket(8080)) {
  5.             System.out.println("Server is running...");
  6.             while (true) {
  7.                 Socket socket = serverSocket.accept();
  8.                 new Thread(new RemoteCalculationServiceHandler(socket)).start();
  9.             }
  10.         } catch (IOException e) {
  11.             e.printStackTrace();
  12.         }
  13.     }
  14. }
复制代码
远程服务代理类

代理类负责与远程服务通信。客户端调用代理的方法时,代理会通过 Socket 连接到远程服务器,将请求发送给远程服务,然后返回结果。
  1. import java.io.*;
  2. import java.net.*;
  3. public class RemoteCalculationServiceProxy implements RemoteCalculationService {
  4.     private String serverAddress;
  5.     private int serverPort;
  6.     public RemoteCalculationServiceProxy(String serverAddress, int serverPort) {
  7.         this.serverAddress = serverAddress;
  8.         this.serverPort = serverPort;
  9.     }
  10.     @Override
  11.     public int add(int a, int b) {
  12.         return sendRequest("add", a, b);
  13.     }
  14.     @Override
  15.     public int subtract(int a, int b) {
  16.         return sendRequest("subtract", a, b);
  17.     }
  18.     private int sendRequest(String operation, int a, int b) {
  19.         try (
  20.             Socket socket = new Socket(serverAddress, serverPort);
  21.             ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
  22.             ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())
  23.         ) {
  24.             // 发送操作请求
  25.             outputStream.writeObject(operation);
  26.             outputStream.writeInt(a);
  27.             outputStream.writeInt(b);
  28.             outputStream.flush();
  29.             // 读取结果
  30.             return inputStream.readInt();
  31.         } catch (IOException e) {
  32.             e.printStackTrace();
  33.         }
  34.         return 0;
  35.     }
  36. }
复制代码
客户端

客户端通过 RemoteCalculationServiceProxy 访问远程计算服务。代理会将请求发送到服务器并接收响应。
  1. public class Client {
  2.     public static void main(String[] args) {
  3.         RemoteCalculationService service = new RemoteCalculationServiceProxy("localhost", 8080);
  4.         // 通过代理调用远程服务
  5.         System.out.println("add 执行结果: " + service.add(10, 5));
  6.         System.out.println("subtract 执行结果: " + service.subtract(10, 5));
  7.     }
  8. }
复制代码
运行步骤

1.运行服务器端
首先运行服务器端RemoteServer,这会启动一个 ServerSocket 来监听客户端的请求。每当接收到客户端请求时,服务器会在一个新线程中处理。
2.运行客户端
然后启动客户端Client,它通过代理类与服务器端进行交互,发送计算请求并接收结果。
结果输出

远程服务端输出结果:
Server is running...
执行的操作:add
执行结果:15
执行的操作:subtract
执行结果:5
客户端输出结果
add 执行结果: 15
subtract 执行结果: 5
远程代理的应用

比如:Apache CXF 服务框架
  1. import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
  2. public class Client {
  3.     public static void main(String[] args) {
  4.         JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
  5.         factory.setServiceClass(HelloWorldService.class);
  6.         factory.setAddress("http://localhost:8080/hello");
  7.         HelloWorldService service = (HelloWorldService) factory.create();
  8.         System.out.println(service.sayHello("World"));
  9.     }
  10. }
复制代码
配置服务接口class和服务路由,通过工厂模式创建对应的远程代理实例化对象,客户端只需要关注接口有什么方法即可,调用远程服务方法就像是调用本地方法一样。
比如:RPC协议框架,例如:dubbo、gRPC等。
总结

通过这种实现,您可以模拟一个基于 Socket 的远程服务和远程代理的应用。客户端通过 RemoteCalculationServiceProxy 与远程服务进行通信,而远程服务通过RemoteCalculationServiceImpl 提供计算功能。客户端在使用代理对象进行操作时,就像是调用本地的方法一样,无感的实现远程方法的调用。这种调用方式又称为远程过程调用。常用的远程过程调用框架有CXF、Dubbo、gRPC等等,其核心思想之一都是远程代理,它实现了在本地调用远程服务时的透明性,使得远程调用看起来像本地调用。
2.gif

需要查看往期设计模式文章的,可以在个人主页中或者文章开头的集合中查看,可关注我,持续更新中。。。
超实用的SpringAOP实战之日志记录
2023年下半年软考考试重磅消息
通过软考后却领取不到实体证书?
计算机算法设计与分析(第5版)
Java全栈学习路线、学习资源和面试题一条龙
软考证书=职称证书?
软考中级--软件设计师毫无保留的备考分享

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册