数据处理器ChannelHandler

ChannelHandler类似于Servlet的Filter过滤器,负责对I/O事件或者I/O操作进行拦截和处理,它可以选择性地拦截和处理自己感兴趣的事件,也可以透传和终止事件的传递。基于ChannelHandler接口,用户可以方便地进行业务逻辑定制,例如打印日志、统一封装异常信息、性能统计和消息编解码等。

ChannelHandler支持注解,目前支持的注解有两种:

  • @Sharable:多个ChannelPipeline共用同一个ChannelHandler;
  • @Skip:被Skip注解的方法不会被调用,直接被忽略。

1. ChannelInboundHandlerAdapter

ChannelInboundHandlerAdapter是ChannelInboundHandler的一个简单实现,默认情况下不会做任何处理,只是简单的将操作通过fire*方法传递到ChannelPipeline中的下一个ChannelHandler,让链中的下一个ChannelHandler去处理。

需要注意的是信息经过channelRead方法处理之后不会自动释放(因为信息不会被自动释放所以能将消息传递给下一个ChannelHandler处理)。

(1) SimpleChannelInboundHandler

SimpleChannelInboundHandler支持泛型的消息处理,默认情况下消息处理完将会被自动释放,无法提供fire*方法传递给ChannelPipeline中的下一个ChannelHandler,如果想要传递给下一个ChannelHandler需要调用ReferenceCountUtil#retain方法。

一般用netty来发送和接收数据都会继承SimpleChannelInboundHandler和ChannelInboundHandlerAdapter这两个抽象类。

其实用这两个抽象类是有讲究的,在客户端的业务Handler继承的是SimpleChannelInboundHandler,而在服务器端继承的是ChannelInboundHandlerAdapter。

最主要的区别就是SimpleChannelInboundHandler在接收到数据后会自动release掉数据占用的Bytebuffer资源(自动调用Bytebuffer.release())。而为何服务器端不能用呢,因为我们想让服务器把客户端请求的数据发送回去,而服务器端有可能在channelRead方法返回前还没有写完数据,因此不能让它自动release。

2. ChannelOutboundHandlerAdapter

表示出去的动作,监听自己的IO操作,比如connect,bind等,在重写这个Adapter的方法时,记得执行super.xxxx,否则动作无法执行。

Netty 中的事件分为inbound 事件和outbound 事件。inbound 事件通常由I/O线程触发,例如TCP 链路建立事件、链路关闭事件、读事件、异常通知事件等。Outbound 事件通常是I/O 用户主动发起的网络I/O 操作,例如用户发起的连接操作、绑定操作、消息发送等操作。

3. 两者的常用事件

我们常用的inbound事件有:

  • hannelRegistered(ChannelHandlerContext) //channel注册事件
  • channelActive(ChannelHandlerContext)//通道激活时触发,当客户端connect成功后,服务端就会接收到这个事件,从而可以把客户端的Channel记录下来,供后面复用
  • exceptionCaught(ChannelHandlerContext, Throwable)//出错时会触发,做一些错误处理
  • userEventTriggered(ChannelHandlerContext, Object)//用户自定义事件
  • channelRead(ChannelHandlerContext, Object) //当收到对方发来的数据后,就会触发,参数msg就是发来的信息,可以是基础类型,也可以是序列化的复杂对象。

常用的outbound事件有:

  • bind(ChannelHandlerContext ctx, SocketAddress localAddress,ChannelPromise promise) //服务端执行bind时,会进入到这里,我们可以在bind前及bind后做一些操作
  • connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) //客户端执行connect连接服务端时进入
  • write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)//发送事件
  • flush(ChannelHandlerContext ctx) //刷新事件

ChannelPromise是ChannelFuture的扩展,允许设置I/O操作的结果,使ChannelFutureListener可以执行相关操作。

 

posted @ 2020-01-19 14:33  codedot  阅读(688)  评论(1编辑  收藏  举报