上善若水
          In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
          posts - 146,comments - 147,trackbacks - 0

          概述

          在很多框架的設(shè)計(jì)中,都有類(lèi)似Channel鏈的設(shè)計(jì),類(lèi)似Decorator模式或Chain Of Responsibility模式,可以向這個(gè)Channel注冊(cè)不同的Handler,用戶(hù)請(qǐng)求可以穿越這個(gè)由多個(gè)Handler組成的Channel,執(zhí)行響應(yīng)的切面邏輯,在最后一個(gè)Handler或者另一個(gè)Processor處理用于自定義的業(yè)務(wù)邏輯,然后生成的響應(yīng)可以逆著方向從這個(gè)Channel回來(lái)。Structs2中的Interceptor、Servlet中Filter都采用這種設(shè)計(jì)。這種設(shè)計(jì)為面向切面編程提供了遍歷,然而目前的Handler設(shè)計(jì)更多的像是Chain Of Responsibility模式,它的處理邏輯只能從鏈頭走到鏈尾,而沒(méi)有返回的路程。引入ScopedHandler的目的就是用于解決這個(gè)問(wèn)題。

          實(shí)現(xiàn)

          Structs2中Interceptor實(shí)現(xiàn)使用傳入ActionInvaction來(lái)調(diào)用Channel中的后繼Interceptor:
          public class MyInterceptor extends AbstractInterceptor {
              @Override
               public String intercept(ActionInvocation ai) throws Exception {
                  try {
                       // Add user customized logic here when request come into the channel
                       return ai.invoke();
                  } finally {
                       // Add user customized logic here when response pass out across the channel
                  }        
              } 
          }
          類(lèi)似的,Servlet中的Filter實(shí)現(xiàn)也是使用FilterChain來(lái)調(diào)用Channel中后繼的Filter:
          public class MyFilter implements Filter {
              @Override
              public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
                  try {
                      // Add user customized logic here when request come into the channel
                      chain.doFilter(request, response);
                  } finally {
                      // Add user customized logic here when response pass out across the channel
                  }
              }
          }

          ScopedHandler采用了不同的實(shí)現(xiàn)方式,首先它繼承自HandlerWrapper,因而它使用HandlerWrapper中的Handler字段來(lái)構(gòu)建Handler鏈,然而并不是所有的Handler都是ScopedHandler,因而ScopedHandler內(nèi)部還定義了_nextScope字段用于創(chuàng)建在這條Handler鏈表中的ScopedHandler鏈表,以及_outerScope字段用于將自己始終和這個(gè)ScopedHandler鏈表中的最外層ScopedHandler相連,對(duì)這個(gè)ScopedHandler的最外層列表,其_outScope字段為null。而ScopedHandler要實(shí)現(xiàn)的行為是,假設(shè)A、B、C都是ScopedHandler,并且它們組成鏈表:A->B->C,那么當(dāng)調(diào)用A.handle()方法時(shí)的調(diào)用堆棧是:
          A.handle()
          |-A.doScope()
          |--B.doScope()
          |----C.doScope()
          |-----A.doHandle()
          |------B.doHandle()
          |-------C.doHandle()
          而如果A、B是ScopedHandler,X、Y是其他的Handler,并且它們組成鏈表:A->X->B->Y,那么當(dāng)調(diào)用A.handle()方法時(shí)的調(diào)用棧是:
          A.handle()
          |-A.doScope()
          |--B.doScope()
          |---A.doHandle()
          |----X.handle()
          |-----B.doHandle()
          |------Y.handle()

          這種行為主要用于Servlet框架的實(shí)現(xiàn),它可以保證在doScope()方法中做一些初始化工作,并且配置環(huán)境,而在后繼調(diào)用中都可以使用這些配置好的環(huán)境,并且doHandle()的順序還是使用原來(lái)定義的Handler鏈表順序,即使有些Handler并不是ScopedHandler。

          在實(shí)現(xiàn)中,其Handler鏈表由HandlerWrapper構(gòu)建,在doStart()方法中計(jì)算_nextScope字段以及_outerScope字段,在handle()方法中,如果_outerScope為null,則調(diào)用doScope()方法,否則調(diào)用doHandle()方法:
              @Override
              public final void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
              {
                  if (_outerScope==null)  
                      doScope(target,baseRequest,request, response);
                  else 
                      doHandle(target,baseRequest,request, response);
              }
          在執(zhí)行完doScope()方法后,調(diào)用nextScope()方法,該方法順著_nextScope鏈表走,直到盡頭,后調(diào)用doHandle()方法:
              public final void nextScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
              {
                  if (_nextScope!=null)
                      _nextScope.doScope(target,baseRequest,request, response);
                  else if (_outerScope!=null)
                      _outerScope.doHandle(target,baseRequest,request, response);
                  else 
                      doHandle(target,baseRequest,request, response);
              }
          而doHandle()方法在完成是調(diào)用nextHandle()方法,它也沿著_nextScope鏈表走,只要_nextScope和_handler相同,則調(diào)用其doHandle()方法,但是如果_nextScope和_handler不同,則調(diào)用_handler中的handle()方法,用于處理在ScopedHandler鏈表中插入非ScopedHandler的情況:
              public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
              {
                  if (_nextScope!=null && _nextScope==_handler)
                      _nextScope.doHandle(target,baseRequest,request, response);
                  else if (_handler!=null)
                      _handler.handle(target,baseRequest, request, response);
              }

          使用

          在ScopedHandler的測(cè)試用例中給出了一個(gè)非常好的例子。首先有一個(gè)TestHandler繼承自ScopedHandler:
              private class TestHandler extends ScopedHandler {
                  private final String _name;

                  private TestHandler(String name) {
                      _name=name;
                  }

                  @Override
                  public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
                      try {
                          _history.append(">S").append(_name);
                          super.nextScope(target,baseRequest,request, response);
                      } finally {
                          _history.append("<S").append(_name);
                      }
                  }

                  @Override
                  public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
                      try {
                          _history.append(">W").append(_name);
                          super.nextHandle(target,baseRequest,request,response);
                      } finally {
                          _history.append("<W").append(_name);
                      }
                  }
              }
          然后有非ScopedHandler的實(shí)現(xiàn):
              private class OtherHandler extends HandlerWrapper {
                  private final String _name;

                  private OtherHandler(String name) {
                      _name=name;
                  }

                  @Override
                  public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
                      try {
                          _history.append(">H").append(_name);
                          super.handle(target,baseRequest,request, response);
                      } finally {
                          _history.append("<H").append(_name);
                      }
                  }
              }
          查看一下Test Case的執(zhí)行結(jié)果:
              @Test
              public void testDouble() throws Exception
              {
                  TestHandler handler0 = new TestHandler("0");
                  OtherHandler handlerA = new OtherHandler("A");
                  TestHandler handler1 = new TestHandler("1");
                  OtherHandler handlerB = new OtherHandler("B");
                  handler0.setHandler(handlerA);
                  handlerA.setHandler(handler1);
                  handler1.setHandler(handlerB);
                  handler0.start();
                  handler0.handle("target",null,null,null);
                  handler0.stop();
                  String history=_history.toString();
                  System.err.println(history);
                  assertEquals(">S0>S1>W0>HA>W1>HB<HB<W1<HA<W0<S1<S0",history);
              }
          posted on 2014-05-07 23:49 DLevin 閱讀(1436) 評(píng)論(3)  編輯  收藏 所屬分類(lèi): Jetty

          FeedBack:
          # re: 深入Jetty源碼之ScopedHandler
          2014-05-08 08:25 | 金利鎖業(yè)
          支持博主分享啊  回復(fù)  更多評(píng)論
            
          # re: 深入Jetty源碼之ScopedHandler
          2014-05-08 08:52 | regale
          請(qǐng)問(wèn)_history是怎么傳進(jìn)去的?  回復(fù)  更多評(píng)論
            
          # re: 深入Jetty源碼之ScopedHandler
          2014-05-08 09:17 | DLevin
          代碼沒(méi)有貼全,TestHandler和OtherHandler都是Test類(lèi)中的內(nèi)部類(lèi),而_history是Test類(lèi)的成員@regale
            回復(fù)  更多評(píng)論
            
          主站蜘蛛池模板: 东平县| 桂林市| 云阳县| 台东市| 渭南市| 乐至县| 读书| 开阳县| 伊宁市| 南和县| 德化县| 长岛县| 明溪县| 大方县| 汝城县| 南华县| 加查县| 深圳市| 四川省| 平阴县| 甘南县| 南丰县| 扎赉特旗| 武安市| 山阳县| 九江县| 克拉玛依市| 衡东县| 四平市| 西吉县| 宁津县| 林芝县| 汤原县| 荔浦县| 和静县| 达拉特旗| 龙岩市| 郧西县| 贵港市| 横山县| 高陵县|