上善若水
          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

          Handler概述

          Handler是Jetty中的核心接口,它用于處理所有連接以外的邏輯,比如對Servlet框架的實現,以及用戶自定義的Handler等,它繼承自LifeCycle和Destroyable接口,只有一個主要方法:handle,包含Request和Response實例。在深入Jetty源碼之Connection中有寫道在HttpConnection的handleRequest()方法中會最終調用Server的handle()或handleAsync()方法,并且傳入HttpConnection自身作為參數以處理后續邏輯,在這里Server作為Handler的容器,在Server中以HttpConnection為參數的handle()和handleAsync()方法中,會調用向這個Handler容器中注冊的所有Handler的handle()方法。即在使用Jetty時,我們首先要向Server注冊相應的Handler實例。

          Handler接口定義

          Handler的接口定義如下:
          public interface Handler extends LifeCycle, Destroyable {
              // 處理一個HTTP請求,并最終將響應寫入Response中。不同的實現有不同的功能和邏輯,如WebAppContext實現一個Servlet容器,
              
          // 而ErrorHandler則向Response中寫入一個包含錯誤碼和原因的HTML頁面。
              
          // 關于參數:
              
          // target表示Request的目標,它可以時一個URI或一個名字。即Request中的pathInfo字段。
              
          // baseRequest表示在HttpConnection中創建并解析的最初的Request,它沒有被包裝。
              
          // request表示一個HttpServletRequest,它可以同baseRequest相同的實例,也可以是一個經過包裝后的HttpServletRequest。
              
          // response表示一個HttpServletResponse,它可以是經過包裝的HttpServletResponse或在HttpConnection創建的最原始的HttpServletResponse。
              public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
                  throws IOException, ServletException;
              
              public void setServer(Server server);
              public Server getServer();
              
              public void destroy();
          }

          Handler類圖


          AbstractHandler

          AbstractHandler繼承自AggregateLifeCycle并實現了Handler接口,是基本上所有Handler的基類。它的實現也非常簡單,它定義了Server成員,并實現了getServer和setServer方法,在setServer實現中,如果已存在的Server引用和新設置的Server不同,則先將自身從已存在的Server的Container中移除,然后將自身添加到新的Server的Container中,并更新內部對Server的引用實例。在destroy方法中,也會將自身從Server引用實例的Container中移除。

          DefaultHandler

          DefaultHandler直接繼承自AbstractHandler,它可以用于Handler鏈表的末尾Handler,用于處理所有不能被其他Handler處理的請求:/favicon.ico -> 顯示jetty圖標,/ -> 顯示404錯誤頁面,并列出所有可用的ContextPath,任何其他請求顯示404錯誤頁面。圖標的顯示和可用ContextPath的列表顯示都是可配的。

          DumpHandler

          DumpHandler直接繼承自AbstractHandler,用于測試和調試,顯示Request消息內容。它顯示的信息有PathInfo、ContentType、CharacterEncoding、RequestLine、Headers、Parameters、CookieName、Cookies、Attributes、Content等。

          ErrorHandler

          ErrorHandler直接繼承自AbstractHandler,用于處理錯誤頁面,使用ContextHandler.setErrorHandler()或Server.addBean()注冊。它顯示出錯代碼、原因以及更詳細的信息。其中異常棧從Request的javax.servlet.errro.exception中獲取。

          ErrorPageErrorHandler

          ErrorPageErrorHandler繼承自ErrorHandler,它可以配置不同的Exception和Response Status Code到不同的頁面。Exception類型從Request中的javax.servlet.error.exception_type或javax.servlet.error.exception屬性中獲取,Response Status Code從Request中的javax.servlet.error.status_code屬性中獲取。使用Exception類型、Response Status Code、Response Status Code Range從_errorPages中查找在web.xml文件中注冊的映射,如果有找到,則使用ServletContext中的RequestDispatcher將當前的Request、Response派發的其error處理邏輯;否則使用ErrorHandler中的邏輯。

          ResourceHandler

          ResourceHandler直接繼承自AbstractHandler,用于處理靜態資源以及If-Modified-Since頭。使用PathInfo以及注冊的或ContextHandler中的BaseResource作為Base查找Resource,如果找不到并且請求的類型是/jetty-stylesheet.css資源,則查找注冊的或默認的stylesheet資源;如果查找到的資源是目錄,如果URL不是以"/"結尾,則重定向到"URL/",否則查找是否有welcome list中配置的頁面存在以顯示,否則列出文件列表或者顯示403 Forbidden頁面;對If-Modified-Since請求頭,如果資源存在LastModified屬性,并且比請求中設置的值要小或相等(以秒為單位),返回304 Not Modified;根據文件名或PathInfo以及注冊的MineTypes信息設置ContentType,設置Content-Length、Cache-Control、Last-Modified等響應頭,將Resource內容寫入Response中。

          順便提及:Resource是Jetty中對靜態資源的抽象,其子類有URLResource、FileResource、JarResource、JarFileResource、BadResource等。類似Spring中對Resource抽象,不詳述。

          AbstractHandlerContainer

          AbstractHandlerContainer繼承自AbstractHandler,并實現了HandlerContainer接口。HandlerContainer接口定義如下:
          public interface HandlerContainer extends LifeCycle {
              // 返回當前Handler包含的所有Handler
              public Handler[] getHandlers();
              // 返回當前Handler和其所有子Handler包含的所有Handler
              public Handler[] getChildHandlers();
              // 返回所有當前Handler和其所有子Handler包含的所有Handler中類型為指定類型的Handler
              public Handler[] getChildHandlersByClass(Class<?> byclass);
              // 返回第一個所有當前Handler和其所有子Handler包含的所有Handler中類型為指定類型的Handler
              public <T extends Handler> T getChildHandlerByClass(Class<T> byclass);
          }
          AbstractHandlerContainer主要實現了兩個方法:
          // 將所有當前handler或其子handler中類型為byClass的Handler添加到list中,并返回該list實例
          protected Object expandHandler(Handler handler, Object list, Class<Handler> byClass);
          // 從root的HandlerContainer中找到handler所在的HandlerContainer實例,并且該HandlerContainer必須屬于type類型
          public static <T extends HandlerContainer> T findContainerOf(HandlerContainer root,Class<T>type, Handler handler);

          HandlerCollection

          HandlerCollection繼承自AbstractHandlerContainer,它使用Handler數組作為容器來存儲Handler,并且可已配置是否在啟動后還能修改這個容器,以及啟動是是否并行啟動:
              private final boolean _mutableWhenRunning;
              private volatile Handler[] _handlers;
              private boolean _parallelStart=false
          在handle()方法實現中,遍歷數組中所有的Handler,調用其handle()方法。
          在setHandlers()和setServer()方法實現中,需要生成并分發handler的Relationship發生變化的事件給在Server中的Container中注冊的Listener,以及更新相應Handler中對Server的引用。

          HandlerList

          它繼承自HandlerCollection,只是重寫了handle()方法的邏輯,即在HandlerList中,它遍歷整個Handlers 數組直到有異常發生或baseRequest的isHandled()返回true(什么時候baseRequest的handled屬性會被設置為true呢?在發送請求之前或相應狀態碼被設置);而HandlerCollection則會遍歷整個Handlers數組直到一個RuntimeException發生或IOException發生或整個Handler數組遍歷完成,如果中途有出現其他異常最后統一拋出。

          ContextHandlerCollection

          ContextHandlerCollection繼承自HandlerCollection,使用PathMap存儲請求URI到ContextHandler的映射。

          HotSwapHandler

          HotSwapHandler繼承自AbstractHandlerContainer,支持動態的替換內部的Handler(即在設置Handler時,如果當前Handler已經啟動,則并立即啟動新設置的Handler,并停止原來的Handler)。它使用Composite模式,內部只是使用一個Handler來保存一個集合的Handler,因而如果要注冊多個Handler,則這個Handler的類型需要HandlerContainer。

          HandlerWrapper

          HandlerWrapper繼承自AbstractHandlerContainer,它類似Composite模式,使用一個Handler本身來表達一個HandlerContainer,因而同HotSwapHandler,它只是包含一個Handler字段用與表示、存儲Handler集合,并且其實現也和HotSwapHandler類似,所不同的是它不會動態的啟動新設置的Handler,即它只是一個Handler的Wrapper。

          ConnectHandler

          ConnectHandler繼承自HandlerWrapper,它實現了一個代理服務器。

          DebugHandler

          DebugHandler繼承自HandlerWrapper,用于測試時使用,在logs 目錄中yyyy_mm_dd.debug.log文件的形式紀錄請求的時間和URL以及響應的時間和響應狀態碼,并設置線程名為請求URL。

          IPAccessHandler

          IPAccessHandler繼承自HandlerWrapper,用于添加可以使用或需要組織的IP列表,并返回403 Forbidden響應。

          RequestLogHandler

          RequestLogHandler繼承自HandlerWrapper,在所有handler處理結束后,將Request和Response使用RequestLog類打印到日志中。

          StatisticsHandler

          StatisticsHandler繼承自HandlerWrapper,用于紀錄一些統計信息,如請求數、請求時間、dispatched數與時間、suspended數、resume數、expire數、1xx到5xx的響應數、響應總的字節數等。
          posted on 2014-05-06 22:56 DLevin 閱讀(4061) 評論(1)  編輯  收藏 所屬分類: Jetty

          FeedBack:
          # re: 深入Jetty源碼之Handler總述
          2014-05-07 19:04 | 天津麻辣燙
          確實不容易總結哦  回復  更多評論
            
          主站蜘蛛池模板: 姚安县| 赞皇县| 韶关市| 府谷县| 东阳市| 甘德县| 竹山县| 罗甸县| 温泉县| 太谷县| 衡阳市| 澄迈县| 自治县| 榆中县| 平凉市| 屏东市| 德令哈市| 天津市| 铜鼓县| 乐亭县| 景宁| 溆浦县| 珠海市| 林口县| 长岭县| 隆尧县| 玉田县| 烟台市| 东乡族自治县| 墨竹工卡县| 雷山县| 潢川县| 五峰| 喀喇沁旗| 镇雄县| 酒泉市| 长治市| 岗巴县| 定州市| 报价| 昌江|