Session理解
Cookie和Session都可以實現會話跟蹤,將上一次的請求傳入下一次內,但它們的實現方式有一個顯著的區別,如下:
- Cookie:將當前會話的資訊存在瀏覽器端,每次請求時將Cookie資訊傳入伺服器
- Session:將會話的資訊存在伺服器端,瀏覽器儲存一個JSESSIONID,每次傳入JSESSIONID去取資訊
很顯然,2種會話跟蹤的實現方式,Session是在伺服器端保持狀態的方案,Cookie實在瀏覽器端保持狀態的方案。對於Cookie而言,如果傳輸的狀態資訊較多,將較大的降低網路傳輸的效率和增大伺服器的處理難度,因此Session顯然在這種情況下是比較好的。
Session是基於Cookie來實現的,每次為一個客戶端建立一個Session物件時,其實也是建立了一個Cookie物件,這個Cookie物件儲存的就是JSESSIONID
<session-config>
<session-timeout>30</session-timeout>
</session-config>
注意conf\Web.xml檔案配置和web應用程式的web.xml檔案配置的作用域。
當瀏覽器不支援Cookie或關閉Cookie時,便不能用Cookie的方式來實現Session,這種情況應該很少。此時可以利用URL重寫實現Cookie跟蹤。按照正常訪問網站的規則,使用者是直接輸入地址進入一個主頁面,然後通過超連結進入其他頁面,而直接輸入地方訪問其他頁面時視為非法訪問,不建立Session物件。當用超連結訪問時,瀏覽器將會話標識號作為引數附加在超連結的URL地址後面就叫URL重寫。HttpServletResponse介面中定義了兩個完全用於URL重寫的方法:
- encodeURL:用於對超連結和form表單的action屬性中設定的URL進行重寫
- encodeRedirectURL:用於對要傳遞給HttpServletResponse.sendRedirect方法的URL進行重寫
對encodingURL的測試如下:
@WebServlet("/Session1")
public class SessionServlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
HttpSession session=req.getSession();
Integer sessionCount=(Integer)session.getAttribute("count");
int count=0;
if(sessionCount!=null){
count=sessionCount.intValue();
}
out.println("當前會話中發生了"+(++count)+"次訪問<br>");
session.setAttribute("count",new Integer(count));
count=0;
ServletContext application=getServletContext();
Integer applicationCount=(Integer) application.getAttribute("count");
if(applicationCount!=null){
count=applicationCount.intValue();
}
out.println("Web應用程式中發生了"+(++count)+"次訪問<br>");
application.setAttribute("count",new Integer(count));
out.println("<a href='"+resp.encodeURL("Session2")+"'>訪問Session2");
}
}
@WebServlet("/Session2")
public class SessionServlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
HttpSession session=req.getSession();
Integer sessionCount=(Integer)session.getAttribute("count");
int count=0;
if(sessionCount!=null){
count=sessionCount.intValue();
}
out.println("當前會話發生了"+(++count)+"次訪問<br>");
session.setAttribute("count",new Integer(count));
count=0;
ServletContext application=getServletContext();
Integer applicationCount=(Integer)application.getAttribute("count");
if(applicationCount!=null){
count=applicationCount.intValue();
}
out.println("Web應用程式發生了"+(++count)+"次訪問<br>");
application.setAttribute("count",new Integer(count));
out.println("<a href='"+resp.encodeURL("Session1")+"'>訪問Session1</a>");
}
}
當訪問Session1時,檢視網頁原始碼如下:
點選超連結,位址列如下:
對於不支援Cookie而言的瀏覽器,實現Session跟蹤就是以這種形式實現的,如果瀏覽器支援Cookie也採用了這種實現方式的話,第一次訪問會將會話標識號附加到URL路徑後,但後續響應訊息則不在附加,這是因為建立Session時總是將會話標識號以Cookie的形式傳送給瀏覽器,如果瀏覽器不支援或關閉Cookie,則不會回傳這個標識號,如果支援,會回傳,則伺服器知道瀏覽器支援Cookie,便不在附加標識號到URL後。第一次訪問時伺服器不知道瀏覽器支不支援,所以也會附加標識號到URL後。