Jetty9源码剖析 - Handler组件 - ScopedHandler

博客已迁移至 http://www.ph0ly.com 欢迎大家访问新的网站,文章更加齐全~

一、ScopedHandler的概念

在Jetty生态中,特别是Handler组件里面,不得不提ScopedHandler,Handler体系里面很大部分核心组件都继承了ScopedHandler,例如ContextHandler、ServletHandler、SessionHandler等。
ScopedHandler其实就是责任链的变种,常规的责任链声明一个共享方法,自己完成后调用下一个链。ScopedHandler也不例外,不过它是一个定制化的责任链处理器,他会先从链顶端节点开始执行每个节点的前置准备工作(doScope),之后再回到链顶端,开始执行逐个节点真正的处理方法(doHandle)

二、应用场景

假设有ServletContextHandler、SessionHandler、ServletHandler 3个类型都是ScopedHandler,在启动的时候我们可以将ServletContextHandler作为第一个执行的节点,SessionHandler作为第二个执行的节点,ServletHandler作为第三个执行节点,它们分别会执行各自的doScope准备数据,之后挨个执行doHandle完成执行的处理,这样就能完成一个链式处理。特别要注意的是doHandle的触发通常是doScope里面,而不是直接就被调用。个人觉得Jetty这个链还是比较晦涩,特别是用HandlerWrapper的特性绑定一个handler到内部,然后用容器托管,完成链的构建(参考ServletContextHandler的doStart方法),有点重

三、继承体系

ScopedHandler组件继承体系

我们可以从继承体系看到ScopedHandler实际就是一个HandlerWrapper,子类有SessionHandler、ContextHandler、ServletHandler,同时它的类标记为abstract,所以可以看出ScopeHandler是一个半成品

四、源码剖析

ScopedHandler类声明及字段

ScopedHandler用一个静态变量__outScope,类型为ThreadLocal,保存每个线程对应的顶端链节点。_outScope表示当前链的顶端链节点,_nextScope表示当前节点的下一个节点

ScopedHandler的doStart方法实现

doStart:设置当前节点的顶级节点_outScope,然后调用父类的doStart,完成容器中孩子的启动,之后从当前handler的孩子里面查找ScopedHandler,将第一个孩子(注意getChildHandlerByClass其实是拿当前容器里面所有ScopedHandler类型的对象,通常第一个孩子肯定是我们前面设置的handler)设置为_nextScope。finally里面判断如果是顶端节点,则将该线程绑定的顶端节点设置回null,防止后续线程复用的情况出现错误的顶端链

ScopedHandler的handle方法实现

handle:处理方法,如果当前节点没有外层节点,则执行doScope,如果有则执行doHandle,该方法会触发链顶端节点的的doScope,然后挨个doScope完成后,在该方法里面回到顶端节点,执行其doHandle方法,再接着挨个节点doHandle直至最终完成调用

ScopedHandler的doScope方法实现

doScope:实现一个模板方法,调用nextScope完成下一节点处理路由

ScopedHandler的doHandle方法实现

doHandle:抽象方法,让子类自行实现

ScopedHandler的nextScope方法实现

nextScope:
如果下一节点不为空,则执行下一个节点的doScope方法;
如果下一节点为空但上一节点不为空,则执行上一节点的doHandle(这里就引导回顶端链节点了);
如果上一节点和下一节点均为空,则执行doHandle方法(这种情况就只有一个节点,只需执行自己的doHandle即可)

ScopedHandler的nextHandle方法实现

nextHandle:如果下一节点不为空,同时当前节点是当前处理器,则执行下一个节点的doHandle方法;否则如果当前执行器不为空,则执行父类HandlerWrapper的处理方法。这里第一个分支_nextScope != null && _nextScope != _handler的场景是,假设A、B、C均为ScopedHandler,但X不是ScopedHandler,形成了一个A、B、X、C的链,由于前期我们的A、B、C会形成以下关系:
A._outScope = null
A._nextScope = B
B._outScope = A
B._nextScope = C
X由于不是ScopedHandler,因此不会存在_outScope和_nextScope属性
C._outScope = A
C._nextScope = null

当A.handle时,会触发A.doScope,同时A的nextScope不是null,因此继续B.doScope,B的nextScope也不是null,因此执行C.doScope;此时C.nextScope是null,但outScope不是null,因此执行A.doHandle,由于A.nextScope不是null并且A.handler = B,所以执行B.doHandle;由于B.nextScope不是null,但B.nextScope是C,并不是之前设置的X,因此会直接执行HandlerWrapper的handle方法,这时会执行X.handle,X执行完成后,会执行自己的handler,也就是C,于是C.handle,由于C是ScopedHandler,同时C的outScope不是null,因此直接进入doHandle,C完成执行后发现nextScope为null,因此停止执行,这样其实就构建了ScopedHandler的注释里面提到的A、B、X、C链的处理逻辑,

即:A.handle -> A.doScope -> B.doScope -> C.doScope -> A.doHandle -> B.doHandle -> X.handle -> C.handle -> C.doHandle

五、总结

ScopedHandler作为Jetty生态中Handler组件的关键成员,用一个handle方法完成整条链的节点的顺序前置准备(doScope)和各节点的顺序执行(doHandle),也算是Jetty特色下的设计思路。通常一个应用会使用WebAppContext(实际就是ServletContextHandler的扩展)作为主Handler,该Handler会同时开启SessionHandler、SecurityHandler、ServletHandler,并会构建一个执行链,通过这个链会最终调用到我们的业务Servlet(在Spring MVC里面其实就是调用到了我们的DispatcherServlet)。后续会重点讲解SessionHandler、ServletHandler,我会带领大家探索Session管理以及Filter链及Servlet的执行

博客已迁移至 http://www.ph0ly.com 欢迎大家访问新的网站,文章更加齐全~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容

  • 专业考题类型管理运行工作负责人一般作业考题内容选项A选项B选项C选项D选项E选项F正确答案 变电单选GYSZ本规程...
    小白兔去钓鱼阅读 8,981评论 0 13
  • 面试必背 会舍弃、总结概括——根据我这些年面试和看面试题搜集过来的知识点汇总而来 建议根据我的写的面试应对思路中的...
    luoyangzk阅读 6,747评论 6 173
  • 1.地埋变的铝件加工问题 2..梯形丝杆两端尺寸公差问题 今天工作出现上面二个问题 产生原因: 为什么铝件加工赶不...
    cxw002515阅读 156评论 0 0
  • 剪短长发,偷藏流年之香眉眼带笑,韵一汪秋水金桂俏然满枝头清风漫香浓 秋雨醉把背影陌何需再转身一圈涟漪漾波心回眸为哪...
    浅浅是水阅读 2,409评论 59 63
  • 你可曾想过母亲 也曾是一个懵懂的小女孩 儿时的她 也曾采一朵田野里的野菊花插在发间 也曾叠一个纸船轻轻放进清澈小河...
    净意19阅读 1,407评论 0 0