Netty学习笔记(六)ChannelHandler和ChannelPipeLine
一、ChannelHandler
1、Channel生命周期
Channel 定义了一组和 ChannelInboundHandler API 密切相关的简单但功能强大的状态模型,下表展示的是Channel的生命周期个阶段状态:
| 状态 | 描述 |
|
ChannelUnregistered |
Channel 已经被创建,但还未注册到 EventLoop |
|
ChannelRegistered |
Channel 已经被注册到了 EventLoop |
|
ChannelActive |
Channel 处于活动状态(已经连接到它的远程节点)。它现在可以接收和发送数据了 |
|
ChannelInactive |
Channel没有连接到远程节点 |
Channel 的正常生命周期如下图所示。当这些状态发生改变时,将会生成对应的事件。 这些事件将会被转发给 ChannelPipeline 中的 ChannelHandler,其可以随后对它们做出响应。

2、ChannelHandler的生命周期
下表列出了 ChannelHandler 定义的生命周期操作,在 ChannelHandler 被添加到 ChannelPipeline 中或者被从 ChannelPipeline 中移除时会调用这些操作。这些方法中的每一个都接受一个 ChannelHandlerContext 参数。
| 类型 | 描述 |
|
handlerAdded |
当把 ChannelHandler 添加到 ChannelPipeline 中时被调用 |
|
handlerRemoved |
当从 ChannelPipeline 中移除 ChannelHandler 时被调用 |
|
exceptionCaught |
当处理过程中在 ChannelPipeline 中有错误产生时被调用 |
3、ChannelHandler接口
Netty 定义了下面两个重要的 ChannelHandler 子接口:
ChannelInboundHandler:处理入站数据以及各种状态变化;
ChannelOutboundHandler:处理出站数据并且允许拦截所有的操作。
不仅如此,我们也可以使用 ChannelInboundHandlerAdapter 和 ChannelOutboundHandlerAdapter 类作为自己的 ChannelHandler 的起始点。这两个适配器分别提供了 ChannelInboundHandler 和 ChannelOutboundHandler 的基本实现。通过扩展抽象类 ChannelHandlerAdapter,它们获得了它们共同的超接口ChannelHandler 的方法。 他们的类关系图如下:

二、ChannelPipeLine
ChannelPipeline 就是一个拦截流经 Channel 的入站和出站事件的 ChannelHandler 实例链,每一个新创建的 Channel 都将会被分配一个新的 ChannelPipeline。这项关联是永久性的,Channel 既不能附加另外一个 ChannelPipeline,也不能分离其当前的。根据事件的起源,事件将会被 ChannelInboundHandler 或者 ChannelOutboundHandler处理,随后,通过调用 ChannelHandlerContext 实现,它将被转发给同一超类型的下一个ChannelHandler。
下图展示了一个典型的同时具有入站和出站 ChannelHandler 的 ChannelPipeline 的布局,如果一个入站事件被触发,它将被从 ChannelPipeline 的头部开始一直被传播到 ChannelPipeline 的尾端。 而一个出站事件将从 ChannelPipeline 的尾端开始传递到头部。

1、修改ChannelPipeLine
ChannelHandler 可以通过添加、删除或者替换其他的 ChannelHandler 来实时地修改 ChannelPipeline 的布局。(它也可以将它自己从 ChannelPipeline 中移除。)下表列出了相关方法:
| 方法 | 说明 |
|
addFirst addLast addBefore addAfter |
将一个ChannelHandler添加到ChannelPipeline中 |
|
remove |
将一个 ChannelHandler 从 ChannelPipeline 中移除 |
|
replace |
将 ChannelPipeline 中的一个 ChannelHandler 替换为另一个 ChannelHandler |
除了这些操作,还有别的通过类型或者名称来访问 ChannelHandler 的方法如下表所示
| 方法 | 说明 |
| get |
通过类型或者名称返回 ChannelHandler |
| context |
返回和 ChannelHandler 绑定的 ChannelHandlerContext |
| names |
返回 ChannelPipeline 中所有 ChannelHandler 的名称 |
2、触发事件
ChannelPipeline 的API公开了用于调用入站和出站操作的附加方法。下表列出了入站操作,用于通知 ChannelInboundHandler 在 ChannelPipeline 中所发生的事件。
| 方法 | 说明 |
|
fireChannelRegistered |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelRegistered(ChannelHandlerContext)方法 |
|
fireChannelUnregistered |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelUnregistered(ChannelHandlerContext)方法 |
|
fireChannelActive |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelActive(ChannelHandlerContext)方法 |
|
fireChannelInactive |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelInactive(ChannelHandlerContext)方法 |
|
fireExceptionCaught |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 exceptionCaught(ChannelHandlerContext, Throwable)方法 |
|
fireUserEventTriggered |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 userEventTriggered(ChannelHandlerContext, Object)方法 |
|
fireChannelRead |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelRead(ChannelHandlerContext, Object msg)方法 |
|
fireChannelReadComplete |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelReadComplete(ChannelHandlerContext)方法 |
|
fireChannelWritabilityChanged |
调用 ChannelPipeline 中下一个 ChannelInboundHandler 的 channelWritabilityChanged(ChannelHandlerContext)方法 |
下表列出了ChannelPipeline API 的出站操作:
| 方法 | 说明 |
| bind | 将 Channel 绑定到一个本地地址,这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的bind(ChannelHandlerContext, SocketAddress, ChannelPromise)方法 |
| connect | 将 Channel 连接到一个远程地址,这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 connect(ChannelHandlerContext, SocketAddress, ChannelPromise)方法 |
| disconnect | 将 Channel 断开连接。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 disconnect(ChannelHandlerContext, Channel Promise)方法 |
| close | 将 Channel 关闭。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 close(ChannelHandlerContext, ChannelPromise)方法 |
|
deregister |
将 Channel 从它先前所分配的 EventExecutor(即 EventLoop)中注销。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 deregister (ChannelHandlerContext, ChannelPromise)方法 |
| flush | 冲刷 Channel 所有挂起的写入。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 flush(ChannelHandlerContext)方法 |
| write | 将消息写入 Channel。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 write(ChannelHandlerContext, Object msg, ChannelPromise)方法。注意:这并不会将消息写入底层的 Socket,而只会将它放入队列中。 要将它写入 Socket,需要调用 flush()或者 writeAndFlush()方法 |
| writeAndFlush | 这是一个先调用write()方法再接着调用flush()方法的便利方法 |
| read | 请求从 Channel 中读取更多的数据。这将调用 ChannelPipeline 中的下一个 ChannelOutboundHandler 的 read(ChannelHandlerContext)方法 |
总结一下:
- ChannelPipeline 保存了与 Channel 相关联的 ChannelHandler;
- ChannelPipeline 可以根据需要,通过添加或者删除 ChannelHandler 来动态地修改;
- ChannelPipeline 有着丰富的 API 用以被调用,以响应入站和出站事件。

浙公网安备 33010602011771号