Netty 业务处理:ChannelHandler家族
ChannelHandler 接口
类型 | 描述 |
---|---|
handlerAdded | ChannelHandler添加到ChannelPipeline时被调用 |
handlerRemoved | ChannelHandler从ChannelPipeline时被调用 |
exceptionCaught | 处理过程中ChannelPipeline有错误 |
ChannelInBoundHandler接口
- SimpleChannelInBoundHandler 会自动释放资源,调用了 ReferenceCountUtil.release(msg);
ChannelOutBoundHandler接口
可按需推迟操作和事件。大部分方法都接收一个ChannelPromise参数[ChannelFuture的一个子类]
这里借鉴的是 Scala 的 Promise 和 Future 的设计,当一个 Promise 被完成之后,其对应的 Future 的值便 不能再进行任何修改了。
ChannelHandler适配器
ChannelHandlerAdapter 还提供了实用方法 isSharable()。如果其对应的实现被标 注为 Sharable,那么这个方法将返回 true,表示它可以被添加到多个 ChannelPipeline 中.
为何要共享同一个ChannelHandler 在多个ChannelPipeline中安装同一个ChannelHandler 的一个常见的原因是用于收集跨越多个Channel的统计信息。
资源管理 ResourceLeakDetector
对你应用程序的缓冲区分配做大约1%的采样来检测内存泄露,ResourceLeakDetector利用了 JDK 提供的PhantomReference类来实现这一点。
ChannelPipeline 接口
ChannelHandler 可以通过添加、删除或者替换其他的 ChannelHandler 来实时地修改 ChannelPipeline的布局。(它也可以将它自己从ChannelPipeline中移除。)这是ChannelHandler最重要的能力之一。
名 称 | 描 述 |
---|---|
AddFirstaddBefore和addAfteraddLast | 将一个ChannelHandler添加到ChannelPipeline中 |
remove | 将一个ChannelHandler从ChannelPipeline中移除 |
replace | 将 ChannelPipeline 中的一个 ChannelHandler 替换为另一个 Channel- Handler |
ChannelHandlerContext接口
和Channel和ChannelPipeline有很多相同操作的方法。
不同的是:如果调用Channel或者ChannelPipeline上的这 些方法,它们将沿着整个ChannelPipeline进行传播。而调用位于ChannelHandlerContext 上的相同方法,则将从当前所关联的 ChannelHandler 开始,并且只会传播给位于该 ChannelPipeline中的下一个能够处理该事件的ChannelHandler。
通过Channel,ChannelPipeline 和ChannelHandlerContext事件流的区别
异常处理
- 入栈实现:exceptionCaught
- 出站实现:对ChannelFuture添加监听器,判断ChannelFuture.isSuccess()
ChannelFuture future = channel.write(someMessage); future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) { if (!f.isSuccess()) { f.cause().printStackTrace(); f.channel().close(); } } });
第二种方式是将 ChannelFutureListener 添加到即将作为参数传递给 ChannelOut- boundHandler 的方法的 ChannelPromise。
public class OutboundExceptionHandler extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { promise.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture f) { if (!f.isSuccess()) { f.cause().printStackTrace(); f.channel().close(); } } }); } }