美文网首页Netty源码分析系列
Netty源码分析系列--12. 自定义编解码器

Netty源码分析系列--12. 自定义编解码器

作者: ted005 | 来源:发表于2018-11-15 21:57 被阅读38次

    编解码器基类

    入站:

    • ByteToMessageDecoder:将Bytebuf转换为另一种数据类型
    /**
     * in:输入的Bytebuf
     * out:解码后的数据需要添加到out集合中,传递给下一个处理器
    /
    protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;
    
    • MessageToMessageDecoder

    出站:

    • MessageToMessageEncoder
    • MessageToByteEncoder

    自定义编解码器

    这里的自定义解码器MyLongDecoder完成从BytebufLong类型的解码;编码器MyLongEncoder反之。

    解码器Decoder

    继承ByteToMessageDecoder,重写decode方法

    
    public class MyLongDecoder extends ByteToMessageDecoder {
        @Override
        protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    
            //长度够8个字节,才能读取为一个long类型
            if (in.readableBytes() >= 8) {
                out.add(in.readLong());
            }
        }
    }
    

    编码器Encoder

    继承MessageToByteEncoder,重写encode方法。注意这里的泛型类型时Long

    public class MyLongEncoder extends MessageToByteEncoder<Long> {
        @Override
        protected void encode(ChannelHandlerContext ctx, Long msg, ByteBuf out) throws Exception {
            out.writeLong(msg);
        }
    }
    

    发送非Long类型数据

    上面的编解码器发送的数据类型是Long,如果去掉数字后面的L,即数据类型变为整型Int,会发现数据没有发送出去。

    查看父类MessageToByteEncoderwrite方法,其内部调用acceptOutboundMessage方法,使用一个matcher来做类型匹配判断。

    public boolean acceptOutboundMessage(Object msg) throws Exception {
        return matcher.match(msg);
    }
    
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ByteBuf buf = null;
        try {
            
            // 类型判断
            if (acceptOutboundMessage(msg)) {
                @SuppressWarnings("unchecked")
                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();
            }
        }
    }
    

    matcher的类型是抽象类TypeParameterMatcher,其子类RelectiveMatcher:判断是否是泛型类型的实例

    private static final class ReflectiveMatcher extends TypeParameterMatcher {
        private final Class<?> type;
    
        ReflectiveMatcher(Class<?> type) {
            this.type = type;
        }
    
        @Override
        public boolean match(Object msg) {
            //等价于 instanceOf 运算符
            return type.isInstance(msg);
        }
    }
    

    因此非Long类型均无法发送出去,除了两种类型ByteBufFileRegion

    相关文章

      网友评论

        本文标题:Netty源码分析系列--12. 自定义编解码器

        本文链接:https://www.haomeiwen.com/subject/auvufqtx.html