Netty学习笔记(三) ChannelPipeline和ChannelHandler

3 篇文章 0 订阅

目录


在《Netty权威指南》(第二版)中,ChannelPipelineChannelHandler之间的关系被李林峰老师比做J2EE中的ServletFilter,即ChannelHandler的职能是网络I/O操作的过滤器。我们一起来详细学习它们吧。


ChannelHandler

Netty API : ChannelHandler

ChannelHandler功能介绍

  • ChannelHandler的主要功能是为I/O操作进行拦截和处理,我们可以称呼它为:I/O事件拦截器
  • 每一个Channel有拥有一个ChannelPipeline,每一个ChannelPipeline中可以包含多个ChannelHandler
  • ChannelHandler可以全部拦截也可以选择性的拦截通过它的信息。对拦截到的信息加以处理后,处理的结果会被传递到ChannelPipeline中的下一个ChannelHandler中执行对应的处理。

通过ChannelHandlerAdapter自定义拦截器

虽然Netty提供了种类丰富的ChannelHandler足以应付许多场景,但在实际项目中远远不够用,这时我们需要封装自己的拦截器。
通常自定义的ChannelHandler只需要继承ChannelHandlerAdapter并覆盖需要用到的方法即可。

ChannelHandlerContext接口

ChannelHandlerChannelHandlerContext是一一对应的关系,ChannelPipeline并不是直接管理ChannelHandler,而是通过ChannelHandlerContext来间接管理。ChannelHandlerContext通过以下两个方法可以获取到所绑定的ChannelChannelHandler

方法名返回类型说明
channel()Channel返回该ChannelHandlerContext所绑定的Channel
handler()ChannelHandler返回该ChannelHandlerContext所绑定的ChannelHandler

ChannelPipeline

Netty API : ChannelPipeline

ChannelPipeline介绍

每一个Channel都拥有自己的ChannelPipeline,它是ChannelHandler的容器,负责ChannelHandler的管理、事件拦截、消息调度。

ChannelPipeline工作原理

ChannelPipeline实际上就是Channel的数据管道,消息从其中通过,依次通过每个ChannelHandler并执行相应的处理。
我们通过对ChannelPipeline所持有的ChannelHandler链表进行简单的增删的操作就可以实现不同业务逻辑定制。

下图是Netty API 中ChannelPipeline对事件流的拦截和处理流程的示意图:

                                                 I/O Request
                                            via Channel or
                                        ChannelHandlerContext
                                                      |
  +---------------------------------------------------+---------------+
  |                           ChannelPipeline         |               |
  |                                                  \|/              |
  |    +---------------------+            +-----------+----------+    |
  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  |               |
  |               |                                  \|/              |
  |    +----------+----------+            +-----------+----------+    |
  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  .               |
  |               .                                   .               |
  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
  |        [ method call]                       [method call]         |
  |               .                                   .               |
  |               .                                  \|/              |
  |    +----------+----------+            +-----------+----------+    |
  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  |               |
  |               |                                  \|/              |
  |    +----------+----------+            +-----------+----------+    |
  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  |               |
  +---------------+-----------------------------------+---------------+
                  |                                  \|/
  +---------------+-----------------------------------+---------------+
  |               |                                   |               |
  |       [ Socket.read() ]                    [ Socket.write() ]     |
  |                                                                   |
  |  Netty Internal I/O Threads (Transport Implementation)            |
  +-------------------------------------------------------------------+

ChannelHandler的执行顺序

值得注意的一点是,ChannelHandler的执行顺序与向ChannelPipeline添加时的顺序有关。因此,在进行类似编解码这样前后依赖的操作时,对ChannelHandler添加的顺序要格外注意。

Netty API :
For example, let us assume that we created the following pipeline.
In the example above, the class whose name starts with Inbound means it is an inbound handler. The class whose name starts with Outbound means it is a outbound handler.

 ChannelPipeline p = ...;
 p.addLast("1", new InboundHandlerA());
 p.addLast("2", new InboundHandlerB());
 p.addLast("3", new OutboundHandlerA());
 p.addLast("4", new OutboundHandlerB());
 p.addLast("5", new InboundOutboundHandlerX());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿长大人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值