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抽象方法,将解码的逻辑写入此方法。总体来说,流程大致如下:
- 继承ByteToMessageDecoder抽象类
- 实现基类的decode抽象方法,将ByteBuf到POJO解码的逻辑写入此方法。将ByteBuf二进制数据解码成一个一个的Java POJO对象
- 在子类的decode方法中奖解码后的Java POJO对象放入decode的List市财政,这个实惨是父类传入的,也就是父类的结果收集列表
- 父类将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

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

被折叠的 条评论
为什么被折叠?



