前言:
环境:
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流将服务消费端需要调用的类和类中方法以及方法的参数发送给服务提供端
服务提供端接受了服务消费端的请求,利用反射技术将对应需要的方法执行并返回结果,发送给服务消费者。