Netty源码解析9-ChannelHandler实例之MessageToByteEncoder

请戳GitHub原文: github.com/wangzhiwubi…git

更多文章关注:多线程/集合/分布式/Netty/NIO/RPCgithub

MessageToByteEncoder框架可见用户使用POJO对象编码为字节数据存储到ByteBuf。用户只需定义本身的编码方法encode()便可。 首先看类签名:面试

public abstract class MessageToByteEncoder<I> extends 
                                ChannelOutboundHandlerAdapter
复制代码

可知该类只处理出站事件,切确的说是write事件。 该类有两个成员变量,preferDirect表示是否使用内核的DirectedByteBuf,默认为true。TypeParameterMatcher用于检测泛型参数是不是期待的类型,好比说,若是须要编码String类的POJO对象,Matcher会确保write()传入的参数Object的实际切确类型为String。 直接分析write()的处理:promise

public void write(ChannelHandlerContext ctx, Object msg, 
                          ChannelPromise promise) throws Exception {
        ByteBuf buf = null;
        try {
            if (acceptOutboundMessage(msg)) {
                I cast = (I) msg;
                // 分配一个输出缓冲区
                buf = allocateBuffer(ctx, cast, preferDirect);
                try {
                    encode(ctx, cast, buf); // 用户定义的编码方法
                } finally {
                    ReferenceCountUtil.release(cast);
                }

                if (buf.isReadable()) {
                    ctx.write(buf, promise); // 确实写入了数据
                } else {
                    // 没有须要写的数据,也有多是用户编码错误
                    buf.release();  
                    ctx.write(Unpooled.EMPTY_BUFFER, promise);
                }
                buf = null;
            } else {
                ctx.write(msg, promise);
            }
        } catch (EncoderException e) {
            throw e;
        } catch (Throwable e) {
            throw new EncoderException(e);
        } finally {
            if (buf != null) {
                buf.release();
            }
        }
    }
复制代码

编码框架简单明了,再列出allocateBuffer()方法的代码:缓存

protected ByteBuf allocateBuffer(ChannelHandlerContext ctx,  I msg,
                               boolean preferDirect) throws Exception {
        if (preferDirect) {
            return ctx.alloc().ioBuffer();  // 内核直接缓存
        } else {
            return ctx.alloc().heapBuffer(); // JAVA队缓存
        }
    }
复制代码

总的来讲,编码的复杂度大大小于解码的复杂度,这是由于编码不需考虑TCP粘包。编解码的处理还有一个经常使用的类MessageToMessageCodec用于POJO对象之间的转换。若是有兴趣,可下载源码查看。至此,编解码框架已分析完毕。bash

请戳GitHub原文: https://github.com/wangzhiwubigdata/God-Of-BigData

                   关注公众号,内推,面试,资源下载,关注更多大数据技术~
                   大数据成神之路~预计更新500+篇文章,已经更新60+篇~ 复制代码
相关文章
相关标签/搜索