實現自己的大發888平臺開發框架(采用Java Socket)
阿新 • • 發佈:2018-07-23
exe provide lang 輸出流 reflect cati trace 客戶端 hand 大發888平臺開發實現原理圖:
1、Service API對應服務接口。
HelloService.java代碼如下:
package com.shan.rpc.service;
public interface HelloService {
public String sayHello(String content);
}
2、Service Impl對應服務接口的實現:
HelloServiceImpl.java代碼如下:
package com.shan.rpc.service.impl; import com.shan.rpc.service.HelloService; public class HelloServiceImpl implements HelloService { public String sayHello(String content) { return "hello," + content; } }
3、Consumer Proxy 角色對應服務消費者代理類。通過實現服務接口的動態代理對象獲得服務接口的動態代理實例Proxy.newProxyInstance,通過實現InvocationHandler接口中的invoke方法來完成遠程RPC的調用。具體通過輸出流將調用接口的方法及參數寫入Socket,發起遠程調用。之後通過Java對象輸入流從Socket獲得返回結果。
ConsumerProxy.java代碼如下:
package com.shan.rpc.framework; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.Socket; public class ConsumerProxy { /** * @Title: consume * @Description:服務消費代理 * @author fuss * @date 2018年7月12日 * @param interfaceClass * @param host * @param port * @return * @throws Exception */ public static <T> T consume(final Class<T> interfaceClass, final String host, final int port) throws Exception { return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class<?>[]{interfaceClass}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Socket socket = new Socket(host, port); try { ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); try { output.writeUTF(method.getName()); output.writeObject(args); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { Object result = input.readObject(); if (result instanceof Throwable) { throw (Throwable) result; } return result; } finally { input.close(); } } finally { output.close(); } } finally { socket.close(); } } }); } }
4、Provider Reflect角色對應服務發布實現。通過輸入流從Socket中按照ConsumerProxy的寫入順序註意獲取調動方法
名稱及方法參數,通過MethodUtils.invokeExactMethod對服務實現類發起反射調用,將調用結果寫入Socket返回給對方。
ProviderReflect.java代碼如下:
package com.shan.rpc.framework; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.commons.lang3.reflect.MethodUtils; public class ProviderReflect { private static final ExecutorService EXECUTOR_SERVICE = Executors.newCachedThreadPool(); /** * @Title: provider * @Description:服務發布 * @author fuss * @date 2018年7月12日 * @param service * @param port * @throws Exception */ public static void provider(final Object service, int port) throws Exception { ServerSocket serverSocket = new ServerSocket(port); while (true) { final Socket socket = serverSocket.accept(); EXECUTOR_SERVICE.execute(new Runnable() { @Override public void run() { try { ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { try { String methodName = input.readUTF();//方法名稱 Object[] args = (Object[]) input.readObject();//方法參數 ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); try { Object result = MethodUtils.invokeExactMethod(service, methodName, args); output.writeObject(result); } catch (Throwable t) { output.writeObject(t); } finally { output.close(); } } catch (Exception e) { e.printStackTrace(); } finally { input.close(); } } finally { socket.close(); } } catch (Exception e) { e.printStackTrace(); } } }); } } }
然後寫main方法通過ProviderReflect發布服務,代碼如下:
package com.shan.rpc.invoke;
import com.shan.rpc.framework.ProviderReflect;
import com.shan.rpc.service.HelloService;
import com.shan.rpc.service.impl.HelloServiceImpl;
public class RpcProviderMain {
public static void main(String[] args) throws Exception {
HelloService service = new HelloServiceImpl();
ProviderReflect.provider(service, 8083);
}
}
客戶端調用遠程服務的main方法,代碼如下:
package com.shan.rpc.invoke;
import com.shan.rpc.framework.ConsumerProxy;
import com.shan.rpc.service.HelloService;
public class RpcConsumerMain {
public static void main(String[] args) throws Exception {
HelloService service = ConsumerProxy.consume(HelloService.class, "127.0.0.1", 8083);
for (int i = 0; i < 1000; i++) {
String hello = service.sayHello("fuss_" + i);
System.out.println(hello);
Thread.sleep(1000);
}
}
}
執行結果如圖:
實現自己的大發888平臺開發框架(采用Java Socket)