RPC
RPC(Remote Procedure Call)即远程过程调用协议。是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。
基于Socket实现简易RPC
公共组件
定义一个公共组件,客户端和服务器都依赖这个组件。包含三个类:
UserHandleService 接口:定义了远程调用的方法。
public interface UserHandleService {
public String getUserInfo(User user);
public String sayHello(User user);
}
User类:实体类
import java.io.Serializable;
public class User implements Serializable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
RpcRequest类:请求类,包含调用的类、方法以及参数。
import java.io.Serializable;
public class RpcRequest implements Serializable {
private String className;
private String methodName;
private Object[] parametes;
public RpcRequest(){
}
public RpcRequest(String className, String methodName, Object[] parametes) {
this.className = className;
this.methodName = methodName;
this.parametes = parametes;
}
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[] getParametes() {
return parametes;
}
public void setParametes(Object[] parametes) {
this.parametes = parametes;
}
}
服务端
UserHandleServiceImpl类:定义了远程调用方法的具体实现
import com.dmf.api.User;
import com.dmf.api.UserHandleService;
public class UserHandleServiceImpl implements UserHandleService {
@Override
public String getUserInfo(User user) {
System.out.println(user);
return "姓名:"+user.getName()+";年龄:"+user.getAge();
}
@Override
public String sayHello(User user) {
System.out.println(user.getName()+"say Hello!");
return user.getName()+"say Hello!";
}
}
RpcServerHandleThread类:线程类,处理socket通信
import com.dmf.api.RpcRequest;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Socket;
public class RpcServerHandleThread implements Runnable {
private Socket socket = null;
private UserHandleService service;
public RpcServerHandleThread(UserHandleService service,Socket socket) {
this.socket = socket;
this.service = service;
}
@Override
public void run() {
ObjectOutputStream outputStream= null;
ObjectInputStream inputStream = null;
try {
inputStream = new ObjectInputStream(socket.getInputStream());
RpcRequest request = (RpcRequest)inputStream.readObject();
Object result = invoke(request);
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(result);
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//通过反射调用客户端想要调用的方法
private Object invoke(RpcRequest request) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
//调用方法的参数
Object[] args = request.getParametes();
Method method = null;
Class clazz;
if(args!=null && args.length>0){
//参数类型
Class<?>[] types = new Class[args.length];
for(int i=0;i<args.length;i++){
types[i] = args[i].getClass();
}
clazz = Class.forName(request.getClassName());
method = clazz.getMethod(request.getMethodName(),types);
}else{
clazz = Class.forName(request.getClassName());
method = clazz.getMethod(request.getMethodName());
}
//service是具体调用的类的实例对象
Object result = method.invoke(service,args);
return result;
}
}
RpcServer类:通过线程池来实现socket通信
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class RpcServer {
public static void main(String[] args) {
publish();
}
public static void publish(){
UserHandleServiceImpl service = new UserHandleServiceImpl();
ExecutorService pool = Executors.newCachedThreadPool();
ServerSocket server = null;
try {
server = new ServerSocket(8080);
while (true){
Socket socket = server.accept();
pool.execute(new RpcServerHandleThread(service,socket));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
客户端
ClientProxy:通过动态代理创建需要调用的类的实例
import java.lang.reflect.Proxy;
public class ClientProxy {
public <T> T getClassByProxy(final Class<T> interfaceCls,String host,int port){
return (T)Proxy.newProxyInstance(interfaceCls.getClassLoader(),
new Class<?>[]{interfaceCls},new RemoteInvocationHandler(host,port));
}
}
RemoteInvocationHandler类:动态代理的处理类
import com.dmf.api.RpcRequest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class RemoteInvocationHandler implements InvocationHandler {
private String hostName;
private int port;
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
public int getPort() {
return port;
}
public RemoteInvocationHandler(String hostName, int port) {
this.hostName = hostName;
this.port = port;
}
public void setPort(int port) {
this.port = port;
}
//通过动态代理创建的对象调用方法时,实际上是调用这个invoke方法。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//设置调用参数
RpcRequest request= new RpcRequest();
request.setClassName(method.getDeclaringClass().getName());
request.setMethodName(method.getName());
request.setParametes(args);
//socket通信将参数传到服务端
RpcClientTransport transport = new RpcClientTransport();
//得到返回结果
Object result = transport.send(request,hostName,port);
return result;
}
}
RpcClientTransport类:基于socket通信
import com.dmf.api.RpcRequest;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class RpcClientTransport {
public Object send(RpcRequest request,String host, int port){
Socket socket = null;
ObjectInputStream inputStream = null;
ObjectOutputStream outputStream = null;
Object result = null;
try {
socket = new Socket(host,port);
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(request);
outputStream.flush();
inputStream = new ObjectInputStream(socket.getInputStream());
result = inputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
if(outputStream!=null){
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(inputStream!=null){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
RpcClient类
import com.dmf.api.User;
import com.dmf.api.UserHandleService;
public class RpcClient {
public static void main(String[] args) {
UserHandleService service = new ClientProxy().getClassByProxy(UserHandleService.class,
"localhost",8080);
User user = new User("张三",20);
System.out.println(service.sayHello(user));
System.out.println(service.getUserInfo(user));
}
}