MessageToByteEncoder是一個抽象編碼器,子類可重新encode方法把對象編碼爲ByteBuf輸出。
源碼分析
package io.netty.handler.codec;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandler;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.internal.TypeParameterMatcher;
public abstract class MessageToByteEncoder<I> extends ChannelOutboundHandlerAdapter {
private final TypeParameterMatcher matcher;
private final boolean preferDirect;
protected MessageToByteEncoder() {
this(true);
}
//匹配msg的數據類型是否爲I,也就是子類定義的泛型
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 {
//msg是I這種類型就調用編碼邏輯,否則向下傳遞
if (acceptOutboundMessage(msg)) {
@SuppressWarnings("unchecked")
I cast = (I) msg; //類型轉換
//分配ByteBuf,默認堆外類型
buf = allocateBuffer(ctx, cast, preferDirect);
try {
//子類實現編碼邏輯
encode(ctx, cast, buf);
} finally {
//釋放msg
ReferenceCountUtil.release(cast);
}
//如果buf可讀,則寫入ctx,實際就是交給netty調用底層socket輸出
if (buf.isReadable()) {
ctx.write(buf, promise);
} else {
//否則釋放buf
buf.release();
//向下傳遞空的buf對象
ctx.write(Unpooled.EMPTY_BUFFER, promise);
}
buf = null;
} else {
//如果不是I類型,則次編碼器不做任何處理,直接傳遞msg對象給下一個編碼器
ctx.write(msg, promise);
}
} catch (EncoderException e) {
throw e;
} catch (Throwable e) {
throw new EncoderException(e);
} finally {
if (buf != null) {
buf.release();
}
}
}
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, @SuppressWarnings("unused") I msg,
boolean preferDirect) throws Exception {
if (preferDirect) {
return ctx.alloc().ioBuffer();
} else {
return ctx.alloc().heapBuffer();
}
}
//需要子類實現,根據msg的內容,把數據寫入ByteBuf中
protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;
//默認使用堆外內存
protected boolean isPreferDirect() {
return preferDirect;
}
}
例子,一個Integer類型的編碼,負責把一個Integer寫入到ByteBuf當中。
public class IntegerEncoder extends MessageToByteEncoder<Integer> {
@Override
public void encode(ChannelHandlerContext ctx, Integer msg, ByteBuf out)
throws Exception {
out.writeInt(msg);
}
}