解码器
将字节解码为消息 - ByteToMessageDecoder和ReplayingDecoder
将一种消息类型转为另一种 - MessageToMessageDecoder
netty中的解码器继承了ChannelInboundHandlerAdapter,提供了为Pipeline中的下一个ChannelInBoundHandler转换入站数据的作用
ByteToMessageDecoder
实现从ByteBuf中读取Int并传递到下一个ChannleHandler中
public class ToIntegerDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
if(byteBuf.isReadable()) {
list.add(byteBuf.readInt());
}
}
}
ReplayingDecoder
该类拓展了ByteToMessageDecoder,不必调用readableBytes方法,通过一个自定义的ByteBuf实现-ReplayingDecoderByteBuf,包装传入的ByteBuf实现了这一点,其将在内部执行时候调用
public int readInt() {
this.checkReadableBytes(4);
return this.buffer.readInt();
}
实现一个IntToStringDecoder
public class ToIntegerDecoder2 extends ReplayingDecoder<Void> {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
list.add(byteBuf.readInt());
}
}
ReplayingDecoderByteBuf并不支持所有的ByteBuf操作,如果调用了一个不被支持的方法,会抛出UnsupportOperationException,并且该类执行稍慢于ByteToMessageDecoder
MessageToMessageDecoder
实现了两种不同消息格式之间的互转,实现一个IntegerToStringMessageDecoder
public class IntegerToStringMessageDecoder extends MessageToMessageDecoder<Integer> {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, Integer integer, List<Object> list) throws Exception {
list.add(String.valueOf(integer));
}
}
TooLongFrameException
netty是一个异步框架,需要在字节可以解码之前缓存他们,但是不能让解码器大量缓冲数据以至于耗尽内存,neety提供了TooLongFrameException类,将由解码器在帧超出指定的限制大小时抛出
public class SafeByteToMessageDecoder extends ByteToMessageDecoder {
private final int MAX_SIZE = 1024;
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
int bytes = byteBuf.readableBytes();
if(bytes > MAX_SIZE) {
byteBuf.skipBytes(bytes);
throw new TooLongFrameException("2 long");
}
}
}
编码器
MessageToByteEncoder
public class StringToBytesEncoder extends MessageToByteEncoder<String> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, String s, ByteBuf byteBuf) throws Exception {
byteBuf.writeBytes(s.getBytes());
}
}
MessageToMessageEncoder
public class IntegerToStringEncoder extends MessageToMessageEncoder<Integer> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Integer integer, List<Object> list) throws Exception {
list.add(String.valueOf(integer));
}
}
编解码器
MessageToMessageCodec
使用该类,可以在一个单个类中实现转换的往返过程
public class MsgToMsgCodec extends MessageToMessageCodec<Integer,String> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, String s, List<Object> list) throws Exception {
list.add(Integer.parseInt(s));
}
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, Integer integer, List<Object> list) throws Exception {
list.add(String.valueOf(integer));
}
}
CombinedChannelDuplexHandler
结合编解码器可能会对可重用性造成影响,所以netty提供了CombinedChannelDuplexHandler类,该类充当了Inbound和outBound的容器
@ChannelHandler.Sharable
public class CombinedStringIntegerCodec extends CombinedChannelDuplexHandler<IntegerToStringMessageDecoder,IntegerToStringEncoder> {
public CombinedStringIntegerCodec() {
super(new IntegerToStringMessageDecoder(),new IntegerToStringEncoder());
}
}
该方式相比于使用编解码器更加灵活,也取决于个人编程习惯