14-netty-codec-base64
27. netty系列之:netty中的核心编码器base64
简介
我们知道数据在netty中传输是以ByteBuf的形式进行的,可以说ByteBuf是netty的数据传输基础。但是对于现代的应用程序来说,通常我们需要用到其他的数据结构或者类型。
为了方便我们在程序中的编写,一种方式就是在将数据传入到netty中的时候由程序员自身将数据格式进行转换,然后再调用netty的系统方法。另外一种方式就是定义一些codec,由netty的内在编码机制将程序中用到的数据格式和ByteBuf进行自动转换。
很明显,使用codec的方式更加简捷,也更加符合程序的开发规则。
为了方便程序的开发,netty本身在内部定义了一些核心的codec插件,我们在需要的时候直接选用即可。
本文将会讲解netty内部实现codec的方式和一个最核心的编码器base64。
netty codec的实现逻辑
所有的netty codec的目的就是在数据传输过程中进行数据类型的转换,换句话说就是对数据进行处理。我们知道netty中有两个对数据进行handler的类,分别是ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter,他们分别对应channel中的inbound消息和outbound消息进行处理。
所以很自然的,我们的codec逻辑只需要在这两个地方添加即可。
netty为我们提供了两个HandlerAdapter类的继承类,分别是MessageToMessageDecoder和MessageToMessageEncoder:
从名字就可以看出来这两个类分别使用来编码和解码用的,所以我们的codec只需要分别实现这两个类即可。
以下是一个StringToIntegerDecoder和IntegerToStringEncoder的例子:
最简单的实现就是分别重构这两个类的decode和encode方法。
netty中Base64的实现
我们知道JDK中已经有了Base64实现的工具类叫做java.util.Base64。但是在netty中又使用了一个新的实现类同样叫做Base64,它的全称是io.netty.handler.codec.base64.Base64。
这个Base64类中用到了一个Base64Dialect类,也就是netty中Base64支持的Base64编码方式。Base64Dialect中提供了下面的几种类型:
其中STANDARD对应的是RFC3548也是JDK中的标准Base64,URL_SAFE对应的是RFC3548中的base64url版本,对应的JDK中的getUrlEncode。
最后一个是ORDERED,代表的是RFC1940,这个编码实现在JDK中是没有的。
为什么JDK中已经有了Base64的工具类,netty中还需要自己创建一个新的类呢?
我们可以考虑一下在netty中Base64用到的场景,通常来说我们是在handler中添加自定义编码,而这些handler主要是针对于数据流进行处理。
JDK中自带的Base64实现在定长的数据上使用还是没问题的,但是如果运用于数据流的处理话,效率就会比较低。所以Netty才需要为base64在流数据的情况下重新实现一个Base64类。
netty中的实现方式使用的是Robert Harder's Public Domain Base64 Encoder/Decoder。这里就不多讲这个算法的实现逻辑了。感兴趣的朋友可以自行探索。
Base64提供了将ByteBuf进行base64编码和解码的方法,我们选择参数最长的方法来观察,如下所示:
对于encode方法来说,需要下面几个参数:
ByteBuf类型的src,这是我们需要进行编码的源。
int类型的off和len,表示的是ByteBuf中要编码数据的位置。
boolean类型的breakLines,表示是否添加换行符。
Base64Dialect类型的dialect,表示选择的base64编码类型。
ByteBufAllocator的allocator,表示返回的ByteBuf的生成方式。
同样的Decode方法,需要下面的几个参数:
ByteBuf类型的src,这是我们需要进行解码的源。
int类型的off和len,表示的是ByteBuf中要解码数据的位置。
Base64Dialect类型的dialect,表示选择的base64编码类型。
ByteBufAllocator的allocator,表示返回的ByteBuf的生成方式。
netty中的base64编码和解码器
刚刚我们介绍了netty中提供的新的Base64工具类,这个工具类提供了将ByteBuf中数据进行编码和解码的方法。接下来我们看一下netty是如何使用这个工具类实现netty中的base64编码和解码器。
netty中提供了对Base64的编码和解码器,分别是Base64Encoder和Base64Decoder, 先来看下Base64编码解码器的基本使用:
用起来很简单,只需要把Base64Decoder和Base64Encoder添加到pipeline中即可。
有时候Base64Decoder需要和DelimiterBasedFrameDecoder一起使用,尤其是在TCP/IP协议中,因为我们需要根据特定的Delimiters来判断ByteBuf应该被分割为几个frames。这样才能保证数据的有效性。
Base64Encoder
首先来看base64的编码器,Base64Encoder的实现比较简单,首先来看下Base64Encoder的定义:
Base64Encoder继承自MessageToMessageEncoder,它传入的泛型ByteBuf,表示是将ByteBuf编码为ByteBuf,虽然外部的ByteBuf类型没有变化,但是ByteBuf中的数据已经被编码成为Base64了。
接下来是Base64Encoder的构造函数:
Base64Encoder可以接受两个参数,分别是是否有换行符的breakLines和base64编码方式的Base64Dialect。
它的encode方法也很简单:
直接使用的是我们上面讲到的Base64工具类的encode方法,然后把返回值添加到out对象中。
Base64Decoder
Base64Decoder用来将ByteBuf中的base64编码的内容解码成为原始内容,先来看下Base64Decoder的定义:
Base64Decoder继承了MessageToMessageDecoder,传入的泛型是ByteBuf。
先看下Base64Decoder的构造函数:
Base64Decoder的构造函数很简单,和Base64Encoder相比它只需要一个参数就是Base64Dialect类型的dialect,表示的是选择的base64解码的方式。
接下来就是它的解码方法:
解码方法也是调用Base64工具类的decode方法,然后将其添加到返回的out list中去。
总结
本章介绍了netty中的核心编码器Base64,它负责将ByteBuf中的消息编码为base64格式,同时提供了对应的解码器,大家可以在需要的时候进行使用。
最后更新于