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

          概述

          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)求處理。

          AsyncContext

          在Servlet 3.0中引入了AsyncContext,用于實(shí)現(xiàn)一個(gè)請(qǐng)求可以暫停處理,然后在將來的某個(gè)時(shí)候重新處理該請(qǐng)求,以釋放當(dāng)前請(qǐng)求處理過程中占用的線程。在使用時(shí),當(dāng)發(fā)現(xiàn)請(qǐng)求需要等待一段時(shí)間后才能做進(jìn)一步處理時(shí),可以調(diào)用ServletRequest.startAsync()方法,返回AsyncContext實(shí)例,使用自己的線程池啟動(dòng)一個(gè)線程來做接下來的處理或者將其放入一個(gè)任務(wù)隊(duì)列中,以由一個(gè)線程不斷的檢查它的可用狀態(tài),以實(shí)現(xiàn)最后的返回處理,或調(diào)用dispatch方法將其分發(fā)給其他URL做進(jìn)一步響應(yīng)處理。這項(xiàng)功能對(duì)SocketConnector沒有多大意義,因?yàn)榧词筍ervlet的servic俄方發(fā)退出了,其所占用的線程會(huì)繼續(xù)等待,并不會(huì)被回收,只有對(duì)SelectChannelConnector來說才有效果,因?yàn)樗牡却辉贖ttpConnection的handleRequest方法中(AsyncContinuation的scheduleTimeout方法中),而是將timeout的信息提交給SelectSet,它內(nèi)部會(huì)有Acceptors個(gè)線程對(duì)timeout進(jìn)行檢查。AsyncContext接口定義如下:
          public interface AsyncContext {
              // 原始請(qǐng)求相關(guān)信息的屬性名,即dispatch方法所基于的計(jì)算信息。
              static final String ASYNC_REQUEST_URI = "javax.servlet.async.request_uri";
              static final String ASYNC_CONTEXT_PATH = "javax.servlet.async.context_path";
              static final String ASYNC_PATH_INFO = "javax.servlet.async.path_info";
              static final String ASYNC_SERVLET_PATH = "javax.servlet.async.servlet_path";
              static final String ASYNC_QUERY_STRING = "javax.servlet.async.query_string";

              // AsyncContinuation是Jetty對(duì)AsyncContext的實(shí)現(xiàn),它是一個(gè)有限狀態(tài)機(jī)。
              // 1. 在初始化時(shí),它處于IDLE狀態(tài),initial狀態(tài)為true。
              // 2. 調(diào)用其handling()方法使其進(jìn)入處理模式:若它處于IDLE狀態(tài),則設(shè)置initial狀態(tài)為false,將狀態(tài)轉(zhuǎn)移到DISPATCHED,清除AsyncListener,返回true;若它處于REDISPATCH狀態(tài),將狀態(tài)轉(zhuǎn)移到REDISPATCHED,返回true;若它處于COMPLETING狀態(tài),狀態(tài)轉(zhuǎn)移到UNCOMPLETED,返回false;若它處于ASYNCWAIT狀態(tài),返回false。對(duì)其他狀態(tài),拋出IllegalStateException。
              // 3. 如果當(dāng)前請(qǐng)求因?yàn)槟承┰驘o法進(jìn)一步處理時(shí),可以調(diào)用ServletRequest.startAsync方法讓當(dāng)前請(qǐng)求進(jìn)入ASYNCSTARTED狀態(tài),即調(diào)用AsyncContinuation.suspend方法,只有它處于DISPATCHED、REDISPATCHED狀態(tài)下才能調(diào)用suspend方法,即在調(diào)用handling()方法之后。此方法還會(huì)更新AsyncEventState字段的信息,以及調(diào)用已注冊(cè)的AsyncListener的onStartAsync方法,并清除已注冊(cè)的AsyncListener。
              // 4. 調(diào)用unhandle()方法判斷這個(gè)當(dāng)前請(qǐng)求是否不需要做進(jìn)一步處理而可以退出handleRequest中的循環(huán):對(duì)ASYNCSTARTED狀態(tài),將其狀態(tài)設(shè)置為ASYNCWAIT,并向SelectChannelHttpConnection中schedle一個(gè)timeout時(shí)間,如果此時(shí)它還是處于ASYNCWAIT狀態(tài)(因?yàn)閷?duì)非SelectChannelConnector,它會(huì)一直等待下一個(gè)dispatch/complete/timeout事件的到來,更新當(dāng)前狀態(tài),并取消等待),則返回true,否則如果它變?yōu)镃OMPLETING狀態(tài),則設(shè)置狀態(tài)為UNCOMPLETED,返回true,否則設(shè)置其狀態(tài)為REDISPATCHED,并返回false;對(duì)DISPATCHED、REDISPATCHED狀態(tài),設(shè)置狀態(tài)為UNCOMPLETED,返回true;對(duì)REDISPATCHING狀態(tài),設(shè)置為REDISPATCHED狀態(tài),返回false;對(duì)COMPLETING狀態(tài),設(shè)置為UNCOMPLETED,返回true;對(duì)其他狀態(tài),拋出異常。
              // 5. 當(dāng)進(jìn)入異步狀態(tài)的請(qǐng)求完成后,需要將當(dāng)前處理交由Container做進(jìn)一步處理,如由另一個(gè)path完成進(jìn)一步處理等,調(diào)用AsyncContext的dispatch方法,將當(dāng)前請(qǐng)求分發(fā)回Container:如果當(dāng)前AsyncContinuation處于ASYNCWAIT狀態(tài)并且沒有超時(shí),設(shè)置狀態(tài)為REDISPATCH,并cancelTimeout()、scheduleDispatch();對(duì)已經(jīng)處于REDISPATCH狀態(tài),直接返回;對(duì)處于ASYNCSTARTED狀態(tài),設(shè)置為REDISPATCHING,并返回。
              // 6. 如果當(dāng)前AsyncContinuation超時(shí),調(diào)用其expired方法:對(duì)于處于ASYNCSARTED、ASYNCWAIT狀態(tài),觸發(fā)AsyncListener的onTimeout事件,調(diào)用complete方法,并scheduleDispatch
              // 7. 當(dāng)完成異步請(qǐng)求處理時(shí),調(diào)用其complete方法:如果處于ASYNCWAIT狀態(tài),設(shè)置狀態(tài)為COMPLETING,如果沒有超時(shí),scheduleTimeout、scheduleDispatch;當(dāng)前狀態(tài)為ASYNCSTARTED,設(shè)置狀態(tài)為COMPLETING;對(duì)其他狀態(tài),拋出異常。
              // 8. 當(dāng)退出handleRequest方法時(shí),如果當(dāng)前AsyncContinuation處于UNCOMPLETE狀態(tài),調(diào)用其doComplete方法,將其狀態(tài)設(shè)置為COMPLETE,如果出現(xiàn)異常,注冊(cè)javax.servlet.error.exception, javax.servlet.error.message屬性,并觸發(fā)AsyncListener的onError事件,否則觸發(fā)onComplete事件。
              // 9. 對(duì)狀態(tài)為ASYNCSTARTED、REDISPATCHING、COMPLETING、ASYNCWAIT,表示處于suspend狀態(tài)。
              // 10. 對(duì)狀態(tài)為ASYNCSTARTED、REDISPATCHING、REDISPATCH、ASYNCWAIT,表示其處于異步請(qǐng)求開啟的狀態(tài)。
              // 11. 對(duì)狀態(tài)不是IDLE、DISPATCHED、UNCOMPLETED、COMPLETED,表示當(dāng)前正處于異步請(qǐng)求狀態(tài)。 


              // 在調(diào)用ServletRequest.startAsync方法中使用的ServletRequest、ServletResponse實(shí)例。在調(diào)用ServletRequest.startAsync方法時(shí),內(nèi)部調(diào)用AsyncContinuation的suspend方法,
              // 傳入ServletContext、ServletRequest、ServletResponse實(shí)例,在有在AsyncContinuation實(shí)例處于DISPATCHED、REDISPATCHED狀態(tài)下才能調(diào)用suspend方法。此時(shí)將_expired、_resumed狀態(tài)設(shè)置為false,更新AsyncEventState中的AsyncContext、ServletContext(_suspendedContext, _dispatchedContext)、ServletRequest、ServletResponse、Path等信息(即如果傳入的Request、Response、_suspendContext和當(dāng)前已保存的實(shí)例不同或_event實(shí)例為null,則重新創(chuàng)建AsyncEventState實(shí)例,否則清除_event中的_dispatchedContext和_path字段)。將當(dāng)前AsyncContinuation的狀態(tài)設(shè)置為ASYNCSTARTED,保存已注冊(cè)的AsyncListener列表(_asyncListeners)到_lastAsyncListeners,清除_asyncListeners列表,并觸發(fā)_lastAsyncListeners中的onStartAsync事件(該事件中可以決定是否需要將自己注冊(cè)回去)。
              // 對(duì)于AsyncContext實(shí)例,如果已經(jīng)調(diào)用suspend方法,則返回_event中的ServletRequest、ServletResponse,否則返回HttpConnection中的ServletRequest、ServletResponse。 

              public ServletRequest getRequest();
              public ServletResponse getResponse();

              // 當(dāng)前AsyncContext是否使用原始的request、response實(shí)例進(jìn)行初始化。
              public boolean hasOriginalRequestAndResponse();

              public void dispatch();
              public void dispatch(String path);
              public void dispatch(ServletContext context, String path);
              public void complete();
              public void start(Runnable run);

              public void addListener(AsyncListener listener);
              public void addListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse);

             public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException; 

              public void setTimeout(long timeout);
              public long getTimeout();
          }
          在Server的handleAsync()方法中,他使用HttpConnection的Request字段的AsyncEventState中的ServletRequest、ServletResponse作為Handler調(diào)用handle方法的參數(shù),如果AsyncEventState中有path值,則會(huì)用該值來更新baseRequest中的URI相關(guān)信息。

          RequestDispatcher

          在Servlet中RequestDispatcher用于將請(qǐng)求分發(fā)到另一個(gè)URL中,或向響應(yīng)中包含更多的信息。一般用于對(duì)當(dāng)前請(qǐng)求做一些前期處理,然后需要后期其他Servlet、JSP來做進(jìn)一步處理。在Jetty中使用Dispatcher類實(shí)現(xiàn)該接口,其接口定義如下:
          public interface RequestDispatcher {
              // 在Dispatcher類中包含了ContextHandler、uri、path、dQuery、named字段,其中ContextHandler是當(dāng)前Web Application配置的Handler鏈用于將請(qǐng)求分發(fā)給當(dāng)前Container(調(diào)用handle()方法)做進(jìn)一步處理、dipatch后請(qǐng)求的全URI、path表示uriInContext、dQuery表示新傳入的parameter、named表示可以使用Servlet名稱創(chuàng)建Dispatcher,即將當(dāng)前請(qǐng)求分發(fā)到一個(gè)命名的Servlet中。
              // 在Dispatcher類中有三個(gè)方法:forward、error、include。對(duì)forward、error來說,如果Response已經(jīng)commit,會(huì)拋出IllegalStateException。
              // 其中forward和error只是DispatcherType不一樣(FORWARD、ERROR),其他邏輯一樣:清除ServletResponse中所有響應(yīng)相關(guān)的字段,如Content Buffer、locale、ContentType、CharacterEncoding、MimeType等信息,設(shè)置ServletRequest的DispatchType;對(duì)named方式的Dispatcher,直接調(diào)用ContextHandler的handle方法,其target參數(shù)即為傳入的named;如果dQuery字段不為null,將該dQuery中的包含的參數(shù)合并到當(dāng)前請(qǐng)求中;更新Request的URI、ContextPath,并在其Request屬性中添加原始請(qǐng)求的pathInfo、queryString、RequestURI、contextPath、servletPath信息,分別對(duì)應(yīng)該接口中定義的字段,如果這是第二次forward,則保留最原始的請(qǐng)求相關(guān)的信息;最后調(diào)用ContextHandler的handle方法,target為path屬性;在調(diào)用結(jié)束后,將RequestURI、ContextPath、ServletPath、PathInfo、Attributes、Parameters、QueryString、DispatcherType屬性設(shè)置為原來的值。
              // 對(duì)include方法,它不會(huì)清除Response中的Buffer等信息:首先設(shè)置DispatcherType為INCLUDE,HttpConnection中的include字段加1,表示正處于INCLUDE的dispatch狀態(tài),從而阻止對(duì)ServletResponse響應(yīng)頭的設(shè)置、發(fā)送重定向響應(yīng)、發(fā)送Error響應(yīng)等操作,該include字段會(huì)在該方法結(jié)束是調(diào)用HttpConnection的included方法將其減1;同樣對(duì)于named設(shè)置的Dispatcher實(shí)例,直接調(diào)用ContextHandler的handle方法,target為named值;對(duì)以path方式的include,首先合并傳入的dQuery參數(shù)到Request中,更新Request中屬性的requestURI、contextPath、pathInfo、query等,后調(diào)用ContextHandler的handle方法,target為path,在handle方法完成后,將請(qǐng)求Attributes、Parameters、DispatcherType設(shè)置會(huì)原有值。

              // 在forward中,原始請(qǐng)求對(duì)應(yīng)信息使用的屬性名。
              static final String FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri";
              static final String FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";
              static final String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
              static final String FORWARD_SERVLET_PATH = "javax.servlet.forward.servlet_path";
              static final String FORWARD_QUERY_STRING = "javax.servlet.forward.query_string";

              // 在include中,原始請(qǐng)求對(duì)應(yīng)信息使用的屬性名。
              static final String INCLUDE_REQUEST_URI = "javax.servlet.include.request_uri";
              static final String INCLUDE_CONTEXT_PATH = "javax.servlet.include.context_path";
              static final String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";
              static final String INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path";
              static final String INCLUDE_QUERY_STRING = "javax.servlet.include.query_string";

              // 在error中,原始請(qǐng)求對(duì)應(yīng)信息使用的屬性名。
              public static final String ERROR_EXCEPTION = "javax.servlet.error.exception";
              public static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
              public static final String ERROR_MESSAGE = "javax.servlet.error.message";
              public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
              public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
              public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";

              public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException;
              public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException;
          }

          HttpSession

          Http的請(qǐng)求是無狀態(tài)的,這種方式的好處是邏輯簡(jiǎn)單,因?yàn)榉?wù)器不需要根據(jù)當(dāng)前服務(wù)器的狀態(tài)做一些特殊處理,然而在實(shí)際應(yīng)用中,有些時(shí)候希望一系列的請(qǐng)求共享一些數(shù)據(jù)和信息,在HTTP中可以有兩種方式實(shí)現(xiàn)這種需求:一種是cookie,所有這些共享的數(shù)據(jù)和信息都使用cookie在發(fā)送請(qǐng)求時(shí)發(fā)送給服務(wù)器,在響應(yīng)請(qǐng)求時(shí)將最新的信息和狀態(tài)通過set-cookie的方式重新發(fā)送回客戶端,這種方式可以使服務(wù)器依然保持簡(jiǎn)單無狀態(tài)的處理邏輯,然而它每次都要來回傳送這種狀態(tài)信息,會(huì)占用帶寬,而且cookie本身有大小限制,有些客戶端處于安全的因素會(huì)禁止cookie使用,另外cookie采用明文方式,對(duì)有些數(shù)據(jù)來說是不適合的;另一種方式則是采用服務(wù)器端Session的方法,即使用SessionId將一系列的請(qǐng)求關(guān)聯(lián)在一起,可以向Session存儲(chǔ)這些請(qǐng)求共享的信息和數(shù)據(jù),Session方式的好處是這些數(shù)據(jù)保存在服務(wù)器端,因而它是安全的,而且不需要每次在客戶端和服務(wù)器端傳輸,可以減少帶寬,而它不好的地方是會(huì)增加服務(wù)器負(fù)擔(dān),因?yàn)槿绻鸖ession過多會(huì)占用服務(wù)器內(nèi)存,另外它也會(huì)增加服務(wù)器端的邏輯,服務(wù)器要有一種機(jī)制保證相同的SessionId確實(shí)屬于同一個(gè)系列的請(qǐng)求。
          在Servlet種使用HttpSession抽象這種服務(wù)器端Session的信息。它包含了SessionId、CreationTime、LastAccessedTime、MaxInactiveInterval、Attributes等信息,在Servlet中的可見范偉是ServletContext,即跨Web Application的Session是不可見的。在Jetty中使用SessionManager來管理Session,Session可以存儲(chǔ)在數(shù)據(jù)庫(kù)中(JDBCSessionManager),也可以存在內(nèi)存中(HashSessionManager)。在Jetty中使用AbstractSessionManager的內(nèi)部類Session來實(shí)現(xiàn)HttpSession接口,并且該實(shí)現(xiàn)是線程安全的。HttpSession的接口定義如下:
          public interface HttpSession {
              // HttpSession創(chuàng)建的時(shí)間戳,從1970-01-01 00:00:00.000開始算到現(xiàn)在的毫秒數(shù)。
              public long getCreationTime();
              
              // 當(dāng)前Session的ID號(hào),它用來唯一標(biāo)識(shí)Web Application中的一個(gè)Session實(shí)例。在Jetty的實(shí)現(xiàn)中,有兩種ID:NodeId和ClusterId,在SessionIdManager創(chuàng)建一個(gè)ClusterId時(shí),可以使用一個(gè)SecureRandom的兩次nextLong的36進(jìn)制的字符串相加或者兩次當(dāng)前SessionIdManager的hashCode、當(dāng)前可用內(nèi)存數(shù)、random.nextInt()、Request的hashCode左移32位的異或操作的36進(jìn)制字符串相加,并添加workName前綴,如果該ID已經(jīng)存在,則繼續(xù)使用以上邏輯,直到找到一個(gè)沒有被使用的唯一的ID號(hào)。如果請(qǐng)求中的RequestedSessionId存在并在使用,則使用該值作為SessionID;如果當(dāng)前請(qǐng)求已經(jīng)存在一個(gè)正在使用的SessionId(在org.eclipse.jetty.server.newSessionId請(qǐng)求熟悉中),則使用該ID。而對(duì)與NodeId,它會(huì)在ClusterId之后加一個(gè)".workerName",可以通過SessionIdManager設(shè)置workName或在HashSessionIdManager中使用org.eclipse.jetty.ajp.JVMRoute請(qǐng)求屬性設(shè)置。在AbstractSessionManager中設(shè)置NodeIdInSessionId為true來配置使用NodeId作為SessionId,默認(rèn)使用ClusterId作為SessionId。
              public String getId();
              
              // 返回最后一次訪問時(shí)間戳。在每一次屬于同一個(gè)Session的新的Request到來時(shí)都會(huì)更新該值。
              public long getLastAccessedTime();
              
              // 返回該Session對(duì)應(yīng)的ServletContext。
              public ServletContext getServletContext();

              // 設(shè)置Session的Idle時(shí)間,以秒為單位。
              public void setMaxInactiveInterval(int interval);
              public int getMaxInactiveInterval();    

              // Attribute相關(guān)操作。在設(shè)置屬性時(shí),如果傳入value為null,則移除該屬性;如果該屬性已存在,則替換該屬性;如果屬性值實(shí)現(xiàn)了HttpSessionBindingListener,則它在替換時(shí)會(huì)觸發(fā)其valueUnbound事件,屬性設(shè)置時(shí)會(huì)觸發(fā)valueBound事件;如果HttpSession中注冊(cè)了HttpSessionAttributeListener,則會(huì)觸發(fā)響應(yīng)的attributeAdded、attributeReplaced事件。而removeAttribute時(shí),也會(huì)觸發(fā)相應(yīng)的valueUnbound事件以及attributeRemoved事件。
              public Object getAttribute(String name);
              public Enumeration<String> getAttributeNames();    
              public void setAttribute(String name, Object value);
              public void removeAttribute(String name);

              // Session失效,它移除所有和其綁定的屬性,并且將Session實(shí)例從SessionManager中移除。
              public void invalidate();
              
              // true表識(shí)客戶端沒有使用session。此時(shí)客戶端請(qǐng)求可能不需要使用session信息或者它使用cookie作為session的信息交互。
              public boolean isNew();
          }
          在Jetty中使用SessionIdManager來創(chuàng)建管理SessionId信息,默認(rèn)實(shí)現(xiàn)有HashSessionIdManager和JDBCSessionIdManager:
          public interface SessionIdManager extends LifeCycle {
              public boolean idInUse(String id);
              public void addSession(HttpSession session);
              public void removeSession(HttpSession session);
              public void invalidateAll(String id);
              public String newSessionId(HttpServletRequest request,long created);
              public String getWorkerName();
              public String getClusterId(String nodeId);
              public String getNodeId(String clusterId,HttpServletRequest request);  
          }
          而HttpSession的創(chuàng)建和管理則使用SessionManager,默認(rèn)有HashSessionManager和JDBCSessionManager兩個(gè)實(shí)現(xiàn):
          public interface SessionManager extends LifeCycle {
              // 在AbstractSessionManager定義了Session內(nèi)部類實(shí)現(xiàn)了HttpSession接口,使用SessionIdManager來生成并管理SessionId,可以注冊(cè)HttpSessionAttributeListener和HttpSessionListener(在HttpSession創(chuàng)建和銷毀時(shí)分別觸發(fā)sessionCreated、sessionDestroyed事件)。另外它還實(shí)現(xiàn)了SessionCookieConfig內(nèi)部類,用于使用Cookie配置Session的信息,如Name(默認(rèn)JSESSIONID)、domain、path、comment、httpOnly、secure、maxAge等。在HashSessionManager和JDBCSessionManager中還各自有一個(gè)線程會(huì)檢查Session的expire狀態(tài),并Invalidate已經(jīng)expired的Session。最后,AbstractSessionManager還包含了Session相關(guān)的統(tǒng)計(jì)信息。

              // 在SessionManager中定義的一些屬性,可以使用該方法定義的一些屬性在ServletContext的initParam中設(shè)置,即web.xml文件中的init-param中設(shè)置。

              // 創(chuàng)建并添加HttpSession實(shí)例。
              public HttpSession newHttpSession(HttpServletRequest request);

              // 根據(jù)SessionId獲取HttpSession實(shí)例。
              public HttpSession getHttpSession(String id);

              // 獲取Cookie作為SessionTrackingMode時(shí),該Cookie是否屬于httpOnly(用來阻止某些cross-script攻擊)
              public boolean getHttpOnly();

              // Session的最大Idle時(shí)間,秒為單位
              public int getMaxInactiveInterval();
              public void setMaxInactiveInterval(int seconds);

              public void setSessionHandler(SessionHandler handler);

              // 事件相關(guān)操作
              public void addEventListener(EventListener listener);
              public void removeEventListener(EventListener listener);
              public void clearEventListeners();

              // 在使用Cookie作為SessionTrackingMode時(shí),獲取作為Session Tracking的Cookie
              public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure);

              public SessionIdManager getIdManager();
              public void setIdManager(SessionIdManager idManager);
              public boolean isValid(HttpSession session);
              public String getNodeId(HttpSession session);
              public String getClusterId(HttpSession session);

              // 更新Session的AccessTime。
              public HttpCookie access(HttpSession session, boolean secure);

              public void complete(HttpSession session);

              // 使用URL作為SessionTrackingMode時(shí),在URL中作為SessionId的parameter name。
              public void setSessionIdPathParameterName(String parameterName);
              public String getSessionIdPathParameterName();

              // 使用URL作為SessionTrackingMode時(shí),在URL中SessionId信息的前綴,默認(rèn)為:;<sessionIdParameterName>=
              public String getSessionIdPathParameterNamePrefix();

              public boolean isUsingCookies();
              public boolean isUsingURLs();
              public Set<SessionTrackingMode> getDefaultSessionTrackingModes();
              public Set<SessionTrackingMode> getEffectiveSessionTrackingModes();
              public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes);
              public SessionCookieConfig getSessionCookieConfig();

              public boolean isCheckingRemoteSessionIdEncoding();
              public void setCheckingRemoteSessionIdEncoding(boolean remote);
          }

          SessionHandler

          SessionHandler繼承子ScopedHandler,它主要使用SessionManager在doScope方法中為當(dāng)前Scope設(shè)置Session信息。
          1. 如果使用Cookie作為SessionId的通信,則首先從Cookie中向Request設(shè)置RequestedSessionId。
          2. 否則,從URL中計(jì)算出RequestedSessionId,并設(shè)置到Request中。
          3. 如果SessionManager發(fā)生變化,則更新Request中SessionManager實(shí)例以及Session實(shí)例。
          4. 如果Session發(fā)生變化,則更新Session的AccessTime,并將返回的cookie寫入Response中。
          5. 在退出時(shí)設(shè)置回Request原有的SessionManager和Session實(shí)例,如果需要的話。
          posted on 2014-05-17 17:58 DLevin 閱讀(2270) 評(píng)論(0)  編輯  收藏 所屬分類: Jetty
          主站蜘蛛池模板: 唐山市| 福建省| 襄垣县| 衡阳市| 扶余县| 鹰潭市| 门源| 英德市| 东平县| 西藏| 昌吉市| 包头市| 鹿邑县| 西贡区| 邮箱| 微博| 泾川县| 三穗县| 神农架林区| 容城县| 博爱县| 新巴尔虎右旗| 沐川县| 永平县| 莱州市| 滦平县| 敦煌市| 孙吴县| 射洪县| 玛沁县| 分宜县| 蒲城县| 平武县| 稷山县| 墨竹工卡县| 漳浦县| 安宁市| 平果县| 江川县| 麟游县| 靖西县|