因为是远程调用,所以要用动态代理,然后客户端用socket发送我需要调用类名、方法的名字和数据类型,服务端根据获取的类名、方法名字和类型基于反射invoke进行调用,然后把调用的结果再socket传回给客户端
简单的讲发送调用的类的名称+方法到另外一个服务中,拿到类和方法名之后通过反射调用,把数据返回,这就是远程调用。
手RPC框架实现运程调用 (简易版)BIO
①.创建RPCsenver和RPCclient 工程
senver定义两个模块(api模块和实现模块proveder.
1在api模块中定义一个接口.比如Hello.然后在实现模块里实(把api模块Pom 复制到 provider. 否则实现不了)把api模块install到本地仓库
public interface IHelloService {
String sayHello(String a);}
public class RpcRequest implements Serializable {
/**
* 类名
*/
private String className;
/**
* 方法名
*/
private String methodName;
/**
* 传递的参数
*/
private Object[] parameters;
/**
* 参数类型
*/
private Class[] types;
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[] getParameters() {
return parameters;
}
public void setParameters(Object[] parameters) {
this.parameters = parameters;
}
public Class[] getTypes() {
return types;
}
public void setTypes(Class[] types) {
this.types = types;
}
}
2)在client工程中添加api的Pom 这时候就有了之前写的Hello当然这时候还不能远程调用.因为还没有发布服务,所以在server中写一个发布服务 RPCProxyServer.
public class RpcProxyServer {
private final ExecutorService executorService =Executors.newCachedThreadPool();
public void publisher(Object service,int port){
try (ServerSocket serverSocket = new ServerSocket(port)) {
while (true){
//开启监听
final Socket socket = serverSocket.accept();
executorService.execute(new ProcessorHandler(socket,service));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ProcessorHandler implements Runnable{
Socket socket;
Object service;
public ProcessorHandler(Socket socket, Object service) {
this.socket = socket;
this.service = service;
}
@Override
public void run() {
ObjectInputStream inputStream=null;
ObjectOutputStream outputStream=null;
try {
inputStream=new ObjectInputStream(socket.getInputStream());
//需要哪些信息
//反序列化
RpcRequest rpcRequest=(RpcRequest)inputStream.readObject();
Object inovke = inovke(rpcRequest);
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(inovke);
//刷盘
outputStream.flush();
} catch (Exception e) {
e.printStackTrace();
}finally {
//TODO 关闭流
}
}
private Object inovke(RpcRequest rpcRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Class c=Class.forName(rpcRequest.getClassName());
//反射通过方法名和参数类型 获取方法
Method method = c.getMethod(rpcRequest.getMethodName(), rpcRequest.getTypes());
//invoke执行
Object result = method.invoke(service, rpcRequest.getParameters());
return result;
}
}
public class HelloServerImpl implements IHelloService{
@Override
public String sayHello(String content) {
return "hello 恭喜调用成功 content"+content;
}
}
public class App
{
public static void main( String[] args ) {
HelloServerImpl server = new HelloServerImpl();
RpcProxyServer rpcProxyServer = new RpcProxyServer();
rpcProxyServer.publisher(server,8088);
System.out.println( "Hello World!" );
}
}
②server发布服务并监听端口后.在client端写接收.
1.写一个动态代理类
public class RpcProxyClient {
// JDK动态代理:利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
// CGlib动态代理:利用ASM(开源的Java字节码编辑库,操作字节码)开源包,将代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
//
// 区别:JDK代理只能对实现接口的类生成代理;CGlib是针对类实现代理,对指定的类生成一个子类,并覆盖其中的方法,这种通过继承类的实现方式,不能代理final修饰的类。
public <T> T clientProxy(final Class<T> interfaceCls,final String host,final int port){
return (T) Proxy.newProxyInstance(interfaceCls.getClassLoader(),
new Class<?>[]{interfaceCls},new RemoteInovcationHandler(host,port));
}
}
public class RemoteInovcationHandler implements InvocationHandler {
private String host;
private int port;
public RemoteInovcationHandler(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("触发了调用的代码");
RpcRequest request=new RpcRequest();
request.setClassName(method.getDeclaringClass().getName());
request.setMethodName(method.getName());
request.setParameters(args);
request.setTypes(method.getParameterTypes());
RpcNetTransport rpcNetTransport=new RpcNetTransport(host,port);
Object result=rpcNetTransport.send(request);
return result;
}
}
public class RpcNetTransport {
private String host;
private int port;
public RpcNetTransport(String host, int port) {
this.host = host;
this.port = port;
}
public Object send(RpcRequest request){
Socket socket;
ObjectInputStream inputStream=null;
ObjectOutputStream outputStream=null;
try {
socket=new Socket(host,port);
outputStream = new ObjectOutputStream(socket.getOutputStream());
outputStream.writeObject(request);
outputStream.flush();
inputStream=new ObjectInputStream(socket.getInputStream());
return inputStream.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
public class App {
public static void main(String[] args) {
RpcProxyClient client = new RpcProxyClient();
IHelloService iHelloService = client.clientProxy(IHelloService.class, "localhost", 8088);
String s = iHelloService.sayHello("aaa");
System.out.println(s);
}
}