基于Netty自己去实现一个MessageToMessageEncoder<T>进行自定义的编码的时候。 编码好的ByteBuf如何输出结果?
extends MessageToMessageEncoder<T>的时候encode() 编码结果如果输出 ?
正确做法是out.add(sendBuf);
参考例子https://github.com/flylib/frpc
部分代码片段如下
package org.flylib.frpc.protocal.encode;
public final class NettyMessageEncoder extends MessageToMessageEncoder<NettyMessage> {
MarshallingEncoder marshallingEncoder;
public NettyMessageEncoder() throws IOException {
this.marshallingEncoder = new MarshallingEncoder();
}
@Override
protected void encode(ChannelHandlerContext ctx, NettyMessage msg, List<Object> out) throws Exception {
if (msg == null || msg.getHeader() == null) {
throw new Exception("The encode message is null");
}
ByteBuf sendBuf = Unpooled.buffer();
sendBuf.writeInt(msg.getHeader().getCrcCode());
sendBuf.writeInt(msg.getHeader().getLength());
sendBuf.writeLong(msg.getHeader().getSessionID());
sendBuf.writeByte(msg.getHeader().getType());
sendBuf.writeByte(msg.getHeader().getPriority());
sendBuf.writeInt(msg.getHeader().getAttachment().size());
String key = null;
byte[] keyArray = null;
Object value = null;
for (Map.Entry<String, Object> param : msg.getHeader().getAttachment().entrySet()) {
key = param.getKey();
keyArray = key.getBytes("UTF-8");
sendBuf.writeInt(keyArray.length);
sendBuf.writeBytes(keyArray);
value = param.getValue();
marshallingEncoder.encode(value, sendBuf);
}
key = null;
keyArray = null;
value = null;
if (msg.getBody() != null) {
marshallingEncoder.encode(msg.getBody(), sendBuf);
} else {
sendBuf.writeInt(0);
sendBuf.setInt(4, sendBuf.readableBytes());
}
out.add(sendBuf);
}
}
最后一句是out.add(sendBuf);
out是List<Object>类型的 .里面执行完后, 只有一个元素,就是编码好了的ByteBuf ---- sendBuf
为什么是这么做的呢?
可以看下下面的一些查找方法。
就是去查看super类里这个endoe() 的参数out后面被如何使用了。
io.netty.handler.codec.MessageToMessageEncoder<I> 这个抽象类里的encode方法
protected abstract void encode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception;
右键--Open hierarchy
查看有哪些地方调用它
打开第一处。 发现是
@Override
protected void encode(
ChannelHandlerContext ctx, AddressedEnvelope<M, InetSocketAddress> msg, List<Object> out) throws Exception {
assert out.isEmpty();
encoder.encode(ctx, msg.content(), out);
if (out.size() != 1) {
throw new EncoderException(
StringUtil.simpleClassName(encoder) + " must produce only one message.");
}
Object content = out.get(0);
if (content instanceof ByteBuf) {
// Replace the ByteBuf with a DatagramPacket.
out.set(0, new DatagramPacket((ByteBuf) content, msg.recipient(), msg.sender()));
} else {
throw new EncoderException(
StringUtil.simpleClassName(encoder) + " must produce only ByteBuf.");
}
}
它会判断是否是ByteBuf类型的,如果不是会报错的。 所以,我上面的猜测是正确的。