jsessionid
在服務器端,我們用慣了session.setAttribute("",userInfo)這樣的一行代碼,估計你很少想到:服務器與瀏覽器之間是如何保持會話狀態的。好了,先引用一些文章的精彩片段:http://www.xxx.com/xxx_app;jsessionid=xxxxxxxxxx?a=x&b=x。
這跟一般的url基本一樣,只有一個地方有區別,那就是“;jessionid=xxxxxxxx”。這個參數有時候有,有時候又沒有,說它是參數可又跟一般傳遞的參數不同,它是緊跟在url后面用分號來分隔的 ,用一般的request.getParameter()方法還取不到jsessionid 。
?session的實現方式
做web開發的同學都知道,http是無狀態的會話協議,也就是說無法保存用戶的信息。那如果有一些信息需要在用戶的瀏覽活動中一直保持,該怎么做呢?我們可以把這些信息在每次請求的時候作為參數傳遞給服務器,但這樣做既麻煩又耗費資源,這時候就體現出了session的重要性。session是web開發中不可或缺的一個特性。它是對于一個特定的用戶請求,在web服務器上保存的一個全局變量。有了它我們就可以把用戶的一些信息保存在服務器上,而不用在服務器和客戶端之間來回傳遞。知道了session的作用,那session是怎么實現的呢?服務器上為每個用戶都保存了一個session,那當用戶請求過來的時候是怎么知道某一個用戶應該對應哪個session呢?這時jsessionid就派上用場了。每一個session都有一個id來作為標識,這個id會傳到客戶端,每次客戶端請求都會把這個id傳到服務器,服務器根據id來匹配這次請求應該使用哪個session。jsessionid就是客戶端用來保存sessionid的變量,主要是針對j2ee實現的web容器,沒有研究過其他語言是用什么變量來保存的。一般對于web應用來說,客戶端變量都會保存在cookie中,jsessionid也不例外。不過與一般的cookie變量不同,jsessionid是保存在內存cookie中的,在一般的cookie文件中是看不到它的影子的。內存cookie在打開一個瀏覽器窗口的時候會創建,在關閉這個瀏覽器窗口的時候也同時銷毀。這也就解釋了為什么session變量不能跨窗口使用,要跨窗口使用就需要手動把jsessionid保存到cookie里面。
jsessionid的作用
在以上的文字中我們了解了session的實現原理,同時也知道了session跟jsessionid緊密不可分割的聯系。只有通過jsessionid才能使session機制起作用,而jsessionid又是通過cookie來保存。看到這里,也許你會發現一個問題,如果用戶禁用了cookie,那jsessionid不是就不能保存了嗎?session不是不起作用了嗎?我們真的對此束手無策了嗎?當然不是。在用戶禁用了cookie時候,我們可以通過url重寫來實現jsessionid的傳遞。這就是我上面指出的那樣的url:http://www.xxx.com/xxx_app;jsessionid=xxxxxxxxxx?a=x&b=x..。jessionid通過這樣的方式來從客戶端傳遞到服務器端,從而來標識session。注意一點,jsessionid跟一般的url參數傳遞方式是不同的,不是作為參數跟在?后面,而是緊跟在url后面用;來分隔。這樣在用戶禁用cookie的時候我們也可以傳遞jsessionid來使用session了,只不過需要每次都把jseesionid作為參數跟在url后面傳遞。那這樣豈不是很麻煩,每次請求一個url都要判斷cookie是否可用,如果禁用了cookie,還要從url里解析出jsessionid,然后跟在處理完后轉到的url后面,以保持jsessionid的傳遞。這些問題sun當然已經幫我們想到了,所以提供了2個方法來使事情變得簡單:response.encodeURL()和response.encodeRedirectURL()。這2個方法會判斷cookie是否可用,如果禁用了會解析出url中的jsessionid,并連接到指定的url后面,如果沒有找到jessionid會自動幫我們生成一個。至于為什么要有2個方法?這2個方法有什么不同?google了一下,說是這2個方法在判斷是否要包含jsessionid的邏輯上會稍有不同。在調用HttpServletResponse.sendRedirect前,應該先調用encodeRedirectURL()方法,否則可能會丟失Sesssion信息。這2個方法的使用方法如:response.sendRedirect(response.encodeURL("/myapp/input.jsp"));。如果cookie沒有禁用,我們在瀏覽器地址欄中看到的地址是這樣的:/myapp/input.jsp,如果禁用了cookie,我們會看到:/myapp/input.jsp;jsessionid=73E6B2470C91A433A6698C7681FD44F4。所以,我們在寫web應用的時候,為了保險起見,應該在程序里的每一個跳轉url上都使用這2個方法,來保證session的可用性。
?
啟動你的tomcat,打開FireFox(愛得不得了,一定要安裝FireBug),輸入localhost就行,打開firebug,點網絡,你會看到,瀏覽器與服務器會話的信息,給出瀏覽器
(1)第一次請求服務器:
瀏覽器的請求頭信息
| Host | localhost |
| User-Agent | Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 |
| Accept | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
| Accept-Language | zh-cn,zh;q=0.5 |
| Accept-Encoding | gzip,deflate |
| Accept-Charset | GB2312,utf-8;q=0.7,*;q=0.7 |
| Keep-Alive | 115 |
| Connection | keep-alive ? |
服務器響應頭信息
| Server | Apache-Coyote/1.1 |
| Set-Cookie | JSESSIONID=64D21B4D69DFB3041B6375C1932BD6CB; Path=/ |
| Content-Type | text/html;charset=UTF-8 |
| Content-Language | zh-CN |
| Content-Length | 242 |
| Date | Mon, 28 Jun 2010 02:35:29 GMT |
(2)第二次請求服務器:
瀏覽器的請求頭信息
| Host | localhost |
| User-Agent | Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 |
| Accept | text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 |
| Accept-Language | zh-cn,zh;q=0.5 |
| Accept-Encoding | gzip,deflate |
| Accept-Charset | GB2312,utf-8;q=0.7,*;q=0.7 |
| Keep-Alive | 115 |
| Connection | keep-alive |
| Cookie | JSESSIONID=64D21B4D69DFB3041B6375C1932BD6CB |
服務器響應頭信息
| Server | Apache-Coyote/1.1 |
| Content-Type | text/html;charset=UTF-8 |
| Content-Language | zh-CN |
| Content-Length | 242 |
| Date | Mon, 28 Jun 2010 02:37:51 GMT |
重復第三次,每四次...第N次請求服務器,瀏覽器和服務器的請求頭信息都是與第二次請求服務器是一樣的。
?
(3)但是,如果你在服務器端加入如下一行代碼:
Log.info("SessionId:" + request.getSession().getId());
你會看到,當你第一次請求服務器時,就會默認有一個新的session被創建,而且在session的有效時間范圍內,這個輸出值是不會變的,否則,服務器會重新創建一個session,自然,sessionId也就不同了,這段代碼的輸出自然也會不同了。
?
(4)你必須注意這一點:你用的是瀏覽器與服務器通信:
有一些事情是瀏覽器幫助我們去做了,那就是:當你第一次與服務器通信時,瀏覽器會保存服務器返回的 Set-Cookie 這個健的值( JSESSIONID=64D21B4D69DFB3041B6375C1932BD6CB ),只要你不關閉瀏覽器(徹底關閉,關閉選項卡不算),瀏覽器會從第二次向服務器發出請求開始,一直帶上這個鍵值對,發給服務器。服務器就會知道,這是同一個人(同一個會話)發起的請求。
?
(5)我們再注意一下:request.setAttribute("sysuser",userInfo)這句話:
當你第一次請求服務器時,這句代碼會根據服務器默認產生的session得到ID,并與sysuser=userInfo這個鍵值對掛上鉤(當然,userInfo可以是任何對象),保證唯一關聯,檢測用戶是否登錄就是這樣實現的。
我一定要聲明一點:保持一個會話與用戶是否登錄是沒有任何關系的。
?
(6)再次引深一下,如果你用的不是瀏覽器,比如說做J2ME開發,怎樣保持會話呢?
(1) 在你寫完這行代碼后:HttpConnection hc = (HttpConnection)Connector.open(httpURL),加入以下代碼:( Constant.sessionID只是一個靜態變量 )
?
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
[java] view plaincopyprint?
//在與服務器通信前設置sessionId,維持唯一的一個會話if (Constant.sessionID != null) { hc.setRequestProperty("Cookie", AppContext.CurrentAppContext.sessionID);}
?
?
(2) A:只向服務器讀數據,不向服務寫數據,B:先向服務器寫數據,再從服務器讀數據
對于這兩種情況,只要你第一次打開openDataInputStream(),這可以加入以下代碼( Constant.isLogin 只是一個靜態變量boolean ):
?
view plaincopy to clipboardprint?
·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
[java] view plaincopyprint?
//每次與服務器通信后,保存 sessionIdString cookie = hc.getHeaderField("Set-Cookie");if (cookie != null) { String jsessionId = cookie.substring(0,cookie.indexOf(";")); if(Constant.sessionID != null && !Constant.sessionID.equals(jsessionId) && Constant.isLogin ){ Log.info("sessionid超時, will get new sessionid, but you must login again"); //設置為未登錄狀態 Constant.isLogin = false; } Constant.sessionID = jsessionId;}?
?
這樣就可以保持一個會話了。
?
(7)最后,關于URL重定向
引用一段話:sun幫我們想到了,所以提供了2個方法來使事情變得簡單:response.encodeURL()和response.encodeRedirectURL()。這2個方法會判斷cookie是否可用,如果禁用了會解析出url中的jsessionid,并連接到指定的url后面,如果沒有找到jessionid會自動幫我們生成一個。至于為什么要有2個方法?這2個方法有什么不同?google了一下,說是這2個方法在判斷是否要包含jsessionid的邏輯上會稍有不同。在調用 HttpServletResponse.sendRedirect前,應該先調用encodeRedirectURL()方法,否則可能會丟失 Sesssion信息。這2個方法的使用方法如:response.sendRedirect(response.encodeURL("/myapp /input.jsp"));。如果cookie沒有禁用,我們在瀏覽器地址欄中看到的地址是這樣的:/myapp/input.jsp,如果禁用了 cookie,我們會看到:/myapp /input.jsp;jsessionid=73E6B2470C91A433A6698C7681FD44F4。所以,我們在寫web應用的時候,為了保險起見,應該在程序里的每一個跳轉url上都使用這2個方法,來保證session的可用性。
總結
以上是生活随笔為你收集整理的jsessionid的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC之@requestBo
- 下一篇: idea中修改jsp文件不用再重启tom