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();
}
abstracthandler繼承自aggregatelifecycle并實作了handler接口,是基本上所有handler的基類。它的實作也非常簡單,它定義了server成員,并實作了getserver和setserver方法,在setserver實作中,如果已存在的server引用和新設定的server不同,則先将自身從已存在的server的container中移除,然後将自身添加到新的server的container中,并更新内部對server的引用執行個體。在destroy方法中,也會将自身從server引用執行個體的container中移除。
defaulthandler直接繼承自abstracthandler,它可以用于handler連結清單的末尾handler,用于處理所有不能被其他handler處理的請求:/favicon.ico -> 顯示jetty圖示,/ -> 顯示404錯誤頁面,并列出所有可用的contextpath,任何其他請求顯示404錯誤頁面。圖示的顯示和可用contextpath的清單顯示都是可配的。
dumphandler直接繼承自abstracthandler,用于測試和調試,顯示request消息内容。它顯示的資訊有pathinfo、contenttype、characterencoding、requestline、headers、parameters、cookiename、cookies、attributes、content等。
errorhandler直接繼承自abstracthandler,用于處理錯誤頁面,使用contexthandler.seterrorhandler()或server.addbean()注冊。它顯示出錯代碼、原因以及更詳細的資訊。其中異常棧從request的javax.servlet.errro.exception中擷取。
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直接繼承自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中。
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繼承自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的引用。
它繼承自handlercollection,隻是重寫了handle()方法的邏輯,即在handlerlist中,它周遊整個handlers 數組直到有異常發生或baserequest的ishandled()傳回true(什麼時候baserequest的handled屬性會被設定為true呢?在發送請求之前或相應狀态碼被設定);而handlercollection則會周遊整個handlers數組直到一個runtimeexception發生或ioexception發生或整個handler數組周遊完成,如果中途有出現其他異常最後統一抛出。
contexthandlercollection繼承自handlercollection,使用pathmap存儲請求uri到contexthandler的映射。
hotswaphandler繼承自abstracthandlercontainer,支援動态的替換内部的handler(即在設定handler時,如果目前handler已經啟動,則并立即啟動新設定的handler,并停止原來的handler)。它使用composite模式,内部隻是使用一個handler來儲存一個集合的handler,因而如果要注冊多個handler,則這個handler的類型需要handlercontainer。
handlerwrapper繼承自abstracthandlercontainer,它類似composite模式,使用一個handler本身來表達一個handlercontainer,因而同hotswaphandler,它隻是包含一個handler字段用與表示、存儲handler集合,并且其實作也和hotswaphandler類似,所不同的是它不會動态的啟動新設定的handler,即它隻是一個handler的wrapper。
connecthandler繼承自handlerwrapper,它實作了一個代理伺服器。
debughandler繼承自handlerwrapper,用于測試時使用,在logs 目錄中yyyy_mm_dd.debug.log檔案的形式紀錄請求的時間和url以及響應的時間和響應狀态碼,并設定線程名為請求url。
ipaccesshandler繼承自handlerwrapper,用于添加可以使用或需要組織的ip清單,并傳回403 forbidden響應。
requestloghandler繼承自handlerwrapper,在所有handler處理結束後,将request和response使用requestlog類列印到日志中。
statisticshandler繼承自handlerwrapper,用于紀錄一些統計資訊,如請求數、請求時間、dispatched數與時間、suspended數、resume數、expire數、1xx到5xx的響應數、響應總的位元組數等。