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

通过远程代理 来实现一个简易的远程过程调用实例。带你打开新的大门。

Socket 远程代理服务案例

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

  1. 服务端实现 :创建一个远程服务,通过 Socket 接受客户端请求并提供计算服务。

  2. 客户端实现:客户端通过代理类访问远程计算服务,代理通过网络与服务器交互。

  3. 代理类:代理类会通过网络与服务器建立连接,转发请求并返回响应。

看下案例类图应该就明白了

案例类图

客户端和服务端都共有服务接口RemoteCalculationService,服务端实现了该接口的具体处理逻辑,客户端通过socket来完成具体服务的调用。

在这里必须明确理解的一个点就是,客户端的远程代理类。这个远程代理类 是一个实现了共有服务接口RemoteCalculationService的实现类,但是在真实的场景中,这个代理类不需要我们手工动去实现,一般由所依赖的底层去实现(比如Apache CXF),我们要做的事情是配置IP和端口等操作,然后调用接口内的方法即可。

客户端在这个过程中只需要关注这个服务接口RemoteCalculationService有什么方法可以使用、具体传什么参数和返回值是什么即可,给开发者的感觉就像是调用本地方法一样

具体代码实现如下:

远程服务接口

我们首先定义一个远程计算服务接口,它提供加法和减法功能:

复制代码
// 远程接口
public interface RemoteCalculationService {
    int add(int a, int b);
    int subtract(int a, int b);
}

远程服务实现

然后实现该接口,模拟一个远程计算服务。此服务将被远程调用:

复制代码
public class RemoteCalculationServiceImpl implements RemoteCalculationService {

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

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

}

远程服务处理器

该类负责处理来自客户端的请求,它从网络中读取数据并返回计算结果:

复制代码
import java.io.*;
import java.net.*;

public class RemoteCalculationServiceHandler implements Runnable {
    private Socket socket;

    public RemoteCalculationServiceHandler(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try (
                ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())
        ) {
            // 读取请求的操作
            String operation = (String) inputStream.readObject();
            int a = inputStream.readInt();
            int b = inputStream.readInt();

            RemoteCalculationServiceImpl service = new RemoteCalculationServiceImpl();
            int result = 0;
            System.out.println("执行的操作:"+operation);
            // 根据操作执行相应的计算
            if ("add".equals(operation)) {
                result = service.add(a, b);
            } else if ("subtract".equals(operation)) {
                result = service.subtract(a, b);
            }
            System.out.println("执行结果:"+result);
            // 发送结果回客户端
            outputStream.writeInt(result);
            outputStream.flush();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

远程Socket服务

复制代码
public class RemoteServer {

    // 服务器端启动
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(8080)) {
            System.out.println("Server is running...");
            while (true) {
                Socket socket = serverSocket.accept();
                new Thread(new RemoteCalculationServiceHandler(socket)).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

远程服务代理类

代理类负责与远程服务通信。客户端调用代理的方法时,代理会通过 Socket 连接到远程服务器,将请求发送给远程服务,然后返回结果。

复制代码
import java.io.*;
import java.net.*;

public class RemoteCalculationServiceProxy implements RemoteCalculationService {
    private String serverAddress;
    private int serverPort;

    public RemoteCalculationServiceProxy(String serverAddress, int serverPort) {
        this.serverAddress = serverAddress;
        this.serverPort = serverPort;
    }

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

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

    private int sendRequest(String operation, int a, int b) {
        try (
            Socket socket = new Socket(serverAddress, serverPort);
            ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream())
        ) {
            // 发送操作请求
            outputStream.writeObject(operation);
            outputStream.writeInt(a);
            outputStream.writeInt(b);
            outputStream.flush();

            // 读取结果
            return inputStream.readInt();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }
}

客户端

客户端通过 RemoteCalculationServiceProxy 访问远程计算服务。代理会将请求发送到服务器并接收响应。

复制代码
public class Client {
    public static void main(String[] args) {
        RemoteCalculationService service = new RemoteCalculationServiceProxy("localhost", 8080);

        // 通过代理调用远程服务
        System.out.println("add 执行结果: " + service.add(10, 5));
        System.out.println("subtract 执行结果: " + service.subtract(10, 5));
    }
}

运行步骤

1.运行服务器端

首先运行服务器端RemoteServer,这会启动一个 ServerSocket 来监听客户端的请求。每当接收到客户端请求时,服务器会在一个新线程中处理。

2.运行客户端

然后启动客户端Client,它通过代理类与服务器端进行交互,发送计算请求并接收结果。

结果输出

远程服务端输出结果:

Server is running...

执行的操作:add

执行结果:15

执行的操作:subtract

执行结果:5

客户端输出结果

add 执行结果: 15

subtract 执行结果: 5

远程代理的应用

比如:Apache CXF 服务框架

复制代码
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class Client {
    public static void main(String[] args) {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(HelloWorldService.class);
        factory.setAddress("http://localhost:8080/hello");
        HelloWorldService service = (HelloWorldService) factory.create();
        System.out.println(service.sayHello("World"));
    }
}

配置服务接口class和服务路由,通过工厂模式创建对应的远程代理实例化对象,客户端只需要关注接口有什么方法即可,调用远程服务方法就像是调用本地方法一样。

比如:RPC协议框架,例如:dubbo、gRPC等。

总结

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

文章转载自: ++渊渟岳++

原文链接: 用远程代理模式轻松实现远程服务调用,打开编程新大门 - 渊渟岳 - 博客园

体验地址: 引迈 - JNPF快速开发平台_低代码开发平台_零代码开发平台_流程设计器_表单引擎_工作流引擎_软件架构

相关推荐
不当菜虚困2 天前
JAVA设计模式——(七)代理模式
java·设计模式·代理模式
XiaoLeisj2 天前
【设计模式】深入解析代理模式(委托模式):代理模式思想、静态模式和动态模式定义与区别、静态代理模式代码实现
java·spring boot·后端·spring·设计模式·代理模式·委托模式
敖行客 Allthinker4 天前
VS Code 智能代理模式:重塑开发体验
vscode·代理模式
XU磊2604 天前
代理模式(Proxy Pattern)详解:以延迟加载图片为例
java·代理模式
碎梦归途7 天前
23种设计模式-结构型模式之代理模式(Java版本)
java·开发语言·jvm·设计模式·代理模式
侧耳倾听1118 天前
java 设计模式之代理模式
java·设计模式·代理模式
〆、风神11 天前
Spring Boot实战:基于策略模式+代理模式手写幂等性注解组件
spring boot·代理模式·策略模式
忘梓.11 天前
解锁动态规划的奥秘:从零到精通的创新思维解析(9)
算法·动态规划·代理模式
_殊途12 天前
代理模式深度解析
代理模式