1. 程式人生 > >詳解Session的生命週期

詳解Session的生命週期

在進行WEB Application開發的時候,很多程式設計師在理解Session的時候,常常會被誤導,錯誤的認為:一個瀏覽器只有一個Session, 瀏覽器關閉Session就消失了。其實這是不正確的。(很多程式設計師是去baidu,或者google一下,只解決了當下的問題,但是對於更深次的問題沒有仔細思考!)

要了解Session首先要知道一個概念:Session的銷燬只有兩種情況:

第一:成功地呼叫了 session.invalidate()方法。

第二:前後兩次請求超出了session指定的生命週期時間。其中Session的生命週期時間可以在web.xml配置,預設30分鐘。

在web.xml檔案中可以做如下配置:
<session-config>
      <session-timeout>5</session-timeout>
</session-config>


上述配置表示:session的有效時間為 5分鐘。注意:單位是分鐘。

如何來證明關閉瀏覽器的時候Session沒有銷燬呢?我們可以建立一個SessionListener 此監聽器專門用來監聽Session的生命週期的。

此處插入樣例程式碼:

package com.mrbean.commons.utils;

import java.util.Date;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.hibernate.HibernateException;
import org.hibernate.Session;

public class SessionListener implements HttpSessionListener{

//監聽Session的建立
public void sessionCreated(HttpSessionEvent event) {
System.out.println("session已建立,時間:"+new Date().toLocaleString());

                System.out.println(event.getSession().getId());
//此處省略一些程式碼
}

//監聽Session的銷燬
public void sessionDestroyed(HttpSessionEvent event) {
System.out.println("session已銷燬,時間:"+new Date().toLocaleString());

                System.out.println(event.getSession().getId());
//此處省略一些程式碼
}

/**更新*/
public void updateObject(Object entity)
{
Session session=HibernateUtils.getSession();
try {
session.getTransaction().begin();
session.update(entity);
session.getTransaction().commit();
} catch (HibernateException e) {
session.getTransaction().rollback();
e.printStackTrace();
} finally {
HibernateUtils.closeConnection(session);
}
}
}

web.xml中的配置Session監聽的程式碼:

<listener>
<listener-class>com.mrbean.commons.utilsSessionListener</listener-class>
</listener>

關於Session失效時間的配置:

<session-config>
    <session-timeout>5</session-timeout>
</session-config>

 配置完畢後,可以做個測試。 當瀏覽器關閉後此監聽器的 sessionDestroyed方法並沒有執行,而是在5分鐘左右才會觸發sessionDestroyed,當然 再開啟瀏覽器的時候

ssessionCreated 會自動呼叫。 關閉5分鐘後sessionDestroyed 又會自動呼叫,通過getID方法大家可以判斷是否為同一個Session。

控制檯監控,獲得輸出資訊:

session已建立,時間:2014-11-30 17:04:04
D5AB6933ABFFFC6F65736C188CF562CE

session已銷燬,時間:2014-11-30 17:10:35
D5AB6933ABFFFC6F65736C188CF562CE

(個人筆記本上做的測試,時間上存在一些誤差),存在一些時間誤差。

這個時候通過瀏覽器的關閉按鈕,強制關閉瀏覽器。

然後開啟一個新的瀏覽器,直接輸入需要訪問的頁面地址,我們發現不用登陸系統,可以直接開啟你想訪問的頁面。(而第一次訪問該頁面時,需要首先登陸系統,才可以訪問。)

注意:如果沒有任何配置的情況下,關閉瀏覽器30分鐘後Session才會消失的。

我們可以利用這個Session監聽做什麼呢? 最典型的就是利用 SessionListener  的sessionDestroyed方法來記錄使用者非正常退出的時間。使用者在訪問某個網站的時候(目前很多網站都應用了這種方式) 顯示了使用者的最後登入時間。 此時間如何獲取?

在這裡分兩種情況:

        Case 1:如果使用者按"退出" 按鈕那就好說了,跳轉到action中,記錄下使用者退出的時間。 儲存到持久層中。
        Case2: 如果使用者非正常退出, 在沒有配置Session的情況下,預設會在30分鐘後呼叫sessionDestroyed。那麼我們同樣可以在此獲取使用者退出的時間,在

sessionDestroyed 呼叫業務邏輯完成我們想要實現的功能。

        有關Session第2個典型的應用就是Session中儲存了使用者的登入資訊, 那麼就可以訪問使用者許可權的一些頁面。


        有關這個應用要注意一個問題:儲存到session中的 User物件一定要實現Serializable介面。 Serializable的作用可以參考相關資料。正常情況下當我們做測試的時候關閉Tomcat 大家會在Tomcat安裝目錄\work\Catalina\localhost\專案名 資料夾下面看到有一個SESSIONS.ser 的檔案。

        此檔案就是Session在Tomcat停止的時候 持久化到硬碟中的檔案。 所有當前訪問的使用者Session都儲存到此檔案中。 Tomcat啟動成功後.SESSIONS.ser  又會反序列化到記憶體中,所以啟動成功後此檔案就消失了。 所以正常情況下從啟Tomcat使用者是不需要登入的。 注意有個前提就是儲存到Session裡面的user物件所對應的User類必須要序列化才可以。

