Netty编码器和解码器

本文围绕Netty的解码器和编码器展开。介绍了解码器原理,如ByteToMessageDecoder等,还提及Netty内置的多种解码器。阐述了编码器原理,包括MessageToByteEncoder等。最后说明了解码器和编码器的结合方式,如ByteToMessageCodec编解码器和CombinedChannelDuplexHandler组合器。


Netty从底层Java通道读到ByteBuf二进制数据,传入Netty通道的流水线,随后开始入站处理。在入站处理过程中,需要将ByteBuf二进制类型解码成Java POJO对象。这个解码过程可以通过Netty的Decoder解码器去完成。在出站处理过程中,业务处理后的结果需要从某个Java POJO对象编码为最终的ByteBuf二进制数据,然后通过底层 Java通道发送到对端。在编码过程中,需要用到Netty的Encoder编码器去完成数据的编码工作。

一、Decoder原理与实践

Netty的解码器Decoder本质上是一个InBound入站处理器,它将上一站InBound入站处理器传过来的输入数据进行数据的解码或者格式转换,然后输出到下一站InBound入站处理器。

一个标准的解码器将输入类型为ByteBuf缓冲区的数据进行解码,输出一个一个的Java POJO对象。Netty内置了这个解码器,叫做ByteToMessageDecoder。

Netty中的解码器都是Inbound入站处理器类型,都直接或间接地实现了ChannelInboundHandler接口。

1、ByteToMessageDecoder解码器

ByteToMessageDecoder是一个非常重要的解码器基类,它是一个抽象类,实现了解码的基础逻辑和流程。ByteToMessageDecoder继承自ChannelInboundHandlerAdapter适配器,是一个入站处理器,实现了从ByteBuf到Java POJO对象的解码功能。

ByteToMessageDecoder解码的流程大致是先将上一站传过来的输入到ByteBuf中的数据进行解码,解码出一个List对象列表,然后迭代这个列表,逐个将Java POJO对象传入下一站Inbound入站处理器。

ByteToMessageDecoder的解码方法名为decode,在该类中只是提供了一个抽象方法,具体的解码过程,即如何将ByteBuf数据变成Object数据需要子类去完成。ByteToMessageDecoder作为解码器的父类,只是提供了一个流程性质的框架,它仅仅将子类的decode方法解码后的Object结果放入自己内部的结果列表List中(这个过程也是子类的decode方法完成的),最终父类会负责将列表中的元素一个一个传递给下一个站。

如果要实现一个自己的解码器,首先继承ByteToMessageDecoder抽象类,然后实现其积累的decode抽象方法,将解码的逻辑写入此方法。总体来说,流程大致如下:

  1. 继承ByteToMessageDecoder抽象类
  2. 实现基类的decode抽象方法,将ByteBuf到POJO解码的逻辑写入此方法。将ByteBuf二进制数据解码成一个一个的Java POJO对象
  3. 在子类的decode方法中奖解码后的Java POJO对象放入decode的List市财政,这个实惨是父类传入的,也就是父类的结果收集列表
  4. 父类将List中的结果一个个分开地传递到下一站的Inbound入站处理器

ByteToMessageDecoder传递给下一站的是解码之后的Java POJO对象(会遍历list中的所有元素,将其作为参数调用fireChannelRead方法),不是ByteBuf缓冲区。那么ByteBuf缓冲区由谁负责进行引用计数和释放管理的呢?

起始积累的ByteToMessageDecoder负责解码器的ByteBuf缓冲区的释放工作,它会自动调用release方法将之前的ByteBuf缓冲区的引用数减1,这个工作是自动完成的。

如果这个ByteBuf在后面还需要用到,那么可以在decode方法中调用一次retain方法来增加一次引用计数。

2、自定义整数解码器

1)常规方式

public class Byte2IntegerDecoder extends ByteToMessageDecoder {
   
   
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
   
   
        while (byteBuf.readableBytes() >= 4) {
   
   
            int i = byteBuf.readInt();
            System.out.println("解码出一个整数:" + i);
            list.add(i);
        }
    }
}

public class IntegerProcessHandler extends ChannelInboundHandlerAdapter {
   
   

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
   
   
        Integer integer = (Integer) msg;
        System.out.println("打印出一个整数:" + integer);
        super.channelRead(ctx, msg);
    }
}

public class Byte2IntegerDecoderTester {
   
   

    public static void main(String[] args) {
   
   
        EmbeddedChannel embeddedChannel = new EmbeddedChannel(new ChannelInitializer<EmbeddedChannel>() {
   
   
            @Override
            protected void initChannel(EmbeddedChannel ch) throws Exception {
   
   
                ch.pipeline().addLast
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

得过且过的勇者y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值