引言
本文利用java自带的socket编程实现了一个简单的rpc调用框架,由两个工程组成分别名为battercake-provider(服务提供者)、battercake-consumer(服务调用者)。
设计思路如下: 1、在battercake-provider中,写一个服务叫BatterCakeService
2、在battercake-provider中,启动RpcProvider,发布该服务
3、在battercake-consumer中,启动测试类RpcTest
4、在battercake-consumer中,利用jdk动态代理,获得BatterCakeService的动态代理类BatterCakeService$Proxy0
5、在battercake-consumer中,动态代理类BatterCakeService$Proxy0,与battercake-provider建立socket连接,battercake-provider针对每一个连接,都会启动一个ServerThread处理请求,代理类则发送服务参数等相关信息
6、在battercake-consumer中,接收battercake-provider的ServerThread请求返回的结果。
上述过程时序图如下所示
image
接下来上代码!! 服务提供者
本部分的工程为battercake-provider,项目结构图如下图所示
先上使用的部分的代码 先创建一个微服务,接口如下
package com.rjzheng.service;public interface BatterCakeService { /** * 卖煎饼的服务 * @param name * @return */ public String sellBatterCake(String name);}
package com.rjzheng.service.impl;import com.rjzheng.service.BatterCakeService;public class BatterCakeServiceImpl implements BatterCakeService { @Override public String sellBatterCake(String name) { // TODO Auto-generated method stub return name+"煎饼,卖的特别好"; }}
package com.rjzheng.start;import com.rjzheng.rpc.RpcProvider;import com.rjzheng.service.BatterCakeService;import com.rjzheng.service.impl.BatterCakeServiceImpl;public class RpcBootStrap { public static void main(String[] args) throws Exception { BatterCakeService batterCakeService =new BatterCakeServiceImpl(); //发布卖煎饼的服务,注册在20006端口 RpcProvider.export(20006,batterCakeService); }}
package com.rjzheng.rpc;import java.net.ServerSocket;import java.net.Socket;import java.util.ArrayList;import java.util.Arrays;import java.util.List;/** * RPC服务提供器 * @author zhengrongjun * */public class RpcProvider { //存储注册的服务列表 private static List
package com.rjzheng.rpc;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Method;import java.net.Socket;import java.util.List;public class ServerThread implements Runnable { private Socket client = null; private List
package com.rjzheng.rpc;import java.lang.reflect.Proxy;public class RpcConsumer { public staticT getService(Class clazz,String ip,int port) { ProxyHandler proxyHandler =new ProxyHandler(ip,port); return (T)Proxy.newProxyInstance(RpcConsumer.class.getClassLoader(), new Class [] {clazz}, proxyHandler); }}
package com.rjzheng.rpc;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.net.Socket;import com.rjzheng.service.BatterCakeService;public class ProxyHandler implements InvocationHandler { private String ip; private int port; public ProxyHandler(String ip, int port) { // TODO Auto-generated constructor stub this.ip = ip; this.port = port; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Socket socket = new Socket(this.ip, this.port); ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream()); ObjectInputStream input = new ObjectInputStream(socket.getInputStream()); try { output.writeObject(proxy.getClass().getInterfaces()[0]); output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(args); output.flush(); Object result = input.readObject(); if(result instanceof Throwable) { throw (Throwable) result; } return result; } finally { socket.shutdownOutput(); } }}
package com.rjzheng.start;import com.rjzheng.rpc.RpcConsumer;import com.rjzheng.service.BatterCakeService;public class RpcTest { public static void main(String[] args) { BatterCakeService batterCakeService=RpcConsumer.getService(BatterCakeService.class, "127.0.0.1", 20006); String result=batterCakeService.sellBatterCake("双蛋"); System.out.println(result); }}