netty入门——组件2-Handler

Handler & Pipeline

 📢 常用Handler使用

ch.pipeline().addLast(new LoggingHandler(LogLevel.*DEBUG*)); //打印日志输出

ch.pipeline().addLast(new StringEncoder()); //把写入的内容转为string

ch.pipeline().addLast(new SimpleChannelInboundHandler<LoginRequestMessage>() {} //只接收特定消息的handler

ch.pipeline().addLast(newLengthFieldBasedFrameDecoder(1024,0,0,0,0)) //动态解码器handler

ch.pipeline().addLast(new IdleStateHandler(5,0,0)); //用来判断是不是 读空闲时间过长 或 写空闲时间过长 或者读写空闲时间过长时触发

ch.pipeline().addLast(new ChannelDuplexHandler(){} //可以同时作为入站和出战处理器

//                    ChannelDuplexHandler 可以同时作为入站或者出战处理器
                    ch.pipeline().addLast(new ChannelDuplexHandler(){
//                        用来触发特殊事件,自定义事件等
                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            IdleStateEvent event = (IdleStateEvent) evt;
                            if (event.state() == IdleState.READER_IDLE){
log.debug("已经五秒没有读到数据了!");
                            }
                            super.userEventTriggered(ctx, evt);
                        }
                    });

ChannelHandler用来处理Channel上的各种事件,分为入栈,出栈两种。所有ChannelHanndler被连成一串,就是Pipeline

  • 入栈处理器通常是ChannelInboundHandlerAdapter的子类,主要用来读取客户端数据,写回结果
  • 出栈处理器通常是ChannelOutboundHandlerAdapter的子类,主要对写回结果进行加工

打个比喻,每个Channel是一个产品的加工车间,Pipeline是车间的流水线,ChannelHandler就是流水线上的各道工序,而后面要讲的ByteBuf是原材料,经过很多工序的加工;先经过一道道工序入站工序,再经过一道道出战工序最终变成产品

Pipeline执行顺序

  • h1->h2->h3 入栈顺序是从前往后执行,

  • ->h4->h5 出栈顺序是从后面往前执行,先执行h5再执行h4

    • 需要执行了writeAndFlush() 关闭方法才会执行出站的Handler
  • super.channelRead(ctx, name) /``ctx.fireChannelRead(msg);

    • 两个方法都是用于调用下一个Handler,把值传递过去,下一个Handler的msg就是这个Handler处理过了的参数
    • 两者必须调用一个,否则调用链就会断掉

public static void main(String[] args) {
        new ServerBootstrap()
                .group(new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
//                        1、通过channel拿到pipeline
                        ChannelPipeline pipeline = ch.pipeline();
//                        2、添加处理器 head -> h1->h2->h3 ->h4->h5 ->tail
                        pipeline.addLast("h1",new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                log.debug("1");
                                ByteBuf buf = (ByteBuf) msg;
                                String name = buf.toString(Charset.defaultCharset());
                                super.channelRead(ctx, name);  //调用下一个Handler,把值传递过去,下一个Handler的msg就是这个Handler处理过了的参数
//                                ctx.fireChannelRead(msg);  或者调用该实现,两则必须调用一个,反正调用链会断
                            }
                        });
                        pipeline.addLast("h2",new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                log.debug("2");
                                Student student = new Student((String) msg);
                                super.channelRead(ctx, student);
                            }
                        });
                        pipeline.addLast("h3",new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                log.debug("3");
                                log.debug("对象====》{},{}",msg,msg.getClass());
                                super.channelRead(ctx, msg);
//                                把写入的字符串转为Bytebuffer字节数组
//                                ch.writeAndFlush(ctx.alloc().buffer().writeBytes("server...".getBytes()));
                                ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("server...".getBytes()));
                            }
                        });

                        pipeline.addLast("h4",new ChannelOutboundHandlerAdapter(){
                            @Override
                            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                log.debug("出站4");
                                super.write(ctx, msg, promise);
                            }
                        });
                        pipeline.addLast("h5",new ChannelOutboundHandlerAdapter(){
                            @Override
                            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                log.debug("出站5");
                                super.write(ctx, msg, promise);
                            }
                        });
                    }
                }).bind(8080);
    }
    @Data
    @AllArgsConstructor
    static class Student{
        private String name;
    }

Handler测试工具类:EmbeddedChannel

public static void main(String[] args) {
        ChannelInboundHandlerAdapter h1 = new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.debug("入站1");
                super.channelRead(ctx, msg);
            }
        };
        ChannelInboundHandlerAdapter h2 = new ChannelInboundHandlerAdapter() {
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                log.debug("入站2");
                super.channelRead(ctx, msg);
            }
        };
        ChannelOutboundHandlerAdapter h4 = new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.debug("出站4");
                super.write(ctx, msg, promise);
            }
        };
        ChannelOutboundHandlerAdapter h5 = new ChannelOutboundHandlerAdapter() {
            @Override
            public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                log.debug("出站5");
                super.write(ctx, msg, promise);
            }
        };
        EmbeddedChannel channel = new EmbeddedChannel(h1, h2, h4,h5);
//         模拟入栈操作
        channel.writeInbound(ByteBufAllocator.DEFAULT.buffer().writeBytes("hello".getBytes()));
//        模拟出站操作
        channel.writeOutbound(ByteBufAllocator.DEFAULT.buffer().writeBytes("".getBytes()));
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值