• netty实现远程调用RPC功能


    netty实现远程调用RPC功能

    PRC的功能一句话说白了,就是远程调用其他电脑的api

    依赖

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.31.Final</version>
    </dependency>
    

    服务端功能模块编写

    1. 项目结构

    2. ClassInfo

      package test;
      
      import java.io.Serializable;
      
      public class ClassInfo implements Serializable {
      
          private static final long serialVersionUID = -8970942815543515064L;
          
          private String className;//类名
          private String methodName;//函数名称
          private Class<?>[] types;//参数类型  
          private Object[] objects;//参数列表  
          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 Class<?>[] getTypes() {
              return types;
          }
          public void setTypes(Class<?>[] types) {
              this.types = types;
          }
          public Object[] getObjects() {
              return objects;
          }
          public void setObjects(Object[] objects) {
              this.objects = objects;
          }
      }
      
    3. InvokerHandler

      package test;
      
      import java.lang.reflect.Method;
      import java.util.concurrent.ConcurrentHashMap;
      
      import io.netty.channel.ChannelHandlerContext;
      import io.netty.channel.ChannelInboundHandlerAdapter;
      
      public class InvokerHandler extends ChannelInboundHandlerAdapter {
          public static ConcurrentHashMap<String, Object> classMap = new ConcurrentHashMap<String,Object>();
          @Override  
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
              ClassInfo classInfo = (ClassInfo)msg;
              Object claszz = null;
              if(!classMap.containsKey(classInfo.getClassName())){
                  try {
                      claszz = Class.forName(classInfo.getClassName()).getDeclaredConstructor().newInstance();
                      classMap.put(classInfo.getClassName(), claszz);
                  } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                      e.printStackTrace();
                  }
              }else {
                  claszz = classMap.get(classInfo.getClassName());
              }
              Method method = claszz.getClass().getMethod(classInfo.getMethodName(), classInfo.getTypes());  
              Object result = method.invoke(claszz, classInfo.getObjects()); 
              System.out.println("服务器接受客户端的数据" + result);
              ctx.write("SeverSendData");
              ctx.flush();  
              ctx.close();
          }  
          @Override  
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
              cause.printStackTrace();  
              ctx.close();  
          }  
      
      }
      
    4. RPCServer

      package test;
      
      import io.netty.bootstrap.ServerBootstrap;
      import io.netty.channel.ChannelFuture;
      import io.netty.channel.ChannelInitializer;
      import io.netty.channel.ChannelOption;
      import io.netty.channel.ChannelPipeline;
      import io.netty.channel.EventLoopGroup;
      import io.netty.channel.nio.NioEventLoopGroup;
      import io.netty.channel.socket.SocketChannel;
      import io.netty.channel.socket.nio.NioServerSocketChannel;
      import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
      import io.netty.handler.codec.LengthFieldPrepender;
      import io.netty.handler.codec.serialization.ClassResolvers;
      import io.netty.handler.codec.serialization.ObjectDecoder;
      import io.netty.handler.codec.serialization.ObjectEncoder;
      
      public class RPCServer {
          private int port;
      
          public RPCServer(int port) {
              this.port = port;
          }
      
          public void start() {
              EventLoopGroup bossGroup = new NioEventLoopGroup();
              EventLoopGroup workerGroup = new NioEventLoopGroup();
      
              try {
                  ServerBootstrap serverBootstrap = 
                          new ServerBootstrap()
                          .group(bossGroup, workerGroup)
                          .channel(NioServerSocketChannel.class).localAddress(port)
                          .childHandler(new ChannelInitializer<SocketChannel>() {
      
                              @Override
                              protected void initChannel(SocketChannel ch) throws Exception {
                                  ChannelPipeline pipeline = ch.pipeline();
                                  pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                                  pipeline.addLast(new LengthFieldPrepender(4));
                                  pipeline.addLast("encoder", new ObjectEncoder());
                                  pipeline.addLast("decoder",
                                          new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));
                                  pipeline.addLast(new InvokerHandler());
                              }
                          })
                          .option(ChannelOption.SO_BACKLOG, 128)
                          .childOption(ChannelOption.SO_KEEPALIVE, true);
                  ChannelFuture future = serverBootstrap.bind(port).sync();
                  System.out.println("Server start listen at " + port);
                  future.channel().closeFuture().sync();
              } catch (Exception e) {
                  bossGroup.shutdownGracefully();
                  workerGroup.shutdownGracefully();
              }
          }
      
          public static void main(String[] args) throws Exception {
              int port;
              if (args.length > 0) {
                  port = Integer.parseInt(args[0]);
              } else {
                  port = 8080;
              }
              new RPCServer(port).start();
          }
      }
      
    5. SeverClass

      package test;
      
      public class SeverClass implements SeverInterface {
      
          @Override
          public String fn(String data) {
              return data;
          }
      
      }
      
    6. SeverInterface

      package test;
      
      public interface SeverInterface {
          String fn(String data);
      }
      

    客户端功能模块编写

    1. 目录结构

    2. App

      package test;
      
      import io.netty.bootstrap.Bootstrap;
      import io.netty.channel.ChannelFuture;
      import io.netty.channel.ChannelInitializer;
      import io.netty.channel.ChannelOption;
      import io.netty.channel.ChannelPipeline;
      import io.netty.channel.EventLoopGroup;
      import io.netty.channel.nio.NioEventLoopGroup;
      import io.netty.channel.socket.SocketChannel;
      import io.netty.channel.socket.nio.NioSocketChannel;
      import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
      import io.netty.handler.codec.LengthFieldPrepender;
      import io.netty.handler.codec.serialization.ClassResolvers;
      import io.netty.handler.codec.serialization.ObjectDecoder;
      import io.netty.handler.codec.serialization.ObjectEncoder;
      
      public class App 
      {
          public static void main(String [] args) throws Throwable{
              
              ClassInfo classInfo = new ClassInfo();
              classInfo.setClassName("test.SeverClass");
              classInfo.setMethodName("fn");
              classInfo.setObjects(new Object[]{"ClientSendData"});
              classInfo.setTypes(new Class[]{String.class});
              
              ResultHandler resultHandler = new ResultHandler();
              EventLoopGroup group = new NioEventLoopGroup();  
              try {  
                  Bootstrap b = new Bootstrap();  
                  b.group(group)  
                      .channel(NioSocketChannel.class)  
                      .option(ChannelOption.TCP_NODELAY, true)  
                      .handler(new ChannelInitializer<SocketChannel>() {  
                          @Override  
                          public void initChannel(SocketChannel ch) throws Exception {  
                              ChannelPipeline pipeline = ch.pipeline();  
                              pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));  
                              pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));  
                              pipeline.addLast("encoder", new ObjectEncoder());    
                              pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));  
                              pipeline.addLast("handler",resultHandler);
                          }  
                      });  
          
                  ChannelFuture future = b.connect("localhost", 8080).sync();  
                  future.channel().writeAndFlush(classInfo).sync();
                  future.channel().closeFuture().sync();  
              } finally {  
                  group.shutdownGracefully();  
              }
      
              System.out.println("调用服务器数据返回回来的数据:" + resultHandler.getResponse());
          }
      }
      
    3. ResultHandler

      package test;
      
      import io.netty.channel.ChannelHandlerContext;
      import io.netty.channel.ChannelInboundHandlerAdapter;
      
      public class ResultHandler extends ChannelInboundHandlerAdapter {
      
          private Object response;
      
          public Object getResponse() {
              return response;
          }
      
          @Override
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
              response = msg;
              System.out.println("调用服务器数据返回回来的数据:" + response);
          }
      
          @Override
          public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
              System.out.println("client exception is general");
          }
      }
      
  • 相关阅读:
    LeetCode 217. 存在重复元素
    LeetCode 48. 旋转图像
    LeetCode 35. 搜索插入位置
    LeetCode 27. 移除元素
    LeetCode 145. 二叉树的后序遍历 (用栈实现后序遍历二叉树的非递归算法)
    LeetCode 328. 奇偶链表
    LeetCode 160. 相交链表 (找出两个链表的公共结点)
    LeetCode 26. 删除排序数组中的重复项
    LeetCode 836. 矩形重叠
    数据库
  • 原文地址:https://www.cnblogs.com/ye-hcj/p/9896362.html
Copyright © 2020-2023  润新知