Easy Netty 系列(三):ChannelHandler详解

Handler 是处理器,那它处理什么呢?网络中有什么它就做那些处理,常见的有连接的建立,响应读写事件,网络中数据的处理如编码、解码等,这些都输处理器做的,Netty 中的处理器是ChannelHandler接口,所有的处理器都是这个接口的实现。

首先说下 Netty 处理器的定位,它是 Netty 架构网络处理业务逻辑的解耦,处理器代表了与用户相关的业务逻辑,如数据读取后端计算和发送,而网络连接管理、线程控制、网络事件监听处理都由 Netty 接管,使我们可以更加专注业务逻辑,站在开发的角度使用 Netty 开发接触最多的就是ChannelHandler

处理器有许多种类,通过以下分类你可以先在脑海中建立一个简单的概念。

处理器分类

  • 入站处理器:处理 read 事件的数据,通常是解码操作
  • 出站处理器:处理 write 事件的数据,通常是编码操作
  • 编解码器:一种专用的数据转换器,例如字节转换为字符串,称之为“解码器”,反之把字符串转换为“字节”称之为“编码器”
  • 转换器:复合处理器,把一种数据转换为另一种数据,例如 HTTP1 转换为 HTTP2

ChannelHandler 层次结构

Handler结构.png

常用类使用

最常使用的是 ChannelInboundHandlerAdapter、ChannelDuplexHandler、ChannelOutboundHandlerAdapter 的实现类,这些类定义了作为不同的类型的方法,例如 InboundHandler 与 OutBoundHandler 定义的方法就有很大的差别。

以入站为代表的方法有 ByteToMessageDecoder、SimpleChannelInboundHandler。

例如ByteToMessageDecoder使用时重写decode方法即可,编码器重写 encode

      public class SquareDecoder extends {@link ByteToMessageDecoder} {
          @Override
          public void decode(ChannelHandlerContext ctx,  ByteBuf in, List<Object> out)
                  throws  Exception {
              out.add(in.readBytes(in.readableBytes()));
          }
      }

SimpleChannelInboundHandler<T> 使用时重写 channelRead0 方法即可,Adapter 里已经帮我们做好了类型转换。

       public class StringHandler extends SimpleChannelInboundHandler<String> {
            @Override
           protected void channelRead0(ChannelHandlerContext ctx, String message)
                   throws Exception {
               System.out.println(message);
           }
       }

ChannelDuplexHandler 的继承类实现多是进行数据转换,例如:ByteToMessageCodec 将入站的 byte 数据转化为对象,出站时将对象转换为 byte,类似的还有 MessageToMessageCodec,实现两个对象间的转化。

ChannelHandler 的几个注意点

1、执行顺序。按照被添加的顺序执行。

2、共享 Handler 与非共享 Handler。共享的 handler 会帮定到多个 Channel,当 Channel 并行执行时可能存在线程安全问题;非共享 handler 绑定时就会创建一个,Channel 独享不存在线程安全问题。

3、Handler 的 read 会执行多次。当 Channel 中的数据未处理完,上一个 handler 会多次触发下个 handler 的 read 事件。

(end)