美文网首页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