在入站过程中,需要将Bytebuf二进制类型解码成java POJO对象,这个解码过程通过netty中的Decoder(解码器完成)
在出站过程中,业务处理后的结果需要从某个java POJO对象编码为最终的ByteBuf二进制数据,然后通过java底层通道发送到对端,需要通过netty中的Encoder(编码器)去完成数据编码工作。

1、常见解码器

ChannelInboundHandler.png

Netty中主要提供了抽象基类ByteToMessageDecoderMessageToMessageDecoder
ByteToMessageDecoder: 用于将字节转为消息,需要检查缓冲区是否有足够的字节
MessageToMessageDecoder: 用于从一种消息解码为另外一种消息

(1)ByteToMessageDecoder

ByteToMessageDecoder是一个非常重要的解码器基类,实现了家么处理的基础逻辑和流程,完成从ByteBuf到java POJO对象的解码功能。

ByteToMessageDecoder解码方法为decode()方法,需要实现decode()方法将ByteBuf转化为POJO对象,放入List列表中,传入下一个处理器

  1. public class TestDecoder {
  2. public static void main(String[] args) {
  3. new ServerBootstrap()
  4. .group(new NioEventLoopGroup(),new NioEventLoopGroup(2))
  5. .channel(NioServerSocketChannel.class)
  6. .childHandler(new ChannelInitializer<NioSocketChannel>() {
  7. @Override
  8. protected void initChannel(NioSocketChannel ch) throws Exception {
  9. ch.pipeline().addLast("h1", new ByteToMessageDecoder() {
  10. @Override
  11. protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
  12. log.info("出站处理器h1");
  13. list.add(Msg.builder().key("netty").value(byteBuf.toString(Charset.defaultCharset())).build() );
  14. list.add(Msg.builder().key("netty").value(byteBuf.toString(Charset.defaultCharset())).build() );
  15. byteBuf.release();
  16. }
  17. }).addLast("h2",new ChannelInboundHandlerAdapter(){
  18. @Override
  19. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  20. log.info("入站处理器h2");
  21. log.info("数据:" + JSON.toJSON(msg));
  22. super.channelRead(ctx, msg);
  23. }
  24. }).addLast("h3",new ChannelInboundHandlerAdapter(){
  25. @Override
  26. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  27. log.info("入站处理器h3");
  28. super.channelRead(ctx, msg);
  29. }
  30. });
  31. }
  32. })
  33. .bind(8989);
  34. }
  35. }

(2)ReplayingDecoder

实际开发中不建议继承该类:

  • 不是所有的ByteBuf操作都被ReplayingDecoderBuffer装饰器类支持,可能有些ByteBuf方法再ReplayingDecoder的decode()方法中会抛出ReplayError异常
  • 在数据解码逻辑复杂的应用场景下,ReplayingDecoder在解码速度上相对较差

注: ReplayingDecoder及其子类都需要保存状态信息,都不适合在不同的通道之间进行简单的共享

ReplayingDecoder解码器是ByteToMessageDecoder的子类,其主要作用为:

  • 在读取ByteBuf缓冲区数据之前,需要检查缓冲区是否有足够的字节
  • 若ByteBuf中有足够的字节,则正常读取,反之,则会停止解码


(3)LineBasedFrameDecoder

行分割数据包解码器,每个ByteBuf数据包使用换行符或者回车换行符作为边界分隔符

(3)DelimiterBasedDecoder

自定义分隔符数据包解码器

(4)LengthFieldBasedFrameDecoder

自定义长度数据包解码器

(5)MessageToMessageDecoder

POJO对象转POJO对象的解码器

2、常见编码器

image.png

(1)MessageToByteEncoder

(2)MessageToMessageEncoder

3、解码器编码器结合

具有相同配套逻辑的编码器和解码器放在同一个类中

(1)ByteToMessageCodec

继承ByteToMessageCodec 就相当于继承了 ByteToMessageDecoder 和 MessageToByteEncoder

(2)CombinedChannelDuplexHandler

通过组合的方式将编码器和解码器结合起来

  1. public class MyHandler extends CombinedChannelDuplexHandler<ByteToMessageDecoder, MessageToByteEncoder> {
  2. }