范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

netty系列之channelHandlerContext详解

  简介
  我们知道ChannelHandler有两个非常重要的子接口,分别是ChannelOutboundHandler和ChannelInboundHandler,基本上这两个handler接口定义了所有channel inbound和outbound的处理逻辑。
  不管是ChannelHandler还是ChannelOutboundHandler和ChannelInboundHandler,几乎他们中所有的方法都带有一个ChannelHandlerContext参数,那么这个ChannelHandlerContext到底是做什么用的呢?它和handler、channel有什么关系呢? ChannelHandlerContext和它的应用
  熟悉netty的朋友应该都接触过ChannelHandlerContext,如果没有的话,这里有一个简单的handler的例子: public class ChatServerHandler extends SimpleChannelInboundHandler {      @Override     public void channelActive(ChannelHandlerContext ctx) throws Exception {         log.info("accepted channel: {}", ctx.channel());         log.info("accepted channel parent: {}", ctx.channel().parent());         // channel活跃         ctx.write("Channel Active状态!r ");         ctx.flush();     } }
  这里的handler继承了SimpleChannelInboundHandler,只需要实现对应的方法即可。这里实现的是channelActive方法,在channelActive方法中,传入了一个ChannelHandlerContext参数,我们可以通过使用ChannelHandlerContext来调用它的一些方法。
  先来看一下ChannelHandlerContext的定义: public interface ChannelHandlerContext extends AttributeMap, ChannelInboundInvoker, ChannelOutboundInvoker {
  首先ChannelHandlerContext是一个AttributeMap,可以用来存储多个数据。
  然后ChannelHandlerContext继承了ChannelInboundInvoker和ChannelOutboundInvoker,可以触发inbound和outbound的一些方法。
  除了继承来的一些方法之外,ChannelHandlerContext还可以作为channel,handler和pipline的沟通桥梁,因为可以从ChannelHandlerContext中获取到对应的channel,handler和pipline: Channel channel(); ChannelHandler handler(); ChannelPipeline pipeline();
  还要注意的是ChannelHandlerContext还返回一个EventExecutor,用来执行特定的任务: EventExecutor executor();
  接下来,我们具体看一下ChannelHandlerContext的实现。 AbstractChannelHandlerContext
  AbstractChannelHandlerContext是ChannelHandlerContext的一个非常重要的实现,虽然AbstractChannelHandlerContext是一个抽象类,但是它基本上实现了ChannelHandlerContext的所有功能。
  首先看一下AbstractChannelHandlerContext的定义: abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint
  AbstractChannelHandlerContext是ChannelHandlerContext的一个具体实现。
  通常来说一个handler对应一个ChannelHandlerContext,但是在一个程序中可能会有多于一个handler,那么如何在一个handler中获取其他的handler呢?
  在AbstractChannelHandlerContext中有两个同样是AbstractChannelHandlerContext类型的next和prev,从而使得多个AbstractChannelHandlerContext可以构建一个双向链表。从而可以在一个ChannelHandlerContext中,获取其他的ChannelHandlerContext,从而获得handler处理链。     volatile AbstractChannelHandlerContext next;     volatile AbstractChannelHandlerContext prev;
  AbstractChannelHandlerContext中的pipeline和executor都是通过构造函数传入的:     AbstractChannelHandlerContext(DefaultChannelPipeline pipeline, EventExecutor executor,                                   String name, Class<? extends ChannelHandler> handlerClass) {         this.name = ObjectUtil.checkNotNull(name, "name");         this.pipeline = pipeline;         this.executor = executor;         this.executionMask = mask(handlerClass);         // Its ordered if its driven by the EventLoop or the given Executor is an instanceof OrderedEventExecutor.         ordered = executor == null || executor instanceof OrderedEventExecutor;     }
  可能有朋友会有疑问了,ChannelHandlerContext中的channel和handler是如何得到的呢?
  对于channel来说,是通过pipeline来获取的: public Channel channel() {         return pipeline.channel();     }
  对于handler来说,在AbstractChannelHandlerContext中并没有对其进行实现,需要在继承AbstractChannelHandlerContext的类中进行实现。
  对于EventExecutor来说,可以通过构造函数向AbstractChannelHandlerContext传入一个新的EventExecutor,如果没有传入或者传入为空的话,则会使用channel中自带的EventLoop:     public EventExecutor executor() {         if (executor == null) {             return channel().eventLoop();         } else {             return executor;         }     }
  因为EventLoop继承自OrderedEventExecutor,所以它也是一个EventExecutor。
  EventExecutor主要用来异步提交任务来执行,事实上ChannelHandlerContext中几乎所有来自于ChannelInboundInvoker和ChannelOutboundInvoker的方法都是通过EventExecutor来执行的。
  对于ChannelInboundInvoker来说,我们以方法fireChannelRegistered为例:     public ChannelHandlerContext fireChannelRegistered() {         invokeChannelRegistered(findContextInbound(MASK_CHANNEL_REGISTERED));         return this;     }      static void invokeChannelRegistered(final AbstractChannelHandlerContext next) {         EventExecutor executor = next.executor();         if (executor.inEventLoop()) {             next.invokeChannelRegistered();         } else {             executor.execute(new Runnable() {                 @Override                 public void run() {                     next.invokeChannelRegistered();                 }             });         }     }
  fireChannelRegistered调用了invokeChannelRegistered方法,invokeChannelRegistered则调用EventExecutor的execute方法,将真实的调用逻辑封装在一个runnable类中执行。
  注意,在调用executor.execute方法之前有一个executor是否在eventLoop中的判断。如果executor已经在eventLoop中了,那么直接执行任务即可,不需要启用新的线程。
  对于ChannelOutboundInvoker来说,我们以bind方法为例,看一下EventExecutor是怎么使用的:     public ChannelFuture bind(final SocketAddress localAddress, final ChannelPromise promise) {         ObjectUtil.checkNotNull(localAddress, "localAddress");         if (isNotValidPromise(promise, false)) {             // cancelled             return promise;         }          final AbstractChannelHandlerContext next = findContextOutbound(MASK_BIND);         EventExecutor executor = next.executor();         if (executor.inEventLoop()) {             next.invokeBind(localAddress, promise);         } else {             safeExecute(executor, new Runnable() {                 @Override                 public void run() {                     next.invokeBind(localAddress, promise);                 }             }, promise, null, false);         }         return promise;     }
  可以看到执行的逻辑和invokeChannelRegistered方法很类似,也是先判断executor在不在eventLoop中,如果在的话直接执行,如果不在则放在executor中执行。
  上面的两个例子中都调用了next的相应方法,分别是next.invokeChannelRegistered和next.invokeBind。
  我们知道ChannelHandlerContext只是一个封装,它本身并没有太多的业务逻辑,所以next调用的相应方法,实际上是Context中封装的ChannelInboundHandler和ChannelOutboundHandler中的业务逻辑,如下所示:     private void invokeUserEventTriggered(Object event) {         if (invokeHandler()) {             try {                 ((ChannelInboundHandler) handler()).userEventTriggered(this, event);             } catch (Throwable t) {                 invokeExceptionCaught(t);             }         } else {             fireUserEventTriggered(event);         }     }     private void invokeBind(SocketAddress localAddress, ChannelPromise promise) {         if (invokeHandler()) {             try {                 ((ChannelOutboundHandler) handler()).bind(this, localAddress, promise);             } catch (Throwable t) {                 notifyOutboundHandlerException(t, promise);             }         } else {             bind(localAddress, promise);         }     }
  所以,从AbstractChannelHandlerContext可以得知,ChannelHandlerContext接口中定义的方法都是调用的handler中具体的实现,Context只是对handler的封装。 DefaultChannelHandlerContext
  DefaultChannelHandlerContext是AbstractChannelHandlerContext的一个具体实现。
  我们在讲解AbstractChannelHandlerContext的时候提到过,AbstractChannelHandlerContext中并没有定义具体的handler的实现,而这个实现是在DefaultChannelHandlerContext中进行的。
  DefaultChannelHandlerContext很简单,我们看一下它的具体实现: final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {      private final ChannelHandler handler;      DefaultChannelHandlerContext(             DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {         super(pipeline, executor, name, handler.getClass());         this.handler = handler;     }      @Override     public ChannelHandler handler() {         return handler;     } }
  DefaultChannelHandlerContext中额外提供了一个ChannelHandler属性,用来存储传入的ChannelHandler。
  到此DefaultChannelHandlerContext可以传入ChannelHandlerContext中一切必须的handler,channel,pipeline和EventExecutor。 总结
  本节我们介绍了ChannelHandlerContext和它的几个基本实现,了解到了ChannelHandlerContext是对handler,channel和pipline的封装,ChannelHandlerContext中的业务逻辑,实际上是调用的是底层的handler的对应方法。这也是我们在自定义handler中需要实现的方法。 本文已收录于 http://www.flydean.com/04-4-netty-channelhandlercontext/
  最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
  欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

华为宣布今年正式回归!这次超越苹果?华为的手机业务这两年沉寂下来了,主要还是由于美国的制裁,导致供应链跟不上芯片短缺等问题。看看华为最近发布的新机就知道了,基本都是套娃,什么Mate40EP50E之类的,不仅没有5G你手机里有哪些搞笑段子或图片?1。中午吃的大盘鸡,去时桌子上放一袋毛豆,后一同事来了,吃起来,我也吃,完了说你咋不多带点啊?我一懵这不是你的?那你就吃?答,我以为你带的啊。正在这时听到一个女孩子大声问,我的毛豆耳朵听不见一定要买助听器吗?有别的办法吗?这要看你说的听不见是部分听不见还是完全听不见。如果是完全听不见,戴助听器也没用啊。如果只是部分听不见,又没办法治疗,只能采取外界措施了。听力下降当你发现在公共场所听不好女人,孩子,你们的苹果手机感谢您的阅读!一般来说,我们建议苹果手机最好给手机带上手机壳和手机贴膜,在这里分享一下我自己手机使用的体验。我之前使用的是iPhoneX,这款手机的后盖采用的是玻璃的材质,所以手感拿平板当手机用,是一种什么体验?我只能总结一句,缺点很多,优点没有几个!为啥这样所呢首先手机是高频使用设备,尺寸一定有一个临界值的!就像现在的大屏手机最多宣传到7寸,折叠屏展开最大达到8寸左右,就不会太大了,所以3500以内的手机推荐,不要曲面屏?3500以内的手机推荐,不要曲面屏?手机买新不买旧,2022年了,3500元价位有一点尴尬,购买高端旗舰机不够。推荐realme真我GT2pro手机,它是2022年元月份上市的一款你的手机中有哪些珍藏的软件?口袋记账APP。这个是除了微信支付宝这些外,我下载且使用时间最长的一个,大概已经用了3年多了。个人觉得对我来说挺有用的,值得珍藏,而且已经推荐给身边的好多家人和朋友记账了。口袋记账空调是怎么造的?空调接通电源后,制冷制热的转换是通过四通阀来实现的。制冷时,压缩机吸入低温低压的气体,经压缩后,变为高温高压的饱和气体,送入冷凝器,高温饱和气体在冷凝器中经过冷却,保持压力不变,向为什么使用mq?为什么使用MQ(消息队列),这是一个很经典的问题,在互联网公司里,MQ是必须用到的,有以下场景异步处理例如有一个表单提交,涉及多个系统的交互,形成一个冗长的流程,同步处理完毕,再返明智捡漏人入手三星官翻机Note10,我爱了最近一段时间大家是不是都把关注点放在了三星S22系列新机上,而我却注意到,Note10这一部旗舰机。如果你也是一位实用党,抱着性价比的观念选购手机,那先看看这篇评测分享,相信对你有马云做出决定后,刘强东也紧随其后,网友又一个时代落幕了作为互联网时代的受益者,马云和刘强东可以说是两个代表性人物了。马云当初成立阿里公司,凭借着电商时代的来临,成为了首屈一指的人物。而刘强东也同样借着互联网这股东风,成为了电商时代的第
直屏党的最爱!盘点4款直屏手机,颜值吊打曲面屏,配置堪称王者近年来的手机市场上,曲面屏产品占据主流,对于喜欢直屏的朋友来说可以说很头疼,因为他们很难找到一款称心如意的直屏手机。其实,虽然曲面屏手机带来了更好的视觉效果,但是经常会误触,曲面屏腾讯要求抖音赔偿8亿据界面新闻报道,近日,持续8个月之久的长短视频之争有了新进展。腾讯向法院申请变更诉讼请求,将斗罗大陆索赔金额从6160万元提高到8亿元。至此,腾讯半年来起诉抖音的标的总额已超过29中国英伟达的虚与实图片来源视觉中国文丨锦缎最近一个周期,我国在前沿硬科技领域投入越来越大,相关论文发表和论文引用量逐渐开始占领世界第一的位置。数量上的进步鼓舞人心,但质量上的全面突围还需要耐心。比如iOS16将不会支持这些机型,万年钉子户该换机了前阵子iOS15。2正式版发布了,新功估计更新得差不多了,iOS15。3beta1预览版就又来了,主要以修复bug为主和优化性能。除此以外,苹果也将开始在内部关注下一个重要版本,即烽火狼烟丨ApacheLog4j2拒绝服务攻击(CVE45105)漏洞通告漏洞概述近日,WebRAY安全服务部监测到编号为CVE202145105的ApacheLog4j2拒绝服务攻击漏洞,当系统日志配置使用非默认的模式布局和上下文查找时,攻击者可以通过懒出来的财富阿里巴巴总裁马云一直说自己是个懒人,说世界上很多超级富翁都是懒人。电梯的出现是因为懒得爬楼,汽车的出现是因为懒得走路,唱片的出现是因为懒得听音乐会马云的懒不是傻懒,他懒出了思路,懒回顾reInvent2021从15年的科技创新看领导力准则的脉动就在今年7月份,亚马逊发布了最新版领导力准则,在原有14条的基础上新增了努力成为最佳雇主和能力越大,责任越大两条,越发凸显了其作为科技行业领军企业的责任与担当。虽然贝索斯选择在亚马苹果起诉爱立信在5G技术专利谈判中使用强硬策略财经网科技12月21日讯,据凤凰网科技消息,苹果与爱立信的5G专利许可谈判争执仍在继续。这一次,苹果对爱立信提起反诉,指控爱立信在谈判过程中采取强硬策略,提出不合理要求。苹果在上周荣耀60小米Civi哪款值得入手?各有千秋小米手机一直被大众认为是高性价比的品牌,而荣耀留给大众的印象一般是高价低配,那么作为两款定位相仿的机型,荣耀60和小米Civi,哪款更值得入手呢?小米Civi的优势在于屏幕,它是目小米11pro和小米mix4相比较,该如何选?本人有幸两个手机都用过。先用的小米11pro,使用了两个月,后把手机给老爸,自己换了小米mix4。小米11pro,发热严重,看网上评价还会烧wifi。但是屏幕2k屏,清晰。前置摄像从薇娅偷税漏税之事看电商怪象首先讲一讲什么是电商。我们不用专业的词语来解说,说白了电商就是在互联网上销售产品而进行的商业活动,是把现实生活中的商业活动,搬到虚拟的世界当中来进行的。这种交易的方式非常的便利和快