编解码器基类
入站:
-
ByteToMessageDecoder
:将Bytebuf
转换为另一种数据类型
/**
* in:输入的Bytebuf
* out:解码后的数据需要添加到out集合中,传递给下一个处理器
/
protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;
MessageToMessageDecoder
出站:
MessageToMessageEncoder
MessageToByteEncoder
自定义编解码器
这里的自定义解码器MyLongDecoder
完成从Bytebuf
到Long
类型的解码;编码器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
,会发现数据没有发送出去。
查看父类MessageToByteEncoder
的write
方法,其内部调用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
类型均无法发送出去,除了两种类型ByteBuf
和FileRegion
。
网友评论