基本思路也是基于socket完成通信,远程的调用主要封装了一个RpcRequest的实体对用的类名称和方法名称以及调用参数进行了封装
不多说,直接看代码的实现,实现主要分为共用的apI的部分
,还有就是客户端部分
和服务端的部分
客户端需要发起socket的调用,完成对需要调用的类的名称以及方法名称以及参数的封装成RpcRequest实体,同样客户端需要对调用接口进行动态代理
服务端需要new 一个ServerSocket对到来的请求进行监听,需要从socket的shuc输入流中对发过来的RpcRequest进行解析,然后通过反射进行对实际的远程实现类反射调用,最终完成结果的写入socket的输出流中
代码的下载可以参考: https://github.com/sunkang123/jdk/tree/master/java-rmi
具体的代码如下:
先看共用的api部分
/**
* @Project: 3.DistributedProject
* @description: IHello 调用的接口
* @author: sunkang
* @create: 2018-06-23 11:30
* @ModificationHistory who when What
**/
public interface IHello {
String sayHello(String msg) throws RemoteException;
}
/**
* @Project: 3.DistributedProject
* @description: 封装的请求实体
* @author: sunkang
* @create: 2018-06-23 11:33
* @ModificationHistory who when What
**/
public class RpcRequest implements Serializable {
private String className;
private String methodName;
private Object[] paramters;
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[] getParamters() {
return paramters;
}
public void setParamters(Object[] paramters) {
this.paramters = paramters;
}
}
客户端的实现
/**
* @Project: 3.DistributedProject
* @description: 对接口的代理类
* @author: sunkang
* @create: 2018-06-23 11:38
* @ModificationHistory who when What
**/
public class RpcProxyClient {
public Object createProxy(Class clazz,String host,int port){
return Proxy.newProxyInstance(clazz.getClassLoader(),new Class[]{clazz},new RemoteInvocationHandler(host,port));
}
}
/**
* @Project: 3.DistributedProject
* @description: 具体的代理实现
* @author: sunkang
* @create: 2018-06-23 11:41
* @ModificationHistory who when What
**/
public class RemoteInvocationHandler implements InvocationHandler {
private String host;
private int port;
public RemoteInvocationHandler(String host, int port) {
this.host=host;
this.port=port;
}
@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.setParamters(args);
TcpTransport tsp =new TcpTransport(host,port);
return tsp.send(request);
}
}
/**
* @Project: 3.DistributedProject
* @description: 模拟tcp层 发起socket连接
* @author: sunkang
* @create: 2018-06-23 11:45
* @ModificationHistory who when What
**/
public class TcpTransport {
private String host;
private int port;
public TcpTransport(String host, int port) {
this.host=host;
this.port=port;
}
private Socket newSocket(){
try {
Socket socket = new Socket(host,port);
return socket;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public Object send(RpcRequest request) {
Socket socket = newSocket();
ObjectOutputStream oos = null ;
ObjectInputStream ois =null;
try {
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(request);
ois = new ObjectInputStream(socket.getInputStream());
Object obj = ois.readObject();
return obj;
} catch (Exception e) {
e.printStackTrace();
}finally {
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(oos != null){
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(ois !=null){
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
/**
* @Project: 3.DistributedProject
* @description: 具体的客户端的调用者
* @author: sunkang
* @create: 2018-06-23 11:39
* @ModificationHistory who when What
**/
public class ClentDemo {
public static void main(String[] args) throws RemoteException {
RpcProxyClient proxyClient = new RpcProxyClient();
IHello hello =(IHello) proxyClient.createProxy(IHello.class,"localhost",8099);
System.out.println(hello.sayHello("sunkang you are very cool"));
}
}
- 服务端的调用
/**
* @Project: 3.DistributedProject
* @description: 具体的服务实现者
* @author: sunkang
* @create: 2018-06-23 11:33
* @ModificationHistory who when What
**/
public class HelloImpl implements IHello {
@Override
public String sayHello(String msg) throws RemoteException {
return "hello world "+ msg;
}
}
/**
* @Project: 3.DistributedProject
* @description: 模拟服务发布,发起ServerSocket的监听
* @author: sunkang
* @create: 2018-06-23 11:59
* @ModificationHistory who when What
**/
public class RpcServer {
private static final ExecutorService cashedThreadPool = Executors.newCachedThreadPool();
public void publish(final Object service, int port){
try {
ServerSocket serverSocket = new ServerSocket(port);
while(true){
Socket socket = serverSocket.accept();
cashedThreadPool.execute(new ProcessHandler(socket,service));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* @Project: 3.DistributedProject
* @description: 完成具体服务的调用逻辑和结果的socket写入
* @author: sunkang
* @create: 2018-06-23 12:37
* @ModificationHistory who when What
**/
public class ProcessHandler implements Runnable {
private Socket socket;
private Object service;
public ProcessHandler(Socket socket, Object service) {
this.socket = socket;
this.service = service;
}
@Override
public void run() {
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
ois = new ObjectInputStream(socket.getInputStream());
RpcRequest request = (RpcRequest) ois.readObject();
Object obj = invoke(request, service);
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(obj);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private Object invoke(RpcRequest request, Object service) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Object[] types = request.getParamters();
Class[] methodParamters = new Class[types.length];
for (int i = 0; i < types.length; i++) {
methodParamters[i] = types[i].getClass();
}
Method method = service.getClass().getMethod(request.getMethodName(), methodParamters);
return method.invoke(service, types);
}
}
/**
* @Project: 3.DistributedProject
* @description: 模拟服务发布,发起ServerSocket的监听
* @author: sunkang
* @create: 2018-06-23 11:59
* @ModificationHistory who when What
**/
public class RpcServer {
private static final ExecutorService cashedThreadPool = Executors.newCachedThreadPool();
public void publish(final Object service, int port){
try {
ServerSocket serverSocket = new ServerSocket(port);
while(true){
Socket socket = serverSocket.accept();
cashedThreadPool.execute(new ProcessHandler(socket,service));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}