6.4 ChannelHandlers and their types
Netty支持拦截操作或通过ChannelHandler对状态变化做出反应。这使得以可重用的方式编写自定义处理逻辑非常容易。
There are two different types of ChannelHandlers that Netty supports, as shown in table 6.6.

Ill discuss each type, but lets start with the base interface for all of them.
6.4.1 ChannelHandler--the parent of all
Netty使用定义明确(well-defined)的类型层次结构(type-hierarchy)来表示不同的处理程序类型。它们的父级都是ChannelHandler。它提供在从其ChannelPipeline添加或删除ChannelHandler之后调用的生命周期操作。

表6.7中列出的每个方法在调用时都将ChannelHandlerContext作为参数。为添加到ChannelPipeline的每个ChannelHandler自动创建此ChannelHandlerContext。ChannelHandlerContext绑定到ChannelHandler,ChannelPipeline和Channel本身。
ChannelHandlerContext允许您安全地存储和检索在Channel本地的值。请参考有关ChannelHandlerContext的小节,以获取有关它以及如何使用它的更多信息。
Netty为ChannelHandler提供了一个称为ChannelHandlerAdapter的框架(skeleton)实现。这为其所有方法提供了基本实现,因此您只能实现(覆盖)您感兴趣的方法。基本上,它将事件转发到ChannelPipeline中的下一个ChannelHandler,直到结束为止。
6.4.2 Inbound handlers

这些方法中的每一个都是可以在ChannelInboundInvoker上调用的方法的对等方法,该方法由ChannelHandlerContext和ChannelPipeline扩展。
ChannelInboundHandler is a subtype of ChannelHandler and also exposes all of its methods.
Netty provides a skeleton implementation for ChannelInboundHandler implementations called ChannelInboundHandlerAdapter. This provides base implementations for all of its methods and allows you to implement (override) only the methods youre interested in. All of these methods implementations, by default,通过在ChannelHandlerContext上调用相同的方法,将事件转发到ChannelPipeline中的下一个ChannelInboundHandler。
Important to note is that the ChannelInboundHandler which handles received messages and so @Override the channelRead(Ö) method 负责释放资源. 这一点尤其重要,因为Netty将共享资源用于ByteBuf,因此,如果您忘记释放资源,最终将导致资源泄漏。

If you need to be notified about other state changes you could override one of the other methods that are part of the handler.
通常,您可能希望将字节解码为自定义消息类型,并且可能很想实现ChannelInboundHandler或扩展ChannelInboundhandlerAdapter。 But hold on a second, theres an even better solution to this problem. 可以使用编解码器框架轻松实现这些功能,我将在本章稍后解释。
现在,让我们回顾一下ChannelHandler。如果使用ChannelInboundHandler,则ChannelInboundHandlerAdapter或SimpleChannelInboundhandler取决于您的需求。大多数情况下,在处理消息时使用SimpleChannelInboundHandler,对于其他入站事件/状态更改,则使用ChannelInboundHandlerAdapter。
Inbound Message handling and reference counting
As you may remember from the previous chapter Netty uses reference counting to handle pooled ByteBufs. Thus it is important to make sure the reference count is adjusted after a ByteBuf is completly processed.
Because of this it is quite important to understand how ChannelOutboundHandlerAdapter differs from SimpleChannelInboundHandler. ChannelInboundHandlerAdapter does not call release on the message once it was passed to channelRead(...) and so its the responsibility of the user to do so if the message was consumed. SimpleChannelInboundHandler在这里有所不同,因为它在每次channelRead(...)调用之后自动释放消息,因此,如果您希望在方法返回后使用它,则您的代码将消耗该消息或在其上调用retain()。
Not correctly releasing a message will produce a memory leak, lucky enough Netty will by default log a message if this happens.
CHANNELINITIALIZER
有一个稍微修改的ChannelInboundHandler值得引起更多注意:ChannelInitializer.它的功能恰如其名。一旦它在EventLoop中注册并准备处理I / O,它就可以初始化该通道。
ChannelInitializer主要用于为创建的每个通道设置ChannelPipeline。这是自举的一部分(请参阅第9章,以进行更深入的了解)。For now, lets remember that theres an extra ChannelInboundHandler for that.
6.4.3 Outbound handlers
Now that youve had a look at how ChannelHandler allows you to hook into inbound operations and data, its time to look at those ChannelHandler implementations that allow you the same for outbound operations and data. This section shows you all of them.
CHANNELOUTBOUNDHANDLER
The ChannelOutboundHandler provides methods that are called when outbound operations are requested. These are the methods listed in the ChannelOutboundInvoker interface thats extended by Channel, ChannelPipeline, and ChannelHandlerContext.
What makes it powerful is the ability to implement a ChannelOutboundHandler and根据要求推迟操作。This opens some powerful and flexible ways to handle requests. For example, you could defer flush operations once nothing should be written to the remote peer and pick them up later once its allowed again.
Table 6.9 shows all the methods that are supported.

As shown in the hierarchy, ChannelOutboundHandler is a subtype of ChannelHandler and exposes all of its methods.
几乎所有方法都以ChannelPromise作为参数,一旦请求停止通过ChannelPipeline转发,则必须通知该方法。
Netty provides a skeleton implementation for ChannelOutboundHandler implementations called ChannelOutboundHandlerAdapter. This provides base implementations for all of its methods and allows you to implement (override) only the methods youre interested in. All these method implementations, by default, forward the event to the next ChannelOutboundHandler in the ChannelPipeline by calling the same method on the ChannelHandlerContext.
Here the same is true as for the ChannelInboundHandler. If you handle a write operation and discard a message its you responsible to release it probably.
Now lets look at how you could make use of this in practice. The following listing shows an implementation that discarded all written data.

Its important to remember to release resources and notify the ChannelPromise. If the ChannelPromise is not notified it may lead to situations where a ChannelFutureListener is not notified about a handled message.
Outbound Message handling and reference counting
Its the responsiblity of the user to call ReferenceCountUtil.release(message) if the message is consumed and not passed to the next ChannelOutboundHandler in the ChannelPipleline. Once the message is passed over to the actual Transport it will be released automatically by it once the message was written or the Channel was closed.
From this examples you should be able to see how the ChannelHandler implementation and all of its associated features make using Netty easier and more efficient.
最后更新于
这有帮助吗?