前言:
環境:
windown 10
Eclipse
JDK 1.8
RPC的概念:
RPC 是遠程過程調用,是分布式網站的基礎。
實驗
SayHelloService.java 接口類,用於規范
SayHelloServiceImpl.java,是SayHelloService 的實現類
Provider.java 是服務的提供類
Consumer.java 是服務的消費類
SayHelloService.java
package cn.szxy;
/**
* 接口
*
*/
public interface SayHelloService {
/**
* 返回一個字符串
* @param str
* @return
*/
public String sayHello(String str);
}
SayHelloServiceImpl.java
package cn.szxy;
/**
* 實現類
*
*/
public class SayHelloServiceImpl implements SayHelloService{
@Override
public String sayHello(String str) {
if(str.equals("Hello")){
return "Hello 你好";
}else{
return "byebye!";
}
}
}
服務提供類 Provider.java
package cn.szxy;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
/**
*
* 基於TCP協議的 服務提供端
*
*/
public class Provider{
public static void main(String[] args) throws Exception {
HashMap<Object, Object> map = new HashMap<>();
map.put(SayHelloService.class.getName(), new SayHelloServiceImpl());
//創建 socket 對象
ServerSocket server = new ServerSocket(5555);
System.out.println("服務器已啟動....");
while(true){
//監聽用戶請求
Socket client = server.accept();
//獲取輸入流
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
String inferName = ois.readUTF();
String methodName = ois.readUTF();
Class<?>[] parameterTypes = (Class<?>[]) ois.readObject();
Object[] arguments = (Object[])ois.readObject();
//執行調用
Class<?> serviceClass = Class.forName(inferName);
Object service = map.get(inferName);
Method method = serviceClass.getMethod(methodName, parameterTypes);
//執行方法,並返回結果
Object result = method.invoke(service, arguments);
System.out.println("要發送處理的結果: "+result);
//獲取輸出流
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeObject(result);
oos.writeUTF("調用結束");
oos.flush();
;
}
}
}
服務消費類 Consumer
package cn.szxy;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.Socket;
import java.util.Scanner;
/**
*
* 基於 TCP的服務器消費端
*
*
*/
public class Consumer{
public static void main(String[] args) throws Exception {
//獲取需要發送的東西
String interName = SayHelloService.class.getName();
Method method = SayHelloService.class.getMethod("sayHello", String.class);
Object[] argurements = {"Hello"};
//創建 socket 對象
Socket client = new Socket("127.0.0.1",5555);
//獲取輸出流
ObjectOutputStream oos = new ObjectOutputStream(client.getOutputStream());
oos.writeUTF(interName);
oos.writeUTF(method.getName());
oos.writeObject(method.getParameterTypes());
oos.writeObject(argurements);
//刷新緩沖區,不然會出現”連接重置 connection reset 找不到資源 “的問題
oos.flush();
//獲取輸入流
ObjectInputStream ois = new ObjectInputStream(client.getInputStream());
Object result = ois.readObject();
String str = ois.readUTF();
System.out.println("RPC遠程調用結果: ");
System.out.println(result);
//關閉連接
client.close();
}
}
總結
RPC 是基於 Java 的Socket的基礎上,利用 socket 和 IO流將服務消費端需要調用的類和類中方法以及方法的參數發送給服務提供端
服務提供端接受了服務消費端的請求,利用反射技術將對應需要的方法執行並返回結果,發送給服務消費者。