另外補充:

Session儲存在伺服器端,一般為了防止在伺服器的記憶體中(為了高速存取),Sessinon在使用者訪問第一次訪問伺服器時建立,需要注意只有訪問JSP、Servlet等程式時才會建立Session,只訪問HTML、IMAGE等靜態資源並不會建立Session,可呼叫request.getSession(true)強制生成Session。

  Session什麼時候失效?
  1. 伺服器會把長時間沒有活動的Session從伺服器記憶體中清除,此時Session便失效。Tomcat中Session的預設失效時間為20分鐘。
  2. 呼叫Session的invalidate方法。

  Session對瀏覽器的要求:
  雖然Session儲存在伺服器,對客戶端是透明的,它的正常執行仍然需要客戶端瀏覽器的支援。這是因為Session需要使用Cookie作為識別標誌。HTTP協議是無狀態的,Session不能依據HTTP連線來判斷是否為同一客戶,因此伺服器向客戶端瀏覽器傳送一個名為JSESSIONID的Cookie,它的值為該Session的id(也就是HttpSession.getId()的返回值)。Session依據該Cookie來識別是否為同一使用者。


  該Cookie為伺服器自動生成的,它的maxAge屬性一般為-1,表示僅當前瀏覽器內有效,並且各瀏覽器視窗間不共享,關閉瀏覽器就會失效。因此同一機器的兩個瀏覽器視窗訪問伺服器時,會生成兩個不同的Session。但是由瀏覽器視窗內的連結、指令碼等開啟的新視窗(也就是說不是雙擊桌面瀏覽器圖示等開啟的視窗)除外。這類子視窗會共享父視窗的Cookie,因此會共享一個Session。

     注意:新開的瀏覽器視窗會生成新的Session,但子視窗除外。子視窗會共用父視窗的Session。例如,在連結上右擊,在彈出的快捷選單中選擇"在新視窗中開啟"時,子視窗便可以訪問父視窗的Session。

        如果客戶端瀏覽器將Cookie功能禁用,或者不支援Cookie怎麼辦?例如,絕大多數的手機瀏覽器都不支援Cookie。Java Web提供了另一種解決方案:URL地址重寫。

  URL地址重寫是對客戶端不支援Cookie的解決方案。URL地址重寫的原理是將該使用者Session的id資訊重寫到URL地址中。伺服器能夠解析重寫後的URL獲取Session的id。這樣即使客戶端不支援Cookie,也可以使用Session來記錄使用者狀態。HttpServletResponse類提供了encodeURL(String url)實現URL地址重寫,該方法會自動判斷客戶端是否支援Cookie。如果客戶端支援Cookie,會將URL原封不動地輸出來。如果客戶端不支援Cookie,則會將使用者Session的id重寫到URL中。

  注意:TOMCAT判斷客戶端瀏覽器是否支援Cookie的依據是請求中是否含有Cookie。儘管客戶端可能會支援Cookie,但是由於第一次請求時不會攜帶任何Cookie(因為並無任何Cookie可以攜帶),URL地址重寫後的地址中仍然會帶有jsessionid。當第二次訪問時伺服器已經在瀏覽器中寫入Cookie了,因此URL地址重寫後的地址中就不會帶有jsessionid了。

相關推薦

例項化vue發生了什麼?(vue生命週期)

例項化vue發生了什麼?(詳解vue生命週期) 本文將對vue的生命週期進行詳細的講解,讓你瞭解一個vue例項的誕生都經歷了什麼~ 我在Github上建立了一個存放vue筆記的倉庫,以後會陸續更新一些知識和專案中遇到的坑,有興趣的同學可以去看看哈(歡迎star)! 傳送門 例項化一個Vue c

Docker 命令-容器生命週期管理(RUN)

一、概況 run: 建立一個新的容器並執行一個命令; 二、RUN詳情 2.1 語法 $ sudo docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 具體版本特性,可通過命令檢視引數說明 $ sudo docke

React生命週期及鉤子函式

