用遠程代理模式輕松實現遠程服務調用,打開編程新大門
通過遠程代理來實現一個簡易的遠程過程調用實例。帶你打開新的大門。
Socket 遠程代理服務案例
基于 Socket 的遠程服務,我們需要完成以下步驟:
- 服務端實現:創建一個遠程服務,通過 Socket 接受客戶端請求并提供計算服務。
- 客戶端實現:客戶端通過代理類訪問遠程計算服務,代理通過網絡與服務器交互。
- 代理類:代理類會通過網絡與服務器建立連接,轉發請求并返回響應。
看下案例類圖應該就明白了
案例類圖

客戶端和服務端都共有服務接口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等等,其核心思想之一都是遠程代理,它實現了在本地調用遠程服務時的透明性,使得遠程調用看起來像本地調用。

需要查看往期設計模式文章的,可以在個人主頁中或者文章開頭的集合中查看,可關注我,持續更新中。。。

浙公網安備 33010602011771號