Netty——ChannelHandler

  • 类图
  • 顶层接口:ChannelHandler
    • ChannelInboundHandler接口 和 ChannelOutboundHandler接口 和 ChannelHandlerAdapter抽象类
      • ChannelInboundHandlerAdapter接口 和 ChannelOutboundHandlerAdapter接口
        • SimpleChannelInboundHandler

1. 接口ChannelHandler

方法:其中 ctx 为 ChannelHandlerContext 类 
void handlerAdded( ctx )当把 ChannelHandler 添加到 ChannelPipeline 中时被调用
void handlerRemoved( ctx )当从 ChannelPipeline 中移除 ChannelHandler 时被调用
void exceptionCaught(ctx , Throwable var2)当处理过程中在 ChannelPipeline 中有错误产生时被调用
public @interface Sharable {} 

2.1  接口ChannelInboundHandler

方法:其中 ctx 为 ChannelHandlerContext 类 
void channelRegistered( ctx ) 当 Channel 已经注册到它的 EventLoop 并且能够处理 I/O 时被调用
channelUnregistered( ctx )当 Channel 从它的 EventLoop 注销并且无法处理任何 I/O 时被调用
channelActive( ctx )当 Channel 处于活动状态时被调用;Channel 已经连接/绑定并且已经就绪
channelInactive( ctx )当 Channel 离开活动状态并且不再连接它的远程节点时被调用
channelReadComplete( ctx )当Channel上的一个读操作完成时被调用
channelRead( ctx, object  )读取数据时被调用。注:实现类重写这个方法时需要在最后添加ReferenceCountUtil.release(msg);方法来释放ByteBuf相关内存。一个简单的方式是使用SimpleChannelInboundHandler,后者帮你实现好了,会自动释放资源
channelWritabilityChanged( ctx )当 Channel 的可写状态发生改变时被调用。用户可以确保写操作不会完成
得太快(以避免发生 OutOfMemoryError)或者可以在 Channel 变为再
次可写时恢复写入。可以通过调用 Channel 的 isWritable()方法来检测
Channel 的可写性。与可写性相关的阈值可以通过 Channel.config().
setWriteHighWaterMark()和 Channel.config().setWriteLowWaterMark()方法来设置
userEventTriggered( ctx, object  )当 ChannelnboundHandler.fireUserEventTriggered()方法被调用时被调用,因为一个 POJO 被传经了 ChannelPipeline

2.2 接口ChannelOutboundHandler

其中ChannelPromise是ChannelFuture的一个 子类 
void bind(ctx, SocketAddress var2, ChannelPromise var3)当请求将 Channel 绑定到本地地址时被调用
void connect(ctx, SocketAddress var2, SocketAddress var3, ChannelPromise var4)当请求将 Channel 连接到远程节点时被调用
void disconnect(ctx, ChannelPromise var2)当请求将 Channel 从远程节点断开时被调用
void close(ctx, ChannelPromise var2)当请求关闭 Channel 时被调用
void deregister(ctx, ChannelPromise var2)当请求将 Channel 从它的 EventLoop 注销 时被调用
void read(ctx) 当请求从 Channel 读取更多的数据时被调用
void write(ctx, Object var2, ChannelPromise var3)当请求通过 Channel 将数据写到远程节点时被调用。需要注意的是实现类在重写该方法时需要勿忘两件事:1.加上ReferenceCountUtil.release(msg);方法来释放ByteBuf相关内存;2.加上promise.setSuccess()进行通知,否则ChannelFutureListener收不到某个消息已经被处理了的通知情况
void flush(ctx)当请求通过 Channel 将入队数据冲刷到远程 节点时被调用

3. 抽象类ChannelHandlerAdapter

public boolean isSharable()实现了两个与shareable注解相关方法:如果isSharable()对应的实现被标注为 Sharable,那么这个方法将返回 true,表示它可以被添加到多个 ChannelPipeline中
protected void ensureNotSharable()
void handlerRemoved( ctx )继承根接口ChannelHandler,空方法
void handlerAdded( ctx )继承根接口ChannelHandler,空方法
public void exceptionCaught(ctx , Throwable cause)ctx.fireExceptionCaught(cause);

4.1 接口ChannelInboundHandlerAdapter

public void exceptionCaught( ctx, Throwable cause ) 继承自抽象父类ChannelHandlerAdapterctx.fireExceptionCaught(cause)
总共八个方法,全部继承自父接口ChannelInboundHandler,委托给ctx实现,并加了@Skip注解,以channelRead( ctx,Obj msg )为例ctx.fireChannelRead(msg)

4.2 接口ChannelOutboundHandlerAdapter

总共八个方法,全部继承自父接口ChannelOutboundHandler,委托给ctx实现,并加了@Skip注解。以bind(ctx, SocketAddress var2, ChannelPromise var3) 为例ctx.bind(localAddress, promise)

5.1 SimpleChannelInboundHandler

1. 该实现类继承自ChannelInboundHandlerAdapter,与ChannelInboundHandlerAdapter的不同在于channelRead0() 和 channelRead()两个方法。实现这个类的时候只需重写channelRead0()方法

  • channelRead():继承自父类,与父类的区别在于,提供了一个模板:帮你实现好了ReferenceCountUtil.release(msg);释放资源,实际内容由channelRead0()负责
    •     @Override// 继承了 ChannelInboundHandlerAdapter#channelRead
          public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
              boolean release = true;
              try {
                  if (acceptInboundMessage(msg)) {
                      @SuppressWarnings("unchecked")
                      I imsg = (I) msg;
                      channelRead0(ctx, imsg);// 模板方法,抽出可变的部分,具体实现在子类中
                  } else {
                      release = false;
                      ctx.fireChannelRead(msg);
                  }
              } finally {
                  if (autoRelease && release) {
                      ReferenceCountUtil.release(msg);// 释放资源(保存消息的ByteBuf)
                  }
              }
          }
  • channelRead0():抽象方法,真正需要重写的逻辑

    • protected abstract void channelRead0(ChannelHandlerContext var1, I var2) throws Exception;

2. 为什么要设计SimpleChannelInboundHandler这个类?

  • 在客户端,当 channelRead0() 方法完成时,你已经有了传入消息,并且已经处理完它了。当该方法返回时,SimpleChannelInboundHandler负责释放指向保存该消息的ByteBuf的内存引用。
  • 在服务端中,有时你仍然需要将传入消息回送给发送者,而 write() 操作是异步的,直到 channelRead() 方法返回后可能仍然没有完成。为此,EchoServerHandler扩展了 ChannelInboundHandlerAdapter ,其在这个时间点上不会释放消息。
  • Reference:https://blog.csdn.net/u010739551/article/details/89496731
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值