文中黃色字體爲個人標記修改或添加html
Session保存在服務器端。爲了得到更高的存取速度,服務器通常把Session放在內存裏。每一個用戶都會有一個獨立的Session。若是Session內容過於複雜,當大量客戶訪問服務器時可能會致使內存溢出。所以,Session裏的信息應該儘可能精簡。web
Session在用戶第一次訪問服務器的時候自動建立。須要注意只有訪問JSP、Servlet等程序時纔會建立Session,只訪問HTML、IMAGE等靜態資源並不會建立Session。若是還沒有生成Session,也可使用request.getSession(true)強制生成Session。跨域
Session生成後,只要用戶繼續訪問,服務器就會更新Session的最後訪問時間,並維護該Session。用戶每訪問服務器一次,不管是否讀寫Session,服務器都認爲該用戶的Session"活躍(active)"了一次。瀏覽器
因爲會有愈來愈多的用戶訪問服務器,所以Session也會愈來愈多。爲防止內存溢出,服務器會把長時間內沒有活躍的Session從內存刪除。這個時間就是Session的超時時間。若是超過了超時時間沒訪問過服務器,Session就自動失效了。安全
Session的超時時間爲maxInactiveInterval屬性,能夠經過對應的getMaxInactiveInterval()獲取,經過setMaxInactiveInterval(long interval)修改。服務器
筆記:設置session生命週期的三種方法;
方式一:
在Servlet中設置
HttpSession session = request.getSession();
session.setMaxInactiveInterval(60);//單位爲秒
方式二:
在web.xml中設置session-config以下:
<session-config>
<session-timeout>2(單位:分鐘)</session-timeout>
</session-config>
方式三:
在Tomcat的/conf/web.xml中session-config,默認值爲:30分鐘 配置全局Session生命週期,即全部在該服務器中部署的項目都會使用
<session-config>
<session-timeout>30</session-timeout>
</session-config>
優先級:Servlet中API設置 > 程序/web.xml設置 > Tomcat/conf/web.xml設置cookie
Session的超時時間也能夠在web.xml中修改。另外,經過調用Session的invalidate()方法可使Session失效。網絡
筆記: 使session失效的方法: session.invalidate() ;
Session中包括各類方法,使用起來要比Cookie方便得多。Session的經常使用方法以下。session
HttpSession的經常使用方法:併發
void setAttribute(String attribute, Object value) 設置Session屬性。value參數能夠爲任何Java Object。一般爲Java Bean。value信息不宜過大
String getAttribute(String attribute) 返回Session屬性
Enumeration getAttributeNames() 返回Session中存在的屬性名
void removeAttribute(String attribute) 移除Session屬性
String getId() 返回Session的ID。該ID由服務器自動建立,不會重複
long getCreationTime() 返回Session的建立日期。返回類型爲long,常被轉化爲Date類型,例如:Date createTime = new Date(session.getCreationTime())
long getLastAccessedTime() 返回Session的最後活躍時間。返回類型爲long
int getMaxInactiveInterval() 返回Session的超時時間。單位爲秒。超過該時間沒有訪問,服務器認爲該Session失效
void setMaxInactiveInterval(int second) 設置Session的超時時間。單位爲秒
void putValue(String attribute, Object value)
不推薦的方法。已經被setAttribute(String attribute, Object Value)替代
Object getValue(String attribute) 不被推薦的方法。已經被getAttribute(String attr)替代
boolean isNew() 返回該Session是不是新建立的
void invalidate() 使該Session失效
Session對瀏覽器的要求
雖然Session保存在服務器,對客戶端是透明的,它的正常運行仍然須要客戶端瀏覽器的支持。這是由於Session須要使用Cookie做爲識別標誌。HTTP協議是無狀態的,Session不能依據HTTP鏈接來判斷是否爲同一客戶,所以服務器向客戶端瀏覽器發送一個名爲JSESSIONID的Cookie,它的值爲該Session的id(也就是HttpSession.getId()的返回值)。(筆記:JESSIONID = HttpSession.getId())Session依據該Cookie來識別是否爲同一用戶。
該Cookie爲服務器自動生成的,它的maxAge屬性通常爲-1,表示僅當前瀏覽器內有效,而且各瀏覽器窗口間不共享,關閉瀏覽器就會失效。(默認值是-1,表示關閉瀏覽器,cookie就會消失。若是是正數,表示從如今開始,即將過時的seconds。)所以同一機器的兩個瀏覽器窗口訪問服務器時,會生成兩個不一樣的Session。可是由瀏覽器窗口內的連接、腳本等打開的新窗口(也就是說不是雙擊桌面瀏覽器圖標等打開的窗口)除外。這類子窗口會共享父窗口的Cookie,所以會共享一個Session。
注意:新開的瀏覽器窗口會生成新的Session,但子窗口除外。子窗口會共用父窗口的Session。例如,在連接上右擊,在彈出的快捷菜單中選擇"在新窗口中打開"時,子窗口即可以訪問父窗口的Session。
若是客戶端瀏覽器將Cookie功能禁用,或者不支持Cookie怎麼辦?例如,絕大多數的手機瀏覽器都不支持Cookie。Java Web提供了另外一種解決方案:URL地址重寫。
URL地址重寫
URL地址重寫是對客戶端不支持Cookie的解決方案。URL地址重寫的原理是將該用戶Session的id信息重寫到URL地址中。服務器可以解析重寫後的URL獲取Session的id。這樣即便客戶端不支持Cookie,也可使用Session來記錄用戶狀態。HttpServletResponse類提供了encodeURL(String url)實現URL地址重寫,例如:
<a href="<%= response.encodeURL("index.jsp?c=1&wd=Java") %>">Homepage</a>該方法會自動判斷客戶端是否支持Cookie。若是客戶端支持Cookie,會將URL原封不動地輸出來。若是客戶端不支持Cookie,則會將用戶Session的id重寫到URL中。重寫後的輸出多是這樣的:
<td><a href="index.jsp;jsessionid=0CCD096E7F8D97B0BE608AFDC3E1931E?c=1&wd=Java">Homepage</a> 即在文件名的後面,在URL參數的前面添加了字符串";jsessionid=XXX"。其中XXX爲Session的id。分析一下能夠知道,增添的jsessionid字符串既不會影響請求的文件名,也不會影響提交的地址欄參數。用戶單擊這個連接的時候會把Session的id經過URL提交到服務器上,服務器經過解析URL地址得到Session的id。
若是是頁面重定向(Redirection),URL地址重寫能夠這樣寫:
<% if("administrator".equals(userName)){response.sendRedirect(response.encodeRedirectURL("administrator.jsp")); return;} %> 效果跟response.encodeURL(String url)是同樣的:若是客戶端支持Cookie,生成原URL地址,若是不支持Cookie,傳回重寫後的帶有jsessionid字符串的地址。
對於WAP程序,因爲大部分的手機瀏覽器都不支持Cookie,WAP程序都會採用URL地址重寫來跟蹤用戶會話。好比用友集團的移動商街等。
注意:TOMCAT判斷客戶端瀏覽器是否支持Cookie的依據是請求中是否含有Cookie。儘管客戶端可能會支持Cookie,可是因爲第一次請求時不會攜帶任何Cookie(由於並沒有任何Cookie能夠攜帶),URL地址重寫後的地址中仍然會帶有jsessionid。當第二次訪問時服務器已經在瀏覽器中寫入Cookie了,所以URL地址重寫後的地址中就不會帶有jsessionid了。
Session中禁止使用Cookie
既然WAP上大部分的客戶瀏覽器都不支持Cookie,索性禁止Session使用Cookie,統一使用URL地址重寫會更好一些。Java Web規範支持經過配置的方式禁用Cookie。下面舉例說一下怎樣經過配置禁止使用Cookie。
打開項目sessionWeb的WebRoot目錄下的META-INF文件夾(跟WEB-INF文件夾同級,若是沒有則建立),打開context.xml(若是沒有則建立),編輯內容以下:
/META-INF/context.xml
<?xml version='1.0' encoding='UTF-8'?> <Context path="/sessionWeb" cookies="false"> </Context> 或者修改Tomcat全局的conf/context.xml,修改內容以下:
context.xml
<!-- The contents of this file will be loadedfor each web application --> <Context cookies="false"> <!-- ... 中間代碼略 --> </Context> 部署後TOMCAT便不會自動生成名JSESSIONID的Cookie,Session也不會以Cookie爲識別標誌,而僅僅以重寫後的URL地址爲識別標誌了。
注意:該配置只是禁止Session使用Cookie做爲識別標誌,並不能阻止其餘的Cookie讀寫。也就是說服務器不會自動維護名爲JSESSIONID的Cookie了,可是程序中仍然能夠讀寫其餘的Cookie。
Session與Cookie的比較
Cookie與Session均可以進行會話跟蹤,可是實現的原理不太同樣。通常狀況下兩者都可以知足需求,但有時候不可使用Cookie,有時候不可使用Session。下面經過比較說明兩者的特色以及適用的場合。
5.3.1 從存取方式上比較
Cookie中只能保存ASCII字符串,若是須要存取Unicode字符或者二進制數據,須要進行UTF-8,GBK或者BASE64等方式的編碼。Cookie中也不能直接存取Java對象。若要存儲稍微複雜的信息,使用Cookie是比較困難的。
而Session中能夠存取任何類型的數據,包括而不限於String、Integer、List、Map等。Session中也能夠直接保存Java Bean乃至任何Java類,對象等,使用起來很是方便。能夠把Session看作是一個Java容器類。
從隱私安全上比較
Cookie存儲在客戶端瀏覽器中,對客戶端是可見的,客戶端的一些程序可能會窺探、複製甚至修改Cookie中的內容。而Session存儲在服務器上,對客戶端是透明的,不存在敏感信息泄露的危險。
若是選用Cookie,比較好的辦法是,敏感的信息如帳號密碼等儘可能不要寫到Cookie中。最好是像Google、Baidu那樣將Cookie信息加密,提交到服務器後再進行解密,保證Cookie中的信息只有本身能讀得懂。而若是選擇Session就省事多了,反正是放在服務器上,Session裏任何隱私均可以。
從有效期上比較
使用過Google的人都知道,若是登陸過Google,則Google的登陸消息長期有效。用戶沒必要每次訪問都從新登陸,Google會長久地記錄該用戶的登陸信息。要達到這種效果,使用Cookie會是比較好的選擇。只須要設置Cookie的maxAge屬性爲一個很大很大的數字或者Integer.MAX_VALUE就能夠了。Cookie的maxAge屬性支持這樣的效果。
使用Session理論上也能實現這種效果。只要調用方法setMaxInactiveInterval(Integer. MAX_VALUE)不就能夠了麼。可是因爲Session依賴於名爲JSESSIONID的Cookie,而Cookie JSESSIONID的maxAge默認爲-1,只要關閉了瀏覽器該Session就會失效,所以Session不能實現信息永久有效的效果。使用URL地址重寫也不能實現。
並且若是設置Session的超時時間過長,服務器累計的Session就會越多,越容易致使內存溢出。
筆記:爲何不能使用session實現登錄信息長時間有效:
1. session須要依賴jsessionid,而jsessionid的maxAge爲-1,也就是當關閉瀏覽器後存在cookie中的jsessionid就會丟失,當該客戶端再次請求服務器時,即便該客戶端上次會話對應的session對象仍然存在於服務器內存中(由於設置了maxInactiveInterval很大),可是該客戶端的第二次請求沒有jsessionid,因此服務器沒法根據jsessionid找到上次訪問時的session對象。
2. 若是設置session超時時間過長,服務器累計session就會越多,越容易致使內存溢出。
從對服務器的負擔上比較
Session是保存在服務器端的,每一個用戶都會產生一個Session。若是併發訪問的用戶很是多,會產生很是多的Session,消耗大量的內存。所以像Google、Baidu、Sina這樣併發訪問量極高的網站,是不太可能使用Session來追蹤客戶會話的。
而Cookie保存在客戶端,不佔用服務器資源。若是併發瀏覽的用戶很是多,Cookie是很好的選擇。對於Google、Baidu、Sina來講,Cookie也許是惟一的選擇。
從瀏覽器支持上比較
Cookie是須要客戶端瀏覽器支持的。若是客戶端禁用了Cookie,或者不支持Cookie,則會話跟蹤會失效。對於WAP上的應用,常規的Cookie就派不上用場了。
若是客戶端瀏覽器不支持Cookie,須要使用Session以及URL地址重寫。須要注意的是全部的用到Session程序的URL都要使用response.encodeURL(String URL)或者response.encodeRedirectURL(String URL)進行URL地址重寫,不然致使Session會話跟蹤失敗。對於WAP應用來講,Session+URL地址重寫也許是它惟一的選擇。
若是客戶端支持Cookie,則Cookie既能夠設爲僅本瀏覽器窗口(當前打開的這個瀏覽器窗口選項卡)以及其子窗口內有效(把maxAge設爲-1),也能夠設爲全部瀏覽器窗口( 同一進程多個瀏覽器選項卡或者多個進程)內有效(把maxAge設爲某個大於0的整數)。但Session只能在本瀏覽器窗口以及其子窗口內有效。若是兩個瀏覽器窗口互不相干,它們將使用兩個不一樣的Session。session是服務器端對象與瀏覽器沒有關係,若是客戶端瀏覽器存有表示當前session的cookie中的jsessionid,那麼就能夠訪問到session,若是沒有就訪問不到session。
從跨域名上比較
Cookie支持跨域名訪問,例如將domain屬性設置爲".helloweenvsfei.com",則以".helloweenvsfei.com"爲後綴的全部域名都可以訪問該Cookie。跨域名Cookie如今被普遍用在網絡中,例如Google、Baidu、Sina等。而Session則不會支持跨域名訪問。Session僅在他所在的域名內有效。
注意:僅使用Cookie或者僅使用Session可能實現不了理想的效果。這時應該嘗試一下同時使用Cookie與Session。Cookie與Session的搭配使用在實際項目中會實現絢爛多姿的效果。
本章小結
Cookie是早期的會話跟蹤技術,它將信息保存到客戶端瀏覽器中。瀏覽器訪問網站時會攜帶這些Cookie信息,達到鑑別身份的目的。
Session是在Cookie基礎上創建的會話跟蹤技術,它將信息保存在服務器端,Session中可以存儲負責的Java對象,所以使用更加方便。Session依賴於名爲JSESSIONID的Cookie。
若是客戶端瀏覽器不支持Cookie,或者禁用了Cookie,仍然能夠經過使用URL地址重寫來使用Session。