Netty中ChannelHandler 抽象了接口, 在ChannelPipeline中执行,覆盖的事件处理方法,让其写出更简介,处理逻辑。
ChannelPipeline中通过不同的ChannelHandlers处理I/O,对应I/O操作,ChannelPipeline中对应使用ChannelInboundHandler或ChannelOutboundHandler执行。而这些方法定义在ChannelInboundInvoker和ChannelOutboundInvoker中。
ChannelPipeline 可以在运行时,动态的添加修改或删除相应ChannelHandler,提供了
addFirst、addBefore、addAfter、addLast、remove、replace等这些操作方法。
ChannelPipline中执行ChannelHandlers是在单线程中执行,这就意味着我们在ChannelHandlers中不应该写入阻塞的代码。这将直接影响后面的Handler运行。
ChannelPipline还提供了获取他之中的ChannelHandler方法:
get、context、contains、names、iterator等这些操作方法。
ChannelPipline还继承自ChannelInboundInvoker跟ChannelOutboundInvoker,这意味着他提供了许多事件通知执行方法,诸如fireChannelRegistered()这些操作。ChannelOutboundInvoker 则定义了诸如write、flush、bind这些操作。
ChannelHandlerContext 一个上下文对象。当一个ChannelHandler被加入到ChannelPipleline中,会新创建一个ConnalHandlerContext ,并绑定到改ChannelHandler中。
ChannelHandlerContext同样实现了ChannelInboundInvoker跟ChannelOutboundInvoker。
跟ChannlePipeline和ChannelHadnler的关系
前面提到ChannelHandlerContext跟ChannlePipeline都实现了ChannelOutboundInvoker,但他们调用wirte方法时,在netty的事件机制定义下,事件执行的顺序则在ChannelPipeline的中ChannelHandlers的顺序跟方式则不一样。
Channel 跟 ChannelPipeline 都可以通过write方法对客户端写数据,其中write方法写入并不会立即写出,会写入到队列中,除非 flush,则会立即写出。
使用Channel跟ChannelPipleline的write,则会触发事件,经过所有实现了ChannlOutboundHandler的ChannelHandler执行。
而使用ChannelHandlerContext中的write方法,则会出发在ChannelPipeline中当前执行ChannelHandlerContext的ChannelHandler它的一个ChannelHandler继续执行。
我们想在多个ChannelPipeline中使用一个ChannelHandler实例,可在ChannelHandler类定义中加入@Sharable注解。在每次执行方法时,方法传入的ChannelHandlerContext则是对应他们所在ChannelPipeline创建并为他绑定的实例。
ChannelHandler 类型有两类:
Inbound Handler : 处理接收到的数据跟改化他们的状态。
Outbound Handler : 处理要发出去的数据跟可以中断不同的操作。
ChannelHandler的几个事件
handleAddad() , 在生加入 ChannelPipeline执行。
handleRemoved(), 在ChannelPipeline中移除执行。
exceptionCatch(),当在ChannelPipeline中处理时发生异常被捕获。
ChannelInboundHandler 的几个重要方法:
channelRegistered() :Channel在EventLoop中注册时执行,并开始执行I/O操作。
channelUnRegistered() :当Channel在EventLoop中注销时执行,已玩I/O操作。
channelActive() : Channel在connected/bound时执行。
channelInActive() : Channel在disconnected执行。
channelReadComplete():当一次读操作执行完成时间执行。
channelRead():读取到数据时执行。
userEventTriggered():用户在定制的事件中触发。
ChannelInboundHandler 的几个封装的类:
ChannelInboundHandlerAdapter
不释放ByteBuf资源,需要用ReferenceCountUtil.release(..)操作执行释放
SimpleChannelInboundHandler
自动释放 ByteBuf资源。
由于netty对ByteBuf进行池化管理 , 主要是"ReferenceCount"的方式,资源避免泄露,则需要释放。
ChannelOutboundHandler 的几个重要方法:
bind() : Channel绑定的网络地址时触发。
connect():Channel进行连接时触发。
diaconect():Channel关闭连接时触发。
close() :Channel关闭时触发。
deregister():Channel在EventLoop中注销触发。
read():当须要Channel读取更多的数据时触发。
flush():让列队数据写的数据写到客户端/服务端时触发。
write():写数据到客户端/服务端时触发。