父元件 import React , {Component} from 'react' import Son from './Son' class Father extends Component { constructor(props){

vue生命週期(重點!!)

首先,每個Vue例項在被建立之前都要經過一系列的初始化過程,這個過程就是vue的生命週期。首先看一張圖吧~這是官方文件上的圖片相信大家一定都會很熟悉:    可以看出在vue——整個的生命週期中會有很多鉤子函式提供給我們在vue生命週期的不同時可進行操作,那麼先列出所

例項化vue發生了什麼(vue生命週期)

const app = new Vue({ el:"#app', data:{ message:'hello,lifePeriod' }, methods:{ init(){ console.log('這是一個方法!'

Android基礎:3分鐘Activity生命週期

前言 Android開發中,會經常接觸 Activity,所以深入瞭解Activity生命週期非常重要 本文將深入講解Activity生命週期 的相關內容 閱讀本文 需 3分鐘

Session生命週期

在進行WEB Application開發的時候,很多程式設計師在理解Session的時候,常常會被誤導,錯誤的認為:一個瀏覽器只有一個Session, 瀏覽器關閉Session就消失了。其實這是不正確的。(很多程式設計師是去baidu,或者google一下,只解決了當下的問

【Vue】Vue生命周期

pda -a clas 文本 con 存在 操作 ef6 註意 Vue實例的生命周期全過程(圖) (這裏的紅邊圓角矩形內的都是對應的Vue實例的鉤子函數) 在beforeCreate和created鉤子函數間的生命周期 在beforeC

Vue入門系列(五)Vue實例生命周期

auto res context mode parent all from bool silent 【入門系列】 【本文轉自】   http://www.cnblogs.com/fly_dragon Vue的實例是Vue框架的入口,其實也就是前端的ViewM

session、cookie、記住我的登入狀態

Cookie的機制 Cookie是瀏覽器(User Agent)訪問一些網站後,這些網站存放在客戶端的一組資料,用於使網站等跟蹤使用者,實現使用者自定義功能。 Cookie的Domain和Path屬性標識了這個Cookie是哪一個網站傳送給瀏覽器的;Cookie的Expires屬性標識了Co

通過例項來了Activity生命週期

簡單的例項,通過這個例項來更加充分的瞭解Activity生命週期在多個Activity中切換時內建方法載入順序,有誤請指正,不喜勿噴。 MainActivity.class—–>作為Activity A package com.jikexueyuan

關於Session生命週期和使用HttpSessionListener中遇到的問題

    繼續重複昨天的內容,昨天提到 Session 其建立並不是當我們客戶端訪問伺服器時就產生的,而是我們在如Servlet類中有類似HttpServletRequest.getSession()時才會建立。而其結束時間更不是我們關閉客戶端時產生。注:我們關閉客戶端只是使客

Asp.Net Session生命週期

Asp.Net中的Session與Cookie最大的區別在於:Cookie資訊全部存放於客戶端,Session則只是將一個ID存放在客戶端做為與服務端驗證的標記,而真正的資料都是放在服務端的記憶體之中的。  在傳統web程式語言(比如asp)中,session的... &nb

Session過期時間

最近專案中遇到需要對單個Session的過期時間進行特殊處理 很多人是這樣理解的 --------------------------------------------------------------------------------------------- pr

7.SessionManager(session生命週期管理)

SessionManager負責管理shiro自己封裝的session的生命週期。 為什麼shiro要自己封裝session? 1.可以為任意應用提供session支援,不依賴於底層容器 2.簡單擴容session管理容器,可以實現任何資料來源(redis

Hibernate學習--Session生命週期的不同狀態

前言 總結一下Session的不同狀態。 Session的生命週期不同狀態 三種狀態 Hibernate生命週期中java物件的三種狀態: 1、臨時狀態(transient):用ne

安卓服務service全生命週期,前臺服務、後臺服務,啟動登出、繫結綁,註冊

全棧工程師開發手冊 (作者:欒鵬) 定義服務(服務的生命週期) 呼叫context.startService()時依次執行 ->onCreate()- >onStartCommand()->Service

JSP之Session生命週期

我要介紹一下Session的生命週期,當網頁中客戶第一次訪問Web應用中支援session的某個網頁時,就會建立一個新的session。結下來當客戶瀏覽這個Web應用的不同網頁時,始終處於一個se

Session分散式共享(.NET CORE版)

一、前言&回顧        在上篇文章Session分散式共享 = Session + Redis + Nginx中,好多同學留言問了我好多問題,其中印象深刻的有:nginx掛了怎麼辦?採用Redis的Session方案與微軟Session方案相比,有什麼

Vue生命週期函式

 vue例項的生命週期 1 什麼是生命週期(每個例項的一輩子) 概念:每一個Vue例項建立、執行、銷燬的過程,就是生命週期;在例項的生命週期中,總是伴隨著各種事件,這些事件就是生命週期函式; 生命週期:例項的生命週期,就是一個階段,從建立到執行,再到銷燬的階段; 生命週期函式:在例項的生命週