目录
RPC(Remote Procedure Call)简称远程过程调用,就是从一台机器(客户端)上通过参数传递的方式(就像调用了本地方法一样)调用另一台机器(服务器)上的一个方法(可以统称为服务)并得到返回的结果。
服务端搭建
IHelloService接口(就是客户端想远程调用的)
public interface IHelloService {
String sayHello(String str);
}
HelloServiceImpl IHelloService的实现类
public class HelloServiceImpl implements IHelloService{
@Override
public String sayHello(String str) {
return "Hello:" + str;
}
}
RpcRequest 客户端请求的封装类 实现了可序列化(因为要序列化这个类进行网络IO)
public class RpcRequest implements Serializable {
//对象名
private String className;
//方法名
private String methodName;
//参数
private Object[] params;
//参数类型
private Class[] type;
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getParams() {
return params;
}
public void setParams(Object[] params) {
this.params = params;
}
public Class[] getType() {
return type;
}
public void setType(Class[] type) {
this.type = type;
}
}
RpcProxyServer 进行服务的发布
public class RpcProxyServer {
//发布service
//创建线程池
private final ExecutorService executorService = Executors.newCachedThreadPool();
/**
* 进行服务的发布
* @param service 想要发布的服务
* @param port 接受端口号
*/
public void publish(Object service, int port) {
//创建监听
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("开启服务");
while(true) {
final Socket socket = serverSocket.accept();
System.out.println("客户端" + socket.getPort() +"已连接");
executorService.execute(new ProcessorHandler(service, socket));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
ProcessorHandler 执行连接和网络IO的线程
public class ProcessorHandler implements Runnable{
//service对象
Object service;
Socket socket;
public ProcessorHandler(Object service, Socket socket) {
this.service = service;
this.socket = socket;
}
@Override
public void run() {
System.out.println("执行线程任务");
ObjectInputStream inputStream = null;
ObjectOutputStream outputStream = null;
try {
inputStream = new ObjectInputStream(socket.getInputStream());
//反序列化
RpcRequest request = (RpcRequest) inputStream.readObject();
System.out.println("收到客户端通过网络IO发送过来的request");
//执行这个请求方法
Object result = invoke(request);
//把得到的返回结果序列化发送
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(result);
outputStream.flush();
System.out.println("把结果返回给客户端"+socket.getPort());
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
}
}
/**
* 把接收的RpcRequest对象利用反射来执行 并获得返回结果
* @param request
*/
public Object invoke(RpcRequest request) throws Exception {
//获取class
Class clazz = Class.forName(request.getClassName());
//获取方法名
Method method = clazz.getMethod(request.getMethodName(),request.getType());
//利用反射调用方法 获取返回结果
Object result = method.invoke(service,request.getParams());
return result;
}
}
启动代码
public class Application {
public static void main(String[] args) {
//发布服务
RpcProxyServer rpcProxyServer = new RpcProxyServer();
HelloServiceImpl helloService = new HelloServiceImpl();
//调用publish方法开启监听
rpcProxyServer.publish(helloService,7486);
System.out.println("end");
}
}
客户端
RpcProxyClient JDK动态代理类 代理我们的调用方法
public class RpcProxyClient{
public <T> T creatProxyClient (Class<T> interfaceCls, String host, int port) {
return (T) Proxy.newProxyInstance(interfaceCls.getClassLoader(),
new Class<?>[]{interfaceCls}, new ProxyInvocationHandler(host,port) );
}
}
ProxyInvocationHandler JDK动态代理中InvocationHandler 的实现类
public class ProxyInvocationHandler implements InvocationHandler {
String host;
int port;
public ProxyInvocationHandler(String host, int port) {
this.host = host;
this.port = port;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("调用l代理方法");
//创建请求对象
RpcRequest request = new RpcRequest();
request.setClassName(method.getDeclaringClass().getName());
request.setMethodName(method.getName());
request.setParams(args);
request.setType(method.getParameterTypes());
//把请求对象发送给服务端
RpcNetTransport transport = new RpcNetTransport(host,port);
Object result = transport.send(request);
return result;
}
}
RpcNetTransport 进行网络IO所封装的工具类
public class RpcNetTransport {
String host;
int port;
public RpcNetTransport(String host, int port) {
this.host = host;
this.port = port;
}
//给服务端发送数据
public Object send(RpcRequest request) {
Socket socket;
ObjectOutputStream outputStream;
ObjectInputStream inputStream;
Object result = null;
try {
socket = new Socket(host, port);
outputStream = new ObjectOutputStream(socket.getOutputStream());
System.out.println("把request序列化通过网络IO发送给服务短");
//序列化
outputStream.writeObject(request);
outputStream.flush();
inputStream = new ObjectInputStream(socket.getInputStream());
//反序列化
result = inputStream.readObject();
System.out.println("接收服务端返回的结果");
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭流
}
return result;
}
}
main方法
public static void main( String[] args )
{
IHelloService iHelloService = null;
//用代理的方式调用
iHelloService = new RpcProxyClient().creatProxyClient(IHelloService.class,"localhost", 7486);
System.out.println(iHelloService.sayHello("client-01"));//类似调用本地方法
}
执行结果
客户端控制台
服务端控制台