概述
Servlet是Server Applet的縮寫,即在服務(wù)器端運(yùn)行的小程序,而Servlet框架則是對(duì)HTTP服務(wù)器(Servlet Container)和用戶小程序中間層的標(biāo)準(zhǔn)化和抽象。這一層抽象隔離了HTTP服務(wù)器的實(shí)現(xiàn)細(xì)節(jié),而Servlet規(guī)范定義了各個(gè)類的行為,從而保證了這些“服務(wù)器端運(yùn)行的小程序”對(duì)服務(wù)器實(shí)現(xiàn)的無關(guān)性(即提升了其可移植性)。
在Servlet規(guī)范有以下幾個(gè)核心類(接口):
ServletContext:定義了一些可以和Servlet Container交互的方法。
Registration:實(shí)現(xiàn)Filter和Servlet的動(dòng)態(tài)注冊(cè)。
ServletRequest(HttpServletRequest):對(duì)HTTP請(qǐng)求消息的封裝。
ServletResponse(HttpServletResponse):對(duì)HTTP響應(yīng)消息的封裝。
RequestDispatcher:將當(dāng)前請(qǐng)求分發(fā)給另一個(gè)URL,甚至ServletContext以實(shí)現(xiàn)進(jìn)一步的處理。
Servlet(HttpServlet):所有“服務(wù)器小程序”要實(shí)現(xiàn)了接口,這些“服務(wù)器小程序”重寫doGet、doPost、doPut、doHead、doDelete、doOption、doTrace等方法(HttpServlet)以實(shí)現(xiàn)響應(yīng)請(qǐng)求的相關(guān)邏輯。
Filter(FilterChain):在進(jìn)入Servlet前以及出Servlet以后添加一些用戶自定義的邏輯,以實(shí)現(xiàn)一些橫切面相關(guān)的功能,如用戶驗(yàn)證、日志打印等功能。
AsyncContext:實(shí)現(xiàn)異步請(qǐng)求處理。
Jetty中的Holder
在Jetty中,每個(gè)Servlet和其相關(guān)信息都由ServletHolder封裝,并且將Servlet相關(guān)操作代理給ServletHolder;同理,對(duì)Filter也有FilterHolder與其相對(duì)應(yīng);另外ServletHolder和FilterHolder都繼承自Holder實(shí)例。在Servlet 3.0中引入動(dòng)態(tài)向ServletContext注冊(cè)Servlet和Filter,并返回相應(yīng)的Registration實(shí)例,用于進(jìn)一步配置與其關(guān)聯(lián)的Servlet和Filter,因而Registration也是和ServletHolde和FilterHolder相關(guān)聯(lián)的接口。在Jetty中,他們的類關(guān)系圖如下:
Servlet
Servlet和Filter是Servlet規(guī)范中用于定義用戶邏輯實(shí)現(xiàn)的接口,Servlet是最初的版本,所有的“服務(wù)器端小程序”都要實(shí)現(xiàn)該接口,并交由Servlet Container管理其實(shí)例,負(fù)責(zé)其生命周期,以及當(dāng)相應(yīng)請(qǐng)求到來時(shí)調(diào)用相應(yīng)方法。Servlet接口非常簡(jiǎn)單:
public interface Servlet {
// Servlet Container在創(chuàng)建一個(gè)Servlet后調(diào)用該方法,并傳入ServletConfig實(shí)例,從而用戶可以在這個(gè)方法中做一些自定義的初始化工作,如初始化數(shù)據(jù)庫連接等。
// 并且Servlet Container可以保證一個(gè)Servlet實(shí)例init方法之后被調(diào)用一次,但是對(duì)一個(gè)Servlet類init方法可能會(huì)被多次調(diào)用,因而有些Servlet Container可能會(huì)在某些情況下將某些
// Servlet移出Servlet Container,而后又重新加載這些Servlet,如為了在處理Servlet Container資源壓力比較大的情況下。
public void init(ServletConfig config) throws ServletException;
// 返回在init方法中傳入的ServletConfig實(shí)例。ServletConfig包含了在web.xml配置文件中配置當(dāng)前Servlet的初始化參數(shù),并且可以使用該ServletConfig實(shí)例獲取當(dāng)前ServletContext實(shí)例。
public ServletConfig getServletConfig();
// 當(dāng)該Servlet對(duì)應(yīng)的請(qǐng)求到來時(shí),Servlet Container會(huì)調(diào)用這個(gè)Servlet的service方法,用于處理請(qǐng)求,并將相應(yīng)寫入ServletResponse參數(shù)中,該方法只能在init方法完成后被調(diào)用。
// 在service方法中,可以選擇使用ServletResponse定義的方法返回響應(yīng)給客戶端,或只是向ServletResponse中寫入響應(yīng),最終由Servlet Container根據(jù)ServletResponse的信息將響應(yīng)返回給客戶端。
// 很多情況下,Servlet Container都不會(huì)使用多線程來處理客戶請(qǐng)求,應(yīng)該該方法會(huì)在多線程環(huán)境下被使用,Servlet實(shí)現(xiàn)者可以實(shí)現(xiàn)SingleThreadMode接口以強(qiáng)制該方法只在單線程的環(huán)境下被使用。
// 但是SingleThreadMode接口已經(jīng)在Servlet 2.3中被廢棄,實(shí)現(xiàn)該接口也會(huì)影響Servlet的執(zhí)行性能,而且有些Servlet Container會(huì)選擇實(shí)例或多個(gè)Servlet實(shí)例,以保證對(duì)請(qǐng)求的響應(yīng)性能,因而此時(shí)依然不能保證該方法的單線程特性,因而不建議使用這個(gè)SingleThreadMode接口。
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
// 返回當(dāng)前Servlet的描述信息,如作者、版本號(hào)、版權(quán)等。在GenericServlet默認(rèn)實(shí)現(xiàn)中,返回空字符串。
public String getServletInfo();
// 當(dāng)Servlet Container銷毀當(dāng)前Servlet時(shí)會(huì)調(diào)用該方法,從而給Servlet提供擁有清理當(dāng)前Servlet占用的資源的地方,如關(guān)閉和數(shù)據(jù)庫的連接等。
// Servlet Container會(huì)保證該方法在所有執(zhí)行service方法的線程完成或超時(shí)后被調(diào)用。Servlet Container一般會(huì)在三種情況下會(huì)調(diào)用該方法:
// 1. Servlet Container當(dāng)前資源比較緊張,需要將一些不再用或不常用的Servlet移出;2. 實(shí)現(xiàn)某些Servlet的熱部署;3. 當(dāng)前Web Application被停止。
public void destroy();
}
對(duì)每個(gè)Servlet都有一個(gè)ServletConfig實(shí)例和其對(duì)應(yīng),ServletConfig中包含了在web.xml文件中定義的Servlet的init-param參數(shù),并且可以使用ServletConfig實(shí)例獲取ServletContext實(shí)例:
public interface ServletConfig {
// 返回該ServletConfig對(duì)應(yīng)的Servlet的名稱,在web.xml文件中定義的Servlet名稱或?qū)τ跊]有注冊(cè)的Servlet為其類名。
public String getServletName();
// 返回和其關(guān)聯(lián)的ServletContext。
public ServletContext getServletContext();
// 返回在web.xml配置文件中定義或者使用ServletRegistration動(dòng)態(tài)定義添加的init-param參數(shù)。
public String getInitParameter(String name);
public Enumeration<String> getInitParameterNames();
}
在Jetty中,不管是在web.xml中配置的Servlet還是使用ServletContext動(dòng)態(tài)注冊(cè)并使用ServletRegistration.Dynamic動(dòng)態(tài)配置的Servlet,在ServletHandler內(nèi)部都使用ServletHolder來表示一個(gè)Servlet,并且由ServletHolder來處理所有和Servlet相關(guān)的邏輯。ServletHolder的實(shí)現(xiàn)邏輯在之后給出。
Servlet框架中默認(rèn)實(shí)現(xiàn)了兩個(gè)Servlet:GenericServlet和HttpServlet,GenericServlet只是對(duì)Servlet的簡(jiǎn)單實(shí)現(xiàn),而HttpServlet會(huì)根據(jù)請(qǐng)求中的方法將請(qǐng)求分發(fā)給相應(yīng)的:doGet/doPost/doPut/doHead/doOptions/doTrace等方法,它還提供了getLastModified()方法,重寫該方法用于實(shí)現(xiàn)條件GET。以上這些方法(除doOptions和doTrace已經(jīng)有具體的邏輯實(shí)現(xiàn))默認(rèn)實(shí)現(xiàn)直接方法405 Method Not Allowed響應(yīng)(Http/1.1)或404 Bad Request響應(yīng)(HTTP/1.0)。重寫相應(yīng)的方法以實(shí)現(xiàn)各個(gè)Method對(duì)應(yīng)的邏輯。
Filter
在Servlet 2.3開始引入了Filter機(jī)制,以在Servlet的service方法的執(zhí)行前后添加一些公共的Filter邏輯,為面向切面的編程提供了很大的便利,這些公共的邏輯如紀(jì)錄一個(gè)Request從進(jìn)入Servlet Container到出所花費(fèi)的總時(shí)間、為每個(gè)Request添加一些額外的信息以幫助之后處理、對(duì)所有或特定Request添加用戶驗(yàn)證功能等。Filter可以在web.xml文件中定義,由Servlet Container負(fù)責(zé)其實(shí)例化、初始化以及doFilter方法的調(diào)用。在Servlet 3.0以后,還支持動(dòng)態(tài)的給ServletContext注冊(cè)Filter,并由返回的FilterRegistration.Dynamic實(shí)例做進(jìn)一步的配置。Filter的接口定義也是比較簡(jiǎn)單:
public interface Filter {
// 由ServletContainer在初始化一個(gè)Filter時(shí)調(diào)用,F(xiàn)ilter的實(shí)現(xiàn)者可以在該方法中添加一些用戶自定義的初始化邏輯,同時(shí)可以保存FilterConfig實(shí)例,它可以獲取定義的init-param初始化參數(shù)以及獲取ServletContext實(shí)例。其他情況和Servlet類似,不贅述。
public void init(FilterConfig filterConfig) throws ServletException;
// 每一次請(qǐng)求到來都會(huì)穿越配置的FilterChain,執(zhí)行配置的Servlet,然后從這個(gè)FilterChain中返回。在doFilter方法的實(shí)現(xiàn)中,要調(diào)用下一個(gè)Filter,使用FilterChain的doFilter方法。
// 在調(diào)用FilterChain的doFilter之前為執(zhí)行請(qǐng)求之前的處理,而之后為請(qǐng)求已經(jīng)執(zhí)行完成,在響應(yīng)返回的路上的邏輯處理。也可以步調(diào)用FilterChain的doFilter方法,以阻止請(qǐng)求的進(jìn)一步處理。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
// 在Filter被移出Servlet Container時(shí)調(diào)用,它和Servlet類似,不贅述。**
public void destroy();
}
Filter接口中包含對(duì)FilterConfig以及FilterChain的使用,F(xiàn)ilterConfig和ServletConfig定義、實(shí)現(xiàn)以及邏輯都類似:
public interface FilterConfig {
public String getFilterName();
public ServletContext getServletContext();
public String getInitParameter(String name);
public Enumeration<String> getInitParameterNames();
}
FilterChain是Servlet中將Filter鏈以Channel的方式連接在一起的類,它實(shí)現(xiàn)了可以向執(zhí)行Servlet前和后都添加一些切面邏輯,甚至阻止Servlet的執(zhí)行,F(xiàn)ilter的實(shí)現(xiàn)者使用FilterChain的doFilter方法調(diào)用在這個(gè)鏈中的下一個(gè)Filter的doFilter方法,如果當(dāng)前Filter是鏈中最后一個(gè)Filter,則調(diào)用響應(yīng)的Servlet。其接口定義如下:
public interface FilterChain {
// 調(diào)用該方法會(huì)調(diào)用Filter鏈中的下一個(gè)Filter的doFilter方法,如果當(dāng)前Filter是這條鏈中的最后一個(gè)Filter,則該方法會(huì)調(diào)用響應(yīng)的Servlet的service方法。
public void doFilter (ServletRequest request, ServletResponse response) throws IOException, ServletException;
}
在Jetty中,ServletHandler的內(nèi)部類Chain實(shí)現(xiàn)了FilterChain接口,在構(gòu)造Chain實(shí)例時(shí),首先根據(jù)Request的URL以及對(duì)應(yīng)Servlet Name查找所有相關(guān)的Filter列表,然后使用這個(gè)Filter列表、Request實(shí)例、當(dāng)前請(qǐng)求對(duì)應(yīng)的ServletHolder創(chuàng)建這個(gè)鏈,在其doFilter方法實(shí)現(xiàn)中,它會(huì)存儲(chǔ)一個(gè)_filter索引,它指向下一個(gè)Filter實(shí)例,當(dāng)每個(gè)Filter調(diào)用doFilter方法時(shí),Chain會(huì)根據(jù)這個(gè)索引獲取下一個(gè)Filter實(shí)例,并將該索引向后移動(dòng),從而調(diào)用下一個(gè)Filter的doFilter方法,如果這個(gè)索引值到達(dá)最后一個(gè)Filter鏈中的Filter,且有ServletHolder實(shí)例存在,則調(diào)用該ServletHolder的handle方法,否則調(diào)用notFound方法,即向客戶端發(fā)送404 NOT FOUND響應(yīng)。如果Filter不支持ASYNC模式,則在調(diào)用其doFilter之前,需要將Request的ASYNC支持設(shè)置為false。
在ServletHandler中還有CachedChain實(shí)現(xiàn)了FilterChain接口,它以鏈表的形式紀(jì)錄找到的Filter列表,并將這個(gè)列表緩存在ServletHandler中,不同的dispatch類型有一個(gè)列表,并且可以根據(jù)請(qǐng)求的URL或請(qǐng)求的Servlet名來查找是否已經(jīng)有緩存的Filter鏈表。
在ServletHandler中,可以使用setFilterChainsCached方法來配置是否使用CachedChain還是直接使用Chain,默認(rèn)使用CachedChain。
Registration
Registration是Servlet 3.0規(guī)范中引入的接口,用于表示向ServletContext中動(dòng)態(tài)注冊(cè)的Servlet、Filter的實(shí)例,從而實(shí)現(xiàn)對(duì)這些動(dòng)態(tài)注冊(cè)的Servlet、Filter實(shí)例進(jìn)行進(jìn)一步的配置。 對(duì)于Servlet和Filter的配置,他們的共同點(diǎn)是他們有響應(yīng)的Name、ClassName、Init Parameters以及asyncSupported屬性,而這些方法正是Registration接口的定義。Registration接口將setAsyncSupport方法定義在其內(nèi)部的Dynamic接口中,Dynamic用于表示這是用于動(dòng)態(tài)的配置這個(gè)Servlet或Filter的含義,但是為什么要將這個(gè)方法放在Dynamic接口中呢?如何決定不同的方法應(yīng)該是在Registration本身的接口中,而那些應(yīng)該放到Dynamic接口中呢?
public interface Registration {
// 返回這個(gè)Registration實(shí)例關(guān)聯(lián)的Servlet或Filter的Name,這個(gè)Name在向ServletContext注冊(cè)Servlet或Filter時(shí)給定。
public String getName();
// 返回這個(gè)Registration實(shí)例關(guān)聯(lián)的Servlet或Filter的類名。
public String getClassName();
// 和這個(gè)Registration實(shí)例關(guān)聯(lián)的初始化參數(shù)的操作。
public boolean setInitParameter(String name, String value);
public String getInitParameter(String name);
public Set<String> setInitParameters(Map<String, String> initParameters);
public Map<String, String> getInitParameters();
interface Dynamic extends Registration {
// 配置Registration關(guān)聯(lián)的Servlet或Filter是否支持異步操作。
public void setAsyncSupported(boolean isAsyncSupported);
}
}
Registration有兩個(gè)子接口:ServletRegistration和FilterRegistration,分別用于表示Servlet相關(guān)的配置和Filter相關(guān)的配置。
對(duì)ServletRegistration,它可以設(shè)置Servlet的URL Mapping、RunAsRole屬性、LoadOnStartup屬性等:
public interface ServletRegistration extends Registration {
// 添加URL patterns到這個(gè)ServletRegistration關(guān)聯(lián)的Servlet的映射。如果有任意的URL patterns已經(jīng)映射到其他的Servlet中,則該方法不會(huì)執(zhí)行任何行為。
public Set<String> addMapping(String... urlPatterns);
// 獲取所有到當(dāng)前ServletRegistration對(duì)應(yīng)的Servlet的URL patterns。
public Collection<String> getMappings();
// 獲取當(dāng)前ServletRegistration對(duì)應(yīng)的Servlet的RunAsRole。
public String getRunAsRole();
interface Dynamic extends ServletRegistration, Registration.Dynamic {
// 設(shè)置當(dāng)前ServletRegistration對(duì)應(yīng)的Servlet的loadOnStartup等級(jí)。如果loadOnStartup大于或等于0,表示Servlet Container要優(yōu)先初始化該Servlet,
// 此時(shí)Servlet Container要在Container初始化時(shí)實(shí)例化并初始化該Servlet,即在所有注冊(cè)的ContextListener的contextInitialized方法調(diào)用完成后。
// 如果loadOnStartup小于0,則表示這個(gè)Servlet可以在用到的時(shí)候?qū)嵗⒊跏蓟DJ(rèn)值為-1。
public void setLoadOnStartup(int loadOnStartup);
// 設(shè)置ServletRegistration相關(guān)的ServletSecurityElement屬性。
public Set<String> setServletSecurity(ServletSecurityElement constraint);
// 設(shè)置ServletRegistration對(duì)應(yīng)的Servlet的MultipartConfigElement屬性。
public void setMultipartConfig(MultipartConfigElement multipartConfig);
// 設(shè)置ServletRegistration對(duì)應(yīng)的Servlet的RunAsRole屬性。
public void setRunAsRole(String roleName);
}
}
對(duì)FilterRegistration,它可以配置Filter的URL Mapping和Servlet Mapping等:
public interface FilterRegistration extends Registration {
// 添加FilterRegistration關(guān)聯(lián)的Filter到Servlet的映射,使用Servlet Name、DispatcherType作為映射。isMatchAfter表示新添加的Mapping是在已有的Mapping之前還是之后。
public void addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames);
// 獲取當(dāng)前FilterRegistration關(guān)聯(lián)的Filter已存在的到Servlet Name的映射。
public Collection<String> getServletNameMappings();
// 添加FilterRegistration關(guān)聯(lián)的Filter到Servlet的映射,使用URL patterns、DispatcherType作為映射。isMatchAfter表示新添加的Mapping是在已有的Mapping之前還是之后。
public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns);
// 獲取當(dāng)前FilterRegistration關(guān)聯(lián)的Filter已存在的到URL patterns的映射。
public Collection<String> getUrlPatternMappings();
interface Dynamic extends FilterRegistration, Registration.Dynamic {
}
}
在Jetty中對(duì)Registration的實(shí)現(xiàn)在Holder中定義,而相應(yīng)的ServletRegistration和FilterRegistration實(shí)現(xiàn)作為ServletHolder和FilterHolder中的內(nèi)部類實(shí)現(xiàn),具體參考這兩個(gè)類的實(shí)現(xiàn)。
Holder實(shí)現(xiàn)
在之前有提到,在Jetty中Servlet和Filter由相應(yīng)的ServletHolder和FilterHolder封裝,以將Servlet/Filter相關(guān)的信息和配置放在一起,并處理各自相關(guān)的邏輯,即面向?qū)ο笤O(shè)計(jì)中的將數(shù)據(jù)靠近操作。由于Servlet和Filter有一些相同的配置和邏輯,因而在ServletHolder和FilterHolder中提取出了Holder父類。在Holder的實(shí)現(xiàn)中,它主要定義了一些Servlet和Filter都要使用的字段,比高實(shí)現(xiàn)了所有和InitParameter相關(guān)的操作:
public enum Source { EMBEDDED, JAVAX_API, DESCRIPTOR, ANNOTATION };
final private Source _source;
protected transient Class<? extends T> _class;
protected final Map<String,String> _initParams=new HashMap<String,String>(3);
protected String _className;
protected String _displayName;
protected boolean _extInstance;
protected boolean _asyncSupported=true;
protected String _name;
protected ServletHandler _servletHandler;
Holder繼承自AbstractLifeCycle,它在start時(shí),如果_class字段沒有被設(shè)置,則會(huì)使用ClassLoader加載_className中指定的類實(shí)例并賦值給_class字段;Source只是目前只是一種元數(shù)據(jù)的形式存在,用于表示Servlet或Filter的來源;而extInstance用于表示Servlet和Filter實(shí)例是直接通過ServletContext注冊(cè)而來,而不是在當(dāng)前Holder內(nèi)部創(chuàng)建。
在Holder類中還定了兩個(gè)內(nèi)部類:HolderConfig和HolderRegistration,其中HoldConfig實(shí)現(xiàn)了ServletConfig/FilterConfig相關(guān)的所有InitParameter相關(guān)的操作(代理給Holder);HolderRegistration實(shí)現(xiàn)了Registration.Dynamic接口,其實(shí)現(xiàn)也都代理給Holder類中的方法。
FilterHolder實(shí)現(xiàn)
FilterHolder實(shí)現(xiàn)比較簡(jiǎn)單,它直接繼承自Holder類,它額外的包含了一下幾個(gè)字段:
private transient Filter _filter;
private transient Config _config;
private transient FilterRegistration.Dynamic _registration;
其中_filter字段在start時(shí)如果沒有初始化,則使用ServletContext創(chuàng)建該Filter實(shí)例,而_config字段則在啟動(dòng)時(shí)直接創(chuàng)建Config實(shí)例(Config是FilterHolder的內(nèi)部類,且它繼承自HolderConfig,并實(shí)現(xiàn)了FilterConfig接口),最后調(diào)用_filter.init()方法并傳入_config實(shí)例。在stop時(shí),調(diào)用_filter.destroy()方法從而該Filter有機(jī)會(huì)做一些清理工作,并且調(diào)用ServletHandler中的destroyFilter()方法,以通知ContextHandler中定義的Decorators。在注冊(cè)外部實(shí)例化的Filter時(shí),設(shè)置_extInstance為true,同時(shí)更新_class字段,以及_name字段(如果_name字段未被設(shè)置的話)。
最后,F(xiàn)ilterHolder中還定義了Registration內(nèi)部類,它繼承自HolderRegistration,并實(shí)現(xiàn)了FilterRegistration.Dynamic接口。該Registration內(nèi)部類實(shí)現(xiàn)了Mapping相關(guān)方法,Jetty中使用FilterMapping來表達(dá)一個(gè)Filter的映射關(guān)系。在FilterMapping中定義了一下映射關(guān)系:
private int _dispatches=DEFAULT;
private String _filterName;
private transient FilterHolder _holder;
private String[] _pathSpecs;
private String[] _servletNames;
它包含了兩個(gè)appliesTo()方法,這兩個(gè)方法在Chain用于根據(jù)dispatcherType或dispatcherType以及path計(jì)算當(dāng)前FilterMapping是否匹配給定的dispatcherType或dispatcherType和path。在對(duì)dispatcherType做匹配計(jì)算時(shí),使用FilterMapping實(shí)例的沒有設(shè)置dispatcherType集合,它依然匹配REQUEST或ASYNC(如果Filter支持ASYNC模式的話)。
boolean appliesTo(int type) {
if (_dispatches==0)
return type==REQUEST || type==ASYNC && _holder.isAsyncSupported();
return (_dispatches&type)!=0;
}
ServletHolder實(shí)現(xiàn)
ServletHolder實(shí)現(xiàn)相對(duì)復(fù)雜,它繼承自Holder類,并實(shí)現(xiàn)了UserIdentity.Scope接口以及Comparable接口,其中Comparable接口用于當(dāng)ServletHandler在start時(shí),對(duì)注冊(cè)的所有ServletHolder的數(shù)組排序以決定他們的start順序。它包含了一下額外的字段:
private int _initOrder;
private boolean _initOnStartup=false;
private Map<String, String> _roleMap;
private String _forcedPath;
private String _runAsRole;
private RunAsToken _runAsToken;
private IdentityService _identityService;
private ServletRegistration.Dynamic _registration;
private transient Servlet _servlet;
private transient Config _config;
private transient long _unavailable;
private transient UnavailableException _unavailableEx;
public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap();
其中_initOrder為ServletRegistration.Dynamic接口的實(shí)現(xiàn),它定義ServletHolder在ServletHandler中的start順序,即compareTo()方法的實(shí)現(xiàn)的主要參考信息。在Jetty中,只要設(shè)置了loadOnStart字段,則它就會(huì)在start時(shí)被初始化(即使設(shè)置的值為負(fù)數(shù))。在設(shè)置外部Servlet實(shí)例直接到ServletHolder中時(shí),_extInstance字段為被設(shè)置為true。如果在web.xml中的Servlet定義中有jsp-file定義,則設(shè)置該ServletHolder的forcePath值為該jsp-file中定義的值,而其className的值為servlet-class的定義,此時(shí)在ServletHolder的handle方法中會(huì)將forcePath的值設(shè)置到Request的org.apache.catalina.jsp_file屬性中(這個(gè)設(shè)置用來干嘛呢?還不了解。。。);在ServletHolder啟動(dòng)時(shí),如果Servlet實(shí)例實(shí)現(xiàn)了SingleThreadModel接口,則Servlet實(shí)例使用SingleThreadedWrapper類來表示(它包含一個(gè)Servlet棧 ,對(duì)每次請(qǐng)求,它會(huì)復(fù)用以前已經(jīng)創(chuàng)建的Servlet實(shí)例或者創(chuàng)建一個(gè)新的實(shí)例以處理當(dāng)前的請(qǐng)求,即該Servlet會(huì)有多個(gè)實(shí)例),如果_extInstance為true或者配置了loadOnStart屬性,則在ServletHolder啟動(dòng)是就會(huì)初始化這個(gè)Servlet(實(shí)例化Servlet,并調(diào)用Servlet的init方法)。當(dāng)一個(gè)請(qǐng)求到來時(shí),ServletHolder調(diào)用其handle方法以處理該請(qǐng)求,在該方法中調(diào)用Servlet的service方法,如果在處理過程中出錯(cuò)了,則在Request中設(shè)置javax.servlet.error.servlet_name屬性為ServletHolder的Name屬性。
類似FilterMapping,Jetty也使用ServletMapping表達(dá)Servlet和URL pattern的映射關(guān)系:
private String[] _pathSpecs;
private String _servletName;
其他Security相關(guān)的字段和邏輯暫不做介紹。。。。。
posted on 2014-05-11 23:52
DLevin 閱讀(7597)
評(píng)論(3) 編輯 收藏 所屬分類:
Jetty