谈谈SimpleChannelInboundHandler和使用中遇到的坑

在netty4.x中,handler作为netty中一个重要的组件,它通常被用来支持各种协议和处理数据的方式,处理各种事件。而ChannelInboundHandler是比较常用的handler,主要用来处理接收数据的一些事件,我们日常接收消息的处理都是通过扩展这个接口来自定义解析数据的。

ChannelInboundHandlerAdapter是ChannelInboundHandler它的一个简单实现,它的各种实现都只是将操作hannelPipeline中的下一个ChannelHandler中让链中的下一个ChannelHandler去处理。

SimpleChannelInboundHandler是一个支持泛型的消息处理的handler,继承自ChannelInboundHandlerAdapter,主要逻辑是重写了消息处理的方法channelRead,并新增加了channelRead0抽象方法提供给用户实现解码后的自定义处理代码如下:

 @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        boolean release = true;
        try {
            if (acceptInboundMessage(msg)) {
                @SuppressWarnings("unchecked")
                I imsg = (I) msg;
                channelRead0(ctx, imsg);
            } else {
                release = false;
                ctx.fireChannelRead(msg);
            }
        } finally {
            if (autoRelease && release) {
                ReferenceCountUtil.release(msg);
            }
        }
    }

可以看到这个方法逻辑很简单,它会把默认当成你泛型的类型(I)来用,并调用自定义的逻辑channelRead0方法实现数据的处理,这里很坑的一点就是,你要在执行这个ChannelHandler之前,就要处理好msg的数据,比如如果实例化的时候指定泛型是String类型,可能在这个handler前面你就需要添加StringDecode解码,如果上面解码得到的不是String或者解码失败,这个方法则不会执行,关键它还不会报错,由于一些教程的例子里就用了这个类来接收处理String打印数据,我们把代码拷过来一运行就可能没有任何打印也没报错,然后就不知所措。这个时候就要去检查客户端编码和服务端的解码过程有没有问题了。

另外,网上还有一些教程说这个类处理完消息后会自动释放掉msg,其实这也是默认情况下会这样,看源码就知道,我们实例化这个类的时候指定autoRelease等于false,那么msg处理完成之后,就不会被释放掉,这时候调用提供的fire*方法传递给ChannelPipeline中的下一个ChannelHandler去走其他的逻辑是可以的,不过这个msg最终还是要自己释放掉哦.

 

 

你可能感兴趣的:(netty)