Servlet學習筆記(七):Session詳解
Session是伺服器端技術,伺服器在執行時可以為每個使用者的瀏覽器建立一個其獨享的Session物件,由於Session為使用者瀏覽器獨享,所以使用者在訪問伺服器的web資源時,可以把各自的資源放在各自的Session中,當用戶再去訪問伺服器中的其他web資源時,其他web資源再從使用者各自的Session中取出資料為使用者服務。
一、Session基礎知識
1、工作原理:
Cookie類似於檢查客戶身上的“通行證”來確定客戶身份的話,那麼 Session 機制就是通過檢查伺服器上的“客戶明細表”來確認客戶身份。Session相當於程式在伺服器上建立的一份客戶檔案,客戶來訪的時候只需要查詢客戶檔案表就可以了。
2、實現方式。
1)通過 Cookie 實現——將Session的 ID 放入 Cookie。
A、Session 的實現需要使用Cookie作為識別標誌。Session 不能依據 HTTP 連線判斷是否為同一個客戶,因此伺服器向客戶端傳送一個名為JSESSIONID的 Cookie ,它的值為該Session的ID。Sessin依據該Cookie來識別是否為同一使用者。
這邊的JSESSIONID只是個名字,可以隨便修改的。配置伺服器的<Context sessionCookieName=" XXX ">設定。
B、該Cookie 為伺服器自動生成的,它的 maxAge屬性一般為 -1,表示僅當前瀏覽器內有效(包括字視窗),關閉瀏覽器失效,各瀏覽器不共享。
這會是一個問題,當你關閉瀏覽器,在重開,就會是另一個Cookie。解決辦法:伺服器在建立Session的時候回寫一個同名的Cookie,並設定maxAge值即可,注意有path(見下圖)
// 解決自動生成的cookie為臨時性問題,回寫一個同名Cookie回去 Cookie cookie = new Cookie("JSESSIONID",session.getId()); cookie.setMaxAge(session.getMaxInactiveInterval()); cookie.setPath(this.getServletContext().getContextPath()); response.addCookie(cookie);
C、注意:第一次訪問的時候,因為JSESSIONID是放在Cookie中,伴隨瀏覽器訪問傳入,所以第一次訪問的時候是沒有的。request.getRequestedSessionId() 返回為空。這點在Firefox試驗是沒問題的。但是Chrome中會有出入。
Firefox在第一次訪問的時候,請求資訊中是沒有 JSESSIONID資料的,請求結束,伺服器返回。如下:
但是,Chrome在第一次訪問的時候,請求中即會有一個臨時的JSESSIONID,然後返回一個。如下:
問題:
有一種解釋為:第一次訪問的時候,在你的程式第一次訪問伺服器的時候,服務端並不知道你的客戶端瀏覽器是否支援cookie,因此,當你第一次請求發起的時候,服務端會預設url重寫,也就是將session id寫到url中傳遞。
或者只是瀏覽器的支援問題?暫時沒解決。
2)通過URL 重寫實現——將Session的 ID 重寫到URL地址中。
A、針對客戶端不支援Cookie的情況,可以通過 URL 重寫實現Session 。
B、response.encodeURL(String url)實現 URL 地址的重寫。如果重定向可以這麼寫:response.sendRedirect(response.encodeRedirectURL("/"))
// 通過 重寫URL實現 response.encodeURL("/"); response.encodeRedirectURL("/"); response.sendRedirect(response.encodeRedirectURL("/"));
C、可以在伺服器配置,取消重寫的功能。配置Tomcat 的<Context disableURLRewriting="true">即可。
3、Session 的 建立
封裝在javax.servlet.http.HttpSession 物件中,可以通過request.getSession()獲取。
HttpSession session = request.getSession();//不存在,返回空
HttpSession session = request.getSession(true);//不存在,新建一個
4、Session 的ID。
String sessionId = session.getId();
5、Session 的時間。
1)有效期。
// 3-1 有效期
// get/set MaxInactiveInterval可以設定和獲取session的有效期 單位為 秒
// 也可以通過 <session-config>標籤配置在web.xml中 ,單位為分鐘
// tomcat自身的config/web.xml 預設配置session有效期為 30 分鐘
// 如通過setMaxInactiveInterval設定過有效時間,這段程式碼注掉,時間還是不會改變。
session.setMaxInactiveInterval(1000 * 5);
int time = session.getMaxInactiveInterval();
2)建立時間。
// 3-2 建立時間
long createTime = session.getCreationTime();//返回long
Date createDate = new Date(createTime);
logger.debug("Session建立的時間為 : " + formatDate(createDate));
3)最近訪問時間。
// 3-3 最近訪問時間
// 客戶端只要訪問伺服器,不管有沒有讀寫session,伺服器都會更新最近訪問時間,並維護本session
long accessedTime = session.getLastAccessedTime();//返回long
Date accessedDate = new Date(accessedTime);
logger.debug("Session最近訪問的時間為 : " + formatDate(accessedDate));
6、Session路徑
Session 在客戶端對應同一個視窗,沒有路徑訪問問題,同一個servletContext 下的servlet/jsp共享同一個Session 。前提是同一個客戶端視窗。
二、Session 的生命週期
1)Session在使用者第一次訪問伺服器的時候自動建立。只有訪問JSP、Servlet等程式才會建立Session(是訪問到getSession()程式碼時), 只訪問 HTML、 等靜態資源並不會建立Session。 如果尚未生成Session ,也可以使用request.getSession(true)強制生成。
2)Session生成後,只要使用者繼續訪問,伺服器就會更新Session 的最後訪問時間,並維護該 Session 。使用者每訪問伺服器一次,無論是否讀寫 Session ,伺服器都認為該使用者的 Session “活躍(active)”了一次。
3)關閉瀏覽器,不會讓 Session 結束,Session 是伺服器管理的,只有當 session.invalidate() 程式碼或者配置好的有效時間<session-comfig>到了,Session 才會結束。
三、Session的常用方法。
四、測試程式碼如下:
package servlet.session;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.log4j.Logger;
/**
*
* BaseSession.java
*
* @title Session
* @description
* @author SAM-SHO
* @Date 2014-10-12
*/
public class BaseSession extends HttpServlet {
private static final long serialVersionUID = 1L;
private Logger logger = Logger.getLogger(this.getClass());
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//
boolean isValid = request.isRequestedSessionIdValid();
logger.debug("請求帶過來的session是否有效 : " + isValid);
// 第一次訪問的時候 firefox 為空,而chrome 確是有值的,但是和下面建立的session不是同一個
String seesionId = request.getRequestedSessionId();
logger.debug("request獲取的SessionID : " + seesionId);
boolean isFromCookie = request.isRequestedSessionIdFromCookie();
boolean isFromUrl = request.isRequestedSessionIdFromURL();
logger.debug("是否是通過Cookie實現: " + isFromCookie + " | 是否是通過URL實現: " + isFromUrl);
// 1-Session的建立
// HttpSession session = request.getSession();//不存在,返回空
HttpSession session = request.getSession(true);//不存在,新建一個
logger.debug("獲取到的Session 為 : " + session.getClass().getName());
// 2-Session的ID
String sessionId = session.getId();
logger.debug("建立的 Session的ID 為 : " + sessionId);
// 3-session的時間:三個時間構成了session 的生命週期
// 3-1 有效期
// get/set MaxInactiveInterval可以設定和獲取session的有效期 單位為 秒
// 也可以通過 <session-config>標籤配置在web.xml中 ,單位為分鐘
// tomcat自身的config/web.xml 預設配置session有效期為 30 分鐘
// 如通過setMaxInactiveInterval設定過有效時間,這段程式碼注掉,時間還是不會改變。
session.setMaxInactiveInterval(1000 * 5);
int time = session.getMaxInactiveInterval();
logger.debug("Session的有效期 為 : " + time);
// 3-2 建立時間
long createTime = session.getCreationTime();//返回long
Date createDate = new Date(createTime);
logger.debug("Session建立的時間為 : " + formatDate(createDate));
// 3-3 最近訪問時間
// 客戶端只要訪問伺服器,不管有沒有讀寫session,伺服器都會更新最近訪問時間,並維護本session
long accessedTime = session.getLastAccessedTime();//返回long
Date accessedDate = new Date(accessedTime);
logger.debug("Session最近訪問的時間為 : " + formatDate(accessedDate));
// 4-常用方法
// 4-1設定 Attribute 是key-value型別
// key為String 型別, value為 Object 。可以放置javaBean。比Cookie強大。
session.setAttribute("userName", "Sam-Sho");
String userName = (String) session.getAttribute("userName");
logger.debug("Session中放置的資料 : " + userName);
session.removeAttribute("userName");
// 4-2 讓session失效
session.invalidate();
// 4-3 其他與session有關的一些方法
String seesionId2 = request.getRequestedSessionId();//
logger.debug("request獲取的SessionID 2: " + seesionId2);
boolean isFromCookie2 = request.isRequestedSessionIdFromCookie();
boolean isFromUrl2 = request.isRequestedSessionIdFromURL();
logger.debug("是否是通過Cookie實現2: " + isFromCookie2 + " | 是否是通過URL實現2: " + isFromUrl2);
// // 通過 重寫URL實現
// response.encodeURL("/");
// response.encodeRedirectURL("/");
// response.sendRedirect(response.encodeRedirectURL("/"));
}
/**
* 簡單轉換時間
* @param date
* @return
*/
private String formatDate(Date date){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String strDate = format.format(date);
return strDate;
}
}
【輸出】
[JavaWeb] [2014-10-12 11:54:08,345] [DEBUG] [MyFilter:40] - 上下文路徑:/JavaWeb
[JavaWeb] [2014-10-12 11:54:08,345] [DEBUG] [MyFilter:41] - 訪問的servlet或者jsp的路徑 : /servlet/BaseSession
[JavaWeb] [2014-10-12 11:54:08,348] [DEBUG] [BaseSession:31] - 請求帶過來的session是否有效 : false
[JavaWeb] [2014-10-12 11:54:08,348] [DEBUG] [BaseSession:35] - request獲取的SessionID : 9B582560CB3588E3205030C0B9A9E1D7
[JavaWeb] [2014-10-12 11:54:08,348] [DEBUG] [BaseSession:39] - 是否是通過Cookie實現: true | 是否是通過URL實現: false
[JavaWeb] [2014-10-12 11:54:08,361] [DEBUG] [BaseSession:47] - 獲取到的Session 為 : org.apache.catalina.session.StandardSessionFacade
[JavaWeb] [2014-10-12 11:54:08,364] [DEBUG] [BaseSession:51] - 建立的 Session的ID 為 : 95698550D17BB0465D6EC43179A984DB
[JavaWeb] [2014-10-12 11:54:08,364] [DEBUG] [BaseSession:63] - Session的有效期 為 : 1200
[JavaWeb] [2014-10-12 11:54:08,364] [DEBUG] [BaseSession:69] - Session建立的時間為 : 2014-10-12 11:54:08
[JavaWeb] [2014-10-12 11:54:08,365] [DEBUG] [BaseSession:75] - Session最近訪問的時間為 : 2014-10-12 11:54:08
[JavaWeb] [2014-10-12 11:54:08,367] [DEBUG] [BaseSession:85] - Session中放置的資料 : Sam-Sho
[JavaWeb] [2014-10-12 11:54:08,389] [DEBUG] [BaseSession:96] - request獲取的SessionID 2: 9B582560CB3588E3205030C0B9A9E1D7
[JavaWeb] [2014-10-12 11:54:08,389] [DEBUG] [BaseSession:100] - 是否是通過Cookie實現2: true | 是否是通過URL實現2: false
五、Session 和 Cookie 的比較。
1、從存取方式上比較:
1)Cookie 中只能存ASCII字串,其他需要編碼。不能直接存 java 物件。
2)Session 中可以存取任何型別的資料,直接儲存JavaBean。
2、從隱私安全上比較
1)Cookie儲存在客戶端,會存在風險。所以一般一些敏感資訊,如密碼等儘量不要放入 Cookie,並且對Cookie 資訊加密。提交到伺服器在解密,保證安全性。
2)Session 儲存在伺服器,安全多了。
3、從有效期上比較
1)Cookie 的有效期只要設定Cookie 的maxAge即可。
2)Session 如果設定的有效期過長,會導致伺服器累計的 Session 過多,導致記憶體溢位。
4、從對伺服器負擔上比較
1)Cookie無負擔,所以比如大型的網站,電商等都會使用Cookie 追蹤客戶會話。
2)Session 過多就會影響伺服器了。