1. 程式人生 > >Session理解

Session理解

Cookie和Session都可以實現會話跟蹤,將上一次的請求傳入下一次內,但它們的實現方式有一個顯著的區別,如下:

  • Cookie:將當前會話的資訊存在瀏覽器端,每次請求時將Cookie資訊傳入伺服器
  • Session:將會話的資訊存在伺服器端,瀏覽器儲存一個JSESSIONID,每次傳入JSESSIONID去取資訊

很顯然,2種會話跟蹤的實現方式,Session是在伺服器端保持狀態的方案,Cookie實在瀏覽器端保持狀態的方案。對於Cookie而言,如果傳輸的狀態資訊較多,將較大的降低網路傳輸的效率和增大伺服器的處理難度,因此Session顯然在這種情況下是比較好的。

Session是基於Cookie來實現的,每次為一個客戶端建立一個Session物件時,其實也是建立了一個Cookie物件,這個Cookie物件儲存的就是JSESSIONID

。伺服器為每一個客戶端建立的Session物件儲存在伺服器的記憶體中,Session物件有一個超時間隔時間,當離最後一次訪問的時間超過的這個間隔時間之後,這個Session物件將會失效,變成一個垃圾物件,等待回收。預設超時間隔時間為30分鐘,可以在<tomcat安裝目錄>\conf\Web.xml檔案裡面配置,如下:

<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後。