最全最简单的dubbo教程-实现个简单的RPC《十九》

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jingyangV587/article/details/86507330

项目案例的结构

在这里插入图片描述

服务器端业务处理类

//服务器端业务处理类
public class InvokeHandler extends ChannelInboundHandlerAdapter {
    //得到某接口下某个实现类的名字
    private String getImplClassName(ClassInfo classInfo) throws Exception{
        //服务方实现类所在的包路径
        String interfacePath="com.gjy.rpc.server";
        Class superClass=Class.forName(classInfo.getClassName());
        Reflections reflections = new Reflections(interfacePath);
        //得到某接口下的所有实现类
        Set<Class> ImplClassSet=reflections.getSubTypesOf(superClass);
        if(ImplClassSet.size()==0){
            System.out.println("未找到实现类");
            return null;
        }else if(ImplClassSet.size()>1){
            System.out.println("找到多个实现类,未明确使用哪一个");
            return null;
        }else {
            //把集合转换为数组
            Class[] classes=ImplClassSet.toArray(new Class[0]);
            return classes[0].getName(); //得到实现类的名字
        }
    }

    @Override  //读取客户端发来的数据并通过反射调用实现类的方法
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ClassInfo classInfo = (ClassInfo) msg;
        Object clazz = Class.forName(getImplClassName(classInfo)).newInstance();
        Method method = clazz.getClass().getMethod(classInfo.getMethodName(), classInfo.getTypes());
        //通过反射调用实现类的方法
        Object result = method.invoke(clazz, classInfo.getObjects());
        ctx.writeAndFlush(result);
    }
}

客户端代理类

//客户端代理类
public class NettyRPCProxy {
	// 根据接口创建代理对象
	public static Object create(Class target) {
		return Proxy.newProxyInstance(target.getClassLoader(), new Class[] { target }, new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				// 封装ClassInfo
				ClassInfo classInfo = new ClassInfo();
				classInfo.setClassName(target.getName());
				classInfo.setMethodName(method.getName());
				classInfo.setObjects(args);
				classInfo.setTypes(method.getParameterTypes());

				// 开始用Netty发送数据
				EventLoopGroup group = new NioEventLoopGroup();
				ResultHandler resultHandler = new ResultHandler();
				try {
					Bootstrap b = new Bootstrap();
					b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
						@Override
						public void initChannel(SocketChannel ch) throws Exception {
							ChannelPipeline pipeline = ch.pipeline();
							// 编码器
							pipeline.addLast("encoder", new ObjectEncoder());
							// 解码器 构造方法第一个参数设置二进制数据的最大字节数 第二个参数设置具体使用哪个类解析器
							pipeline.addLast("decoder",
									new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
							// 客户端业务处理类
							pipeline.addLast("handler", resultHandler);
						}
					});
					ChannelFuture future = b.connect("127.0.0.1", 9999).sync();
					future.channel().writeAndFlush(classInfo).sync();
					future.channel().closeFuture().sync();
				} finally {
					group.shutdownGracefully();
				}
				return resultHandler.getResponse();
			}
		});
	}
}

封装类信息

//封装类信息
public class ClassInfo implements Serializable {

  private static final long serialVersionUID = 1L;

  private String className;  //类名
  private String methodName;//方法名
  private Class<?>[] types; //参数类型
  private Object[] objects;//参数列表
  //省略get set
}

写samples开始测试

接口定义

public interface HelloRPC {
    String say(String name);
}

服务提供者

实现接口:

public String say(String name) {
		return name;
	}

开启服务:

public static void main(String[] args) throws Exception {
	        new RPCServer(9999).start();
	    }

服务消费者

public static void main(String[] args) {
		HelloRPC helloRPC = (HelloRPC) NettyRPCProxy.create(HelloRPC.class);
		System.out.println(helloRPC.say("RPC"));
	}

完整案例下载:https://gitee.com/jingyang3877/all-examples/blob/master/jingyang3877-gjy-rpc-master.zip

猜你喜欢

转载自blog.csdn.net/jingyangV587/article/details/86507330