一起学netty(12)ChannelInboundHandler和ChannelOutboundHandler处理器
ChannelInboundHandler
ChannelInboundHandler是入栈消息处理的核心接口,如下:
public interface ChannelInboundHandler extends ChannelHandler {
void channelRegistered(ChannelHandlerContext var1) throws Exception;
void channelUnregistered(ChannelHandlerContext var1) throws Exception;
void channelActive(ChannelHandlerContext var1) throws Exception;
void channelInactive(ChannelHandlerContext var1) throws Exception;
void channelRead(ChannelHandlerContext var1, Object var2) throws Exception;
void channelReadComplete(ChannelHandlerContext var1) throws Exception;
void userEventTriggered(ChannelHandlerContext var1, Object var2) throws Exception;
void channelWritabilityChanged(ChannelHandlerContext var1) throws Exception;
void exceptionCaught(ChannelHandlerContext var1, Throwable var2) throws Exception;
}
其主要方法描述如下:
- channelRegistered: 当一个Channel注册到EventLoop上,可以处理I/O时被调用
- channelUnregistered: 当一个Channel从它的EventLoop上解除注册,不再处理I/O时被调用
- channelActive: 当Channel变成活跃状态时被调用;Channel是连接/绑定、就绪的
- channelInactive: 当Channel离开活跃状态,不再连接到某个远端时被调用
- channelReadComplete: 当Channel上的某个读操作完成时被调用
- channelRead: 当从Channel中读数据时被调用
- channelWritabilityChanged: 当Channel的可写状态改变时被调用。通过这个方法,用户可以确保写操作不会进行地太快(避免OutOfMemoryError)或者当Channel又变成可写时继续写操作。Channel类的isWritable()方法可以用来检查Channel的可写状态。可写性的阈值可以通过Channel.config().setWriteHighWaterMark()和Channel.config().setWriteLowWaterMark()来设定。
- userEventTriggered: 因某个POJO穿过ChannelPipeline引发ChannelnboundHandler.fireUserEventTriggered()时被调用。
一般我们在自定义消息处理器的时候通常会实现ChannelInboundHandler的一个子类ChannelInboundHandlerAdapter,它默认实现了调用下一个处理器的方法。
//入栈消息处理器
pipeline.addLast(new ChannelInboundHandlerAdapter(){
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(msg.getClass());
//释放内存
ReferenceCountUtil.release(msg);
}
});
可以看到,当消息处理器继承ChannelInboundHandlerAdapter类时并且msg的类型是ByteBuf类型时,需要执行ReferenceCountUtil.release(msg);方法手动释放ByteBuf的内存,因为ByteBuf使用的是直接内存。
为了避免上述情况的发生,我们还可以继承SimpleChannelInboundHandler类,如下:
//入栈消息处理器
pipeline.addLast(new SimpleChannelInboundHandler<ByteBuf>(){
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf msg) throws Exception {
System.out.println(msg);
}
});
它实际上是ChannelInboundHandlerAdapter的子类,它在实现channelRead方法时对ByteBuf进行了处理。

ChannelOutboundHandler
ChannelOutboundHandler是出栈消息处理的核心接口,一般在做回写数据的消息编码时会用到。它的子类一般都是各种编码器,如StringEncoder,MessageToMessageEncoder,ProtobufEncoder,HttpRequestEncoder等。
public interface ChannelOutboundHandler extends ChannelHandler {
void bind(ChannelHandlerContext var1, SocketAddress var2, ChannelPromise var3) throws Exception;
void connect(ChannelHandlerContext var1, SocketAddress var2, SocketAddress var3, ChannelPromise var4) throws Exception;
void disconnect(ChannelHandlerContext var1, ChannelPromise var2) throws Exception;
void close(ChannelHandlerContext var1, ChannelPromise var2) throws Exception;
void deregister(ChannelHandlerContext var1, ChannelPromise var2) throws Exception;
void read(ChannelHandlerContext var1) throws Exception;
void write(ChannelHandlerContext var1, Object var2, ChannelPromise var3) throws Exception;
void flush(ChannelHandlerContext var1) throws Exception;
}
fixed
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。