大家都知道,在開發(fā)一個互聯網應用的時候,為了達到一種服務端和客戶端有狀態(tài)的效果,需要有一個sessionid 來對客戶端進行標志。很多時候,這是通過在客戶端防止session cookie實現的。但是如果客戶端禁用了cookie呢?這就需要通過urlrewrite或者其他方式來實現。于是我們可能就在應用里面不需要cookie了。既然不需要了當然是希望我們的應用不對cookie進行處理。很遺憾的是,tomcat默認的是處理cookie的。每次請求過來的時候,都會解析request head里面的cookie信息,試圖從中發(fā)現sessionid的信息。于是我們就需要從應用服務器層面把這個"無用功"去掉。
tomcat(我讀的是tomcat6的源碼)可以通過設置來實現:
在conf/context.xml里面:<Context cookies = "false">。那么就禁用了cookie了。
在源碼級別的實現則是在CoyoteAdapter里面:
Java代碼
protected void parseSessionCookiesId(org.apache.coyote.Request req, Request request) { // If session tracking via cookies has been disabled for the current // context, don't go looking for a session ID in a cookie as a cookie // from a parent context with a session ID may be present which would // overwrite the valid session ID encoded in the URL Context context = (Context) request.getMappingData().context; if (context != null && !context.getCookies()) return;
在這里面做了一個判斷,如果context禁用了cookie,那么就不做解析。如果使用cookie,那么試著從cookie里面解析
sessionid,并且如果存在的話覆蓋request里面已有的(從url里面解析出來的)或者還沒有的sesssionid.
這個方法的入口是在CoyoteAdapter的service方法里面,這個方法沿著tomcat6的component 鏈傳遞處理request 和response,結構圖如下:
service--------->EngineValue
|
HostValue
|
ContextValue
|
WrapperValue
這實際就是一個chain of resposibility模式,負責對request和response進行各自職責范圍內的包裝和處理。
最后的WrapperValue執(zhí)行調用servlet處理請求的步驟。
好了,上面簡單解釋了cookie的處理,那么下面就是session了。
不管通過什么方式,通過cookie也好,通過urlrewrite也好,session在需要的時候是肯定要產生的.
但是如果我們不需要呢?比如恰好我們要展現給客戶的首頁就是jsp的,客戶不需要登錄就能瀏覽這個頁面的內容。
那么這個時候對于客戶的請求創(chuàng)建session就是沒有必要的了。
一種常用的不創(chuàng)建session的方法是在jsp頁面頭上加一句:
<%@ page session=”false”>
這樣在請求這個頁面的時候就不產生session了。
這個在tomcat內部是怎么實現的呢?
首先明確一點,jsp在本質上是httpservlet,在/tomcat/work目錄下面你會發(fā)現有跟自己的應用相同目錄結構的一些文件,其中的jsp文件都變成了class文件,這實際是被jspcompiler編譯過的。上面提到了WrapperValue會最終調用
servlet處理request。有興趣的同學可以跟蹤一下,會發(fā)現到了調用jsp對應的servlet(JspServlet)(這個是在tomcat/conf/web.xml里面配置的,對于.jsp,對應的servlet是jspservlet)時,最終會著落在
tomcat下面實現了PageContext接口的特定于jsp specification的實現類:PageContextImpl。
在這個類的initialize里面有這么一句:
Java代碼
if (request instanceof HttpServletRequest && needsSession) this.session = ((HttpServletRequest) request).getSession();
這句的意思就是,有session獲取session,沒session新建一個。而通常,這個地方也是客戶端與tomcat下面的應用交互時產生session的入口。
這句里面的needsSession就是之前提到的jsp頁面上配置的值,默認是true.所以如果想在訪問某個頁面時不產生session,只需要設置成false就可以了。