基本定義
Session直接翻譯成中文比較困難,一般都譯成時域。在計算機專業術語中,Session是指一個終端用戶與互動系統進行通信的時間間隔,通常指從註冊進入系統到註銷退出系統之間所經過的時間。以及如果需要的話,可能還有一定的操作空間。
需要注意的是,一個Session的概念需要包括特定的客戶端,特定的
伺服器端以及不中斷的操作時間。A用戶和C伺服器建立連線時所處的Session同B用戶和C伺服器建立連線時所處的Session是兩個不同的Session。
session的工作原理
(1)當一個session第一次被啟用時,一個唯一的標識被存儲於本地的cookie中。
(2)首先使用session_start()函式,
PHP從session倉庫中載入已經存儲的session變數。
(3)當執行PHP腳本時,通過使用session_register()函式註冊session變數。
(4)當PHP腳本執行結束時,未被銷毀的session變數會被自動保存在本地一定路徑下的session庫中,這個路徑可以通過php.ini檔案中的session.save_path指定,下次瀏覽網頁時可以載入使用。
解決方案
那什麼是Session的解決方案呢?我們知道,用戶訪問一個網站時往往需要瀏覽許多網頁。Session的使用在不同的語言中的使用方法特點不盡相同。對於一個通過PHP構築的網站來說,用戶在訪問的過程中需要執行許多的PHP腳本。然而由於
HTTP協定自身的特點,用戶每執行一個PHP腳本都需要和Web
伺服器重新建立連線。
又由於無狀態記憶的特點,此次連線無法得到上次連線的狀態。這樣,用戶在一個PHP腳本中對一個變數進行了賦值操作,而在另外一個PHP腳本中卻無法得到這個變數的值。例如,用戶在負責登錄的PHP腳本中設定了$user="wind",卻無法在另一個PHP腳本中通過調用$user來獲得“wind”這個值。也就是說,在一次HTTP請求中,PHP無法將已經賦值的參數傳遞給下一次http請求的腳本。因此,每個PHP腳本中所定義的變數都是只在本次HTTP請求內有效,本次HTTP請求結束,PHP就會釋放掉這些為這些變數分配的記憶體。
Session解決方案,就是要提供在PHP腳本中定義全局變數的方法,使得這個全局變數在同一個Session中對於所有的PHP腳本都有效。上面我們提到了,Session不是一個簡單的時間概念,一個Session中還包括了特定的用戶和
伺服器。因此更詳細地講,在一個Session定義的全局變數的作用範圍,是指這個Session所對應的用戶所訪問的所有PHP。
例如A用戶通過Session定義了一個全局變數$user=“wind”中,而B用戶通過Session定義的全局變數$user=“jane”。那么在A用戶所訪問的PHP腳本中,$user的值就是wind。
使用方法
Session 是 用於保持狀態的基於 Web
伺服器的方法。Session 允許通過將對象存儲在 Web伺服器的記憶體中在整個用戶會話過程中保持任何對象。
Session 通常用於執行以下操作
存儲需要在整個用戶會話過程中保持其狀態的信息,例如登錄信息或用戶瀏覽 Web應用程式時需要的其它信息。
存儲只需要在頁面重新載入過程中或按功能分組的一組頁之間保持其狀態的對象。
Session 的作用就是它在 Web伺服器上保持用戶的
狀態信息供在任何時間從任何設備上的頁面進行訪問。因為瀏覽器不需要存儲任何這種信息,所以可以使用任何瀏覽器,即使是像 Pad 或手機這樣的瀏覽器設備。
持久性方法的限制
隨著越來越多用戶登錄,Session 所需要的
伺服器記憶體量也會不斷增加。
訪問 Web應用程式的每個用戶都生成一個單獨的 Session 對象。每個 Session 對象的持續時間是用戶訪問的時間加上不活動的時間。
如果每個 Session 中保持許多對象,並且許多用戶同時使用 Web應用程式(創建許多 Session),則用於 Session 持久性的伺服器記憶體量可能會很大,從而影響了可伸縮性。
基本語法
1. 對於
值類型的變數,Session中保存的是值類型的
拷貝Session["__test0"] = 1;
int i = (int)Session["__test0"]+1;
int j = (int)Session["__test0"];
結果:i=2,j=1
2. 對於引用類型的變數,Session中保存的是引用
CDACommon cda = new CDACommon();
Session["__test"] = cda.GetDataSet("select top 1 * from tb_customer");
DataSet ds = (DataSet)Session["__test"];
DataSet ds2 = (DataSet)Session["__test"];
ds.Tables[0].Rows[0][0]="9999";
結果:
ds.Tables[0].Rows[0][0]=="9999"
ds2.Tables[0].Rows[0][0]=="9999";
3. Session周期
新的瀏覽器視窗啟動後,開始一個新的Session,觸發Global的Session_Start的調用,從第一個瀏覽器視窗打開的瀏覽器視窗不啟動新的Session。Session過期後,執行頁面的提交也會觸發Session_Start,等於是新的一個Session。
4. 調用Session
對於Web Service,每個方法的調用都會啟動一個Session,可以用下面的方法來使多個調用在同一個Session里 CWSSyscfg cwsCfg = new CWSSyscfg(); cwsCfg.CookieContainer = new System Net.CookieContainer(); CWSSyscfg是一個Web Service類,Web Service的給代理類設定CookieContainer屬性,只要多個代理的CookieContainer屬性是相同的值,則對這些Web Service的調用在同一個Session。可以用單例模式來實現。
5. Session數據有效期
只要頁面有提交活動,則Session的所有項都會保持,頁面在20分鐘(默認配置)內沒有任何提交活動時Session會失效。Session記憶體儲的多個
數據項是整體失效的。
6. Session的保存
在Session中如果保存的是非序列化的類比如DataView,在用SQLServer保存Session的模式下,無法使用。查看一個類是否是序列化的方法是,需看是否用[Serializable]來標記了該類.
在PHP中
PHP session 變數用於存儲關於用戶會話(session)的信息,或者更改用戶會話(session)的設定。Session 變數存儲單一用戶的信息,並且對於應用程式中的所有頁面都是可用的。
PHP Session 變數
您在計算機上操作某個應用程式時,您打開它,做些更改,然後關閉它。這很像一次對話(Session)。計算機知道您是誰。它清楚您在何時打開和關閉應用程式。然而,在網際網路上問題出現了:由於 HTTP 地址無法保持狀態,Web 伺服器並不知道您是誰以及您做了什麼。
PHP session 解決了這個問題,它通過在伺服器上存儲用戶信息以便隨後使用(比如用戶名稱、購買商品等)。然而,會話信息是臨時的,在用戶離開網站後將被刪除。如果您需要永久存儲信息,可以把數據存儲在資料庫中。
Session 的工作機制是:為每個訪客創建一個唯一的 id (UID),並基於這個 UID 來存儲變數。UID 存儲在 cookie 中,或者通過 URL 進行傳導。
在JSP中
Jsp的session是使用bean的一個生存期限,一般為page,session意思是在這個用戶沒有離開網站之前一直有效,如果無法判斷用戶何時離開,一般依據系統設定,tomcat中設定為30分鐘.
我們使用session功能,可以達到多個jsp程式從操作同一個java bean,那么這個java bean可以作為我們傳統意義上的"全局變數池".(在java中我們可以使用static靜態化一個變數和方法,使用singleton唯一化對象.)
在項目實踐中,我們Jsp程式中很多參數需要從資料庫中讀取,有的參數實際讀取一次就可以,如果設計成每個用戶每產生一個頁面都要讀取資料庫,很顯然,資料庫的負載很大,同時也浪費時間,雖然可能有
資料庫連線池最佳化,但是儘量少使用資料庫是我們編程的原則.
JSP使用一個叫HttpSession的對象實現同樣的功能。HTTPSession 是一個建立在cookies 和URL-rewriting上的高質量的界面。Session的信息保存在
伺服器端,Session的id保存在客戶機的cookie中。事實上,在許多伺服器上,如果瀏覽器支持的話它們就使用cookies,但是如果不支持或廢除了的話就自動轉化為URL-rewriting,session自動為每個流程提供了方便地存儲信息的方法。
Httpsession具有如下API:
getId 此方法返回唯一的標識,這些標識為每個session而產生。當只有一個單一的值與一個session聯合時,或當日誌信息與先前的sessions有關時,它被當作鍵名用。
GetCreationTime 返回session被創建的時間。最小單位為千分之一秒。為得到一個對列印輸出很有用的值,可將此值傳給Date constructor 或者
GregorianCalendar的方法setTimeInMillis.
GetLastAccessedTime 返回session最後被客戶傳送的時間。最小單位為千分之一秒。
GetMaxInactiveInterval 返回總時間(秒),負值表示session永遠不會逾時。
getAttribute 取一個session相聯繫的信息。(在jsp1.0中為 getValue)
Integer item = (Integer) session.getAttribute("item") //檢索出session的值並轉化為整型
setAttribute 提供一個關鍵字和一個值。會替換掉任何以前的值。(在jsp1.0中為putValue)
session.setAttribute("ItemValue", itemName); // ItemValue 必須不是must簡單類型
在套用中使用最多的是getAttribute和setAttribute.現以一個簡單的例子來說明session的套用,test1.jsp(信息寫入session),test2.jsp(從session讀出信息)。
test1.jsp
<HTML>
<HEAD>
<TITLE> Document </TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<%
session.setAttribute("str",new String(“this is test”));
%>
</BODY>
</HTML>
test2.jsp
<HTML>
<HEAD>
<TITLE> New Document </TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF">
<%
String ls_str=null;
ls_str=(String)session.getAttribute("str");
out.println(“從session里取出的值為:”+ls_str);
%>
</BODY>
</HTML>
使用詳解
php中的Session與Cookie
在PHP開發中對比起Cookie,session 是存儲在
伺服器端的會話,相對安全,並且不像 Cookie 那樣有存儲長度限制,本文簡單介紹 session 的使用。
由於 Session 是以文本檔案形式存儲在伺服器端的,所以不怕客戶端修改 Session 內容。實際上在伺服器端的 Session 檔案,PHP 自動修改 session 檔案的許可權,只保留了系統讀和寫許可權,而且不能通過 ftp 修改,所以安全得多。
對於 Cookie 來說,假設我們要驗證用戶是否登入,就必須在 Cookie 中保存用戶名和密碼(可能是 md5 加密後字元串),並在每次請求頁面的時候進行驗證。如果用戶名和密碼存儲在資料庫,每次都要執行一次資料庫查詢,給資料庫造成多餘的負擔。因為我們並不能只做一次驗證。為什麼呢?因為客戶端Cookie 中的信息是有可能被修改的。假如你存儲 $admin變數來表示用戶是否登入,$admin 為 true 的時候表示登入,為 false 的時候表示未登錄,在第一次通過驗證後將 $admin 等於 true 存儲在 Cookie,下次就不用驗證了,這樣對么?錯了,假如有人偽造一個值為 true 的 $admin 變數那不是就立即取的了管理許可權么?非常的不安全。
而 Session 就不同了,Session 是存儲在
伺服器端的,
遠程用戶沒辦法修改 session 檔案的內容,因此我們可以單純存儲一個 $admin變數來判斷是否登入,首次驗證通過後設定 $admin 值為 true,以後判斷該值是否為 true,假如不是,轉入
登入界面,這樣就可以減少很多資料庫操作了。而且可以減少每次為了驗證 Cookie 而傳遞密碼的不安全性了(session 驗證只需要傳遞一次,假如你沒有使用 SSL 安全協定的話)。即使密碼進行了 md5 加密,也是很容易被截獲的。
當然使用 session 還有很多優點,比如控制容易,可以按照用戶自定義存儲等(存儲於資料庫)。我這裡就不多說了。
session 在 php.ini 是否需要設定呢?一般不需要的,因為並不是每個人都有修改 PHP.ini 的許可權,默認 session 的存放路徑是
伺服器的系統
臨時資料夾,我們可以自定義存放在自己的資料夾里,這個稍後我會介紹。
Php如何創建Session
開始介紹如何創建 session。非常簡單,真的。
啟動 session 會話,並創建一個 $admin變數:
// 啟動 session
session_start();
// 聲明一個名為 admin 的變數,並賦
空值。
$_session["admin"] = null;
>
如果你使用了 Session,或者該 PHP 檔案要調用 Session變數,那么就必須在調用 Session 之前啟動它,使用 session_start() 函式。其它都不需要你設定了,PHP 自動完成 session 檔案的創建。
執行完這個程式後,我們可以到系統
臨時資料夾找到這個 session 檔案,一般檔案名稱形如:sess_4c83638b3b0dbf65583181c2f89168ec,後面是 32 位編碼後的隨機字元串。用編輯器打開它,看一下它的內容:
admin|N;
Session是什麼呢?簡單來說就是
伺服器給客戶端的一個編號。當一台WWW伺服器運行時,可能有若干個用戶瀏覽正在運行這台伺服器上的網站。當每個用戶首次與這台WWW伺服器建立連線時,他就與這個伺服器建立了一個Session,同時伺服器會自動為其分配一個SessionID,用以標識這個用戶的唯一身份。這個SessionID是由WWW伺服器隨機產生的一個由24個字元組成的字元串,我們會在下面的實驗中見到它的實際樣子。
這個唯一的SessionID是有很大的實際意義的。當一個用戶提交了
表單時,瀏覽器會將用戶的SessionID自動附加在HTTP頭信息中,(這是瀏覽器的自動功能,用戶不會察覺到),當
伺服器處理完這個表單後,將結果返回給SessionID所對應的用戶。試想,如果沒有SessionID,當有兩個用戶同時進行註冊時,伺服器怎樣才能知道到底是哪個用戶提交了哪個表單呢。當然,SessionID還有很多其他的作用,我們會在後面提及到。
除了SessionID,在每個Session中還包含很多其他信息。但是對於編寫ASP或ASP .NET的程式設計師來說,最有用的還是可以通過訪問ASP/ASP .NET的內置
Session對象,為每個用戶存儲各自的信息。例如我們想了解一下訪問我們網站的用戶瀏覽了幾個頁面,我們可能在用戶可能訪問到每個的頁面中加入:
<% If Session("PageViewed") = ""Then Session("PageViewed") = 1 Else Session("PageViewed") = Session("PageViewed") + 1 End If %>
通過以下這句話可以讓用戶得知自己瀏覽了幾個頁面:
<% Response.Write("You have viewed " & Session("PageViewed") & " pages") %>
可能有些讀者會問:這個看似像是
數組的Session(“..”)是哪裡來的?需要我定義嗎?實際上,這個Session對象是具有ASP解釋能力的的WWW
伺服器的內建對象。也就是說ASP的系統中已經給你定義好了這個對象,你只需要使用就行了。其中Session(“..")中的..就好像變數名稱,Session(“..")=$$中的$$就是變數的值了。你只需要寫上句話,在這個用戶的每個頁面中都可以訪問..變數中的值了。
其實ASP會話一共內建了7個對象,有Session、Application、Cookie、Response、Request、Server等。在其他的伺服器端
腳本語言如JSP、PHP等中也有其類似的對象,只是叫法或者使用方法上不太一樣。
一般內容結構
變數名|類型:長度:值;
並用分號隔開每個變數。有些是可以省略的,比如長度和類型。
我們來看一下驗證程式,假設資料庫存儲的是用戶名和 md5 加密後的密碼:
$posts = $_POST;
// 清除一些空白符號
foreach ($posts as $key => $value)
{
$posts[$key] = trim($value);
}
$password = md5($posts["password"]);
$username = $posts["username"];
$query = "SELECT `username` FROM `user` WHERE `password` = '$password'";
// 取得查詢結果
$userInfo = $DB->getRow($query);
if (!empty($userInfo))
{
if ($userInfo["username"] == $username)
{
// 當驗證通過後,啟動 session
session_start();
// 註冊登入成功的 admin變數,並賦值 true
$_SESSION["admin"] = true;
}
else
{
die("用戶名密碼錯誤");
}
}
else
{
die("用戶名密碼錯誤");
}
我們在需要用戶驗證的頁面啟動 session,判斷是否登入:
$admin = false;
// 啟動會話,這步必不可少
session_start();
// 判斷是否登入
if (isset($_SESSION["admin"]) && $_SESSION["admin"] == true)
{
echo "您已經成功登入";
}
else
{
// 驗證失敗,將 $_session["admin"] 置為 false
$_SESSION["admin"] = false;
die("您無權訪問");
}
>
是不是很簡單呢?將 $_session 看成是存儲在
伺服器端的
數組即可,我們註冊的每一個變數都是數組的鍵,跟使用數組沒有什麼分別。
如果要登出系統怎么辦?銷毀 session 即可。
<?php
session_start();
// 這種方法是將原來註冊的某個變數銷毀
unset($_SESSION["admin"]);
// 這種方法是銷毀整個 session 檔案
session_destroy();
>
釋放當前在記憶體中已經創建的所有$_SESSION變數,但不刪除session檔案以及不釋放對應的session id
<?php
session_start();
session_unset();
session_destroy();
session_write_close();
session_regenerate_id(true);
?>
session_destroy()
刪除當前用戶對應的session檔案以及釋放session id,記憶體中的$_SESSION變數內容依然保留
因此,釋放用戶的session所有資源,需要順序執行如下代碼:
<?php
$_SESSION['user'] = ‘user1′;
session_unset();
session_destroy();
?>
Session 能否像 Cookie 那樣設定生存周期呢?有了 Session 是否就完全拋棄 Cookie 呢?我想說,結合 Cookie 來使用 session 才是最方便的。
Session 是如何來判斷客戶端用戶的呢?它是通過 Session ID 來判斷的,什麼是 Session ID,就是那個 Session 檔案的檔案名稱,Session ID 是隨機生成的,因此能保證唯一性和隨機性,確保 Session 的安全。一般如果沒有設定 Session 的生存周期,則 Session ID 存儲在記憶體中,關閉瀏覽器後該 ID 自動註銷,重新請求該頁面後,重新註冊一個 session ID。
如果客戶端沒有禁用 Cookie,則 Cookie 在啟動 Session 會話的時候扮演的是存儲 Session ID 和 session 生存期的角色。
我們來手動設定 session 的生存期:
session_start();
// 保存一天
$lifeTime = 24 * 3600;
setcookie(session_name(),session_id(),time() + $lifeTime,"/");
>
其實 Session 還提供了一個函式 session_set_cookie_params(); 來設定 Session 的生存期的,該函式必須在 session_start()
函式調用之前調用:
// 保存一天
<?php
$lifeTime = 24 * 3600;
session_set_cookie_params($lifeTime);
session_start();
$_session["admin"] = true;
>
如果客戶端使用 IE 6.0 , session_set_cookie_params(); 函式設定 Cookie 會有些問題,所以我們還是手動調用
setcookie函式來創建 cookie。
假設客戶端禁用 Cookie 怎么辦?沒辦法,所有生存周期都是瀏覽器進程了,只要關閉瀏覽器,再次請求頁面又得重新註冊 Session。那么怎么傳遞 Session ID 呢?通過 URL 或者通過隱藏
表單來傳遞,PHP 會自動將 session ID 傳送到 URL 上,URL 形如:?PHPSESSID=bba5b2a240a77e5b44cfa01d49cf9669,其中 URL 中的參數 PHPSESSID 就是 Session ID了,我們可以使用 $_GET 來獲取該值,從而實現 session ID 頁面間傳遞。
// 保存一天
<?php
$lifeTime = 24 * 3600;
// 取得當前 session 名,默認為 PHPSESSID
$sessionName = session_name();
// 取得 session ID
$sessionID = $_GET[$sessionName];
// 使用 session_id() 設定獲得的 session ID
session_id($sessionID);
session_set_cookie_params($lifeTime);
session_start();
$_session["admin"] = true;
>
對於
虛擬主機來說,如果所有用戶的 Session 都保存在系統
臨時資料夾里,將給維護造成困難,而且降低了安全性,我們可以手動設定 Session 檔案的保存路徑,session_save_path()就提供了這樣一個功能。我們可以將 session 存放目錄指向一個不能通過 Web 方式訪問的資料夾,當然,該資料夾必須具備可讀寫屬性。
<?php
// 設定一個存放目錄
$savePath = "./session_save_dir/";
// 保存一天
$lifeTime = 24 * 3600;
session_save_path($savePath);
session_set_cookie_params($lifeTime);
session_start();
$_session["admin"] = true;
>
同 session_set_cookie_params(); 函式一樣,session_save_path() 函式也必須在 session_start() 函式調用之前調用。
我們還可以將
數組,對象存儲在 session 中。運算元組和操作一般變數沒有什麼區別,而保存對象的話,PHP 會自動對對象進行序列化(也叫
串列化),然後保存於 session 中。下面例子說明了這一點:
<?php
class person
{
var $age;
function output() {
echo $this->age;
}
function setAge($age) {
$this->age = $age;
}
}
>
setage.PHP
<?php
session_start();
require_once "person.PHP";
$person = new person();
$person->setAge(21);
$_session['person'] = $person;
echo "check here to output age";
>
output.PHP
<?php
ini_set('unserialize_callback_func','mycallback');
function mycallback($classname) {
$classname . ".PHP";
}
session_start();
$person = $_session["person"];
// 輸出 21
$person->output();
>
當我們執行 setage.php 檔案的時候,調用了 setage() 方法,設定了年齡為 21,並將該狀態序列化後保存在 session 中(PHP 將自動完成這一轉換),當轉到 output.php 後,要輸出這個值,就必須反序列化剛才保存的對象,又因為在解序列化的時候需要實例化一個未定義類,所以我們定義了以後
回調函式,自動包含 person.PHP 這個類檔案,因此對象被重構,並取得當前 age 的值為 21,然後調用 output() 方法輸出該值。
如何防止session逾時
眾所周知,當用戶登錄網站後較長一段時間沒有與伺服器進行互動,將會導致伺服器上的用戶會話數據(即session)被銷毀。此時,當用戶再次操作網頁時,如果伺服器進行了session校驗,那么瀏覽器將會提醒用戶session逾時。
那么,如何解決用戶登錄後較長時間未操作而導致的session失效的問題呢?
導致這個問題的關鍵字有兩個:一個是「長時間」,一個是「未操作」。
1、如果用戶未操作的「長時間」超過了
伺服器配置的session逾時時間,並導致session失效,那么我們延長session的逾時時間,讓用戶原來的「長時間」與逾時時間相比,變得不「長」,不就可以解決了嗎?
2、如果用戶是長時間「未操作」導致session失效,那么我們想辦法產生「操作」,讓用戶每隔一小段時間就「操作」一次,與伺服器產生互動,那么session自然也不會失效。一般情況下下,我們首先想到的是,通過改變伺服器的配置,延長伺服器的session逾時時間。例如,在Tomcat伺服器的web.xml檔案中有如下節點內容:
<session-config><session-timeout>30</session-timeout></session-config>
這裡的30表示session的逾時時間,單位為分鐘,如果用戶登錄後在30分鐘內沒有與
伺服器互動,那么當前用戶的session將失效。我們可以配置一個更大的數值(比如60),就可以延長session的逾時時間,如果將該值改為0或負數的話,則表示session永不失效。
不過在實際的工作套用中,一味地上調session的逾時時間設定並不怎么常見,大多數需要實現該功能的網站都將解決問題的焦點集中在第二條思路上。例如:一些線上網站均採用定時刷新頁面的方法來防止session逾時。
定時刷新頁面,最常見的有兩種實現方式:一種是通過JavaScript+HTMLDOM,另一種則是通過meta標籤來實現。
1、JavaScript+HTMLDOM,示例代碼如下:
functionrefresh(seconds){setTimeout("self.location.reload()",seconds*1000);}refresh(600);//調用方法啟動定時刷新,數值單位:秒。
2、通過meta標籤來實現(在頁面中添加meta標籤refresh也可以指定每隔指定時間就刷新當前頁面),示例代碼如下:
<metahttp-equiv="refresh"content="600"/>
上述meta標籤可以實現每過600秒就刷新一次當前頁面。
在上述兩種方案中,較好的為第二種,因為如果當前頁面是在IE瀏覽器的模式視窗中打開的,默認情況下,self.location.reload()方法將會失效,而refreshmeta標籤在IE模式視窗下仍然有效。
上述兩種方式都實現了刷新當前頁面,並且使用起來非常簡單,不過很遺憾的是,它們存在一種幾乎致命的缺陷。試想一下,如果在論壇發帖等需要用戶輸入內容的頁面,用戶花費較長的時間輸入了許多文本內容,可是突然遇到了一個定時頁面刷新,結果用戶輸入的所有內容都沒了,估計這個時候用戶連掐死你的心都有了……
因此我們需要在當前頁面本身不刷新、不影響用戶的任何操作的情況下實現定時刷新。最常見的解決方法仍然有兩種。一種是在當前頁面添加一個隱藏的iframe,然後在該iframe裡面實現定時刷新。
<iframeid="hidden_iframe"style="display:none;"scrolling="no"frameborder="0"name="hidden_iframe"src="ping.php"></iframe>
此外,我們需要在伺服器上編寫對應的請求回響代碼,例如ping.php中可以編寫如下代碼:
<?php//每隔600秒刷新當前頁面echo'<html><head><metahttp-equiv="refresh"content="600"/></head><body></body></html>';?>
另外一種則是使用JavaScriptImage對象來實現定時刷新,JavaScript代碼如下:
functionautoRefresh(seconds){if(typeofperiod=="undefined"){//如果是第一次執行period=seconds*1000;//定義全局變數periodvarbodyDOM=document.getElementsByTagName("body")[0];if(bodyDOM){bodyDOM.innerHTML+='<imgid="auto_refresh_img"src=""style="display:none"/>';//添加隱藏的圖片imgDOM=document.getElementById("auto_refresh_img");//定義全局Image對象}}if(typeofimgDOM!="undefined"){imgDOM.src="ping.php?sid="+newDate().getTime();//防止快取setTimeout("autoRefresh("+seconds+")",period);}}autoRefresh(600);//調用方法啟動定時刷新
和使用iframe來實現定時刷新一樣,使用JavaScriptImage對象實現定時刷新,也需要在
伺服器端編寫類似的請求回響代碼。伺服器的回響可以是文字等非圖片內容,非圖片內容只會造成圖像載入失敗,而我們的圖像標籤本身就是隱藏的,不管是載入成功還是失敗都不會顯示,畢竟我們的主要目的是傳送請求給伺服器,讓伺服器保持session處於活動狀態。
當然,還可以使用Ajax來實現定時刷新,不過使用Image對象會更好一些,因為有些老式瀏覽器的JavaScript無法實現Ajax,但是卻可以使用Image對象。此外,使用Ajax需要編寫更多的代碼來處理XMLHttpRequest等對象的活動。
在上述兩種方式中,各有其優缺點。
使用iframe標籤實現定時刷新的優點是:不需要編寫JavaScript代碼,可以在瀏覽器禁用JavaScript的情況下實現定時刷新;其缺點是:在某些不支持iframe標籤的老式瀏覽器中沒有效果,此外,iframe
標籤在瀏覽器中新增加了一個獨立的頁面,即使沒有顯示出來,不過其內部解析的window、document等對象仍然存在,占用的瀏覽器記憶體相對較多。
使用Image對象的優點是:與iframe相比,占用的記憶體相對較少,支持Image的瀏覽器也相對較多(現代瀏覽器均支持);缺點是:在瀏覽器禁用JavaScript的情況下就毫無用武之地了。
開發人員應根據實際需求情況來確定使用何種實現方式更好。此外,
伺服器在回響定時刷新的請求時,在滿足要求的情況下,應返回儘可能少的數據,以節省頻寬。
有效期
PHP中的session有效期默認是1440秒(24分鐘)【weiweiok 註:php5里默認的是180分】,也就是說,客戶端超過24分鐘沒有刷新,當前session就會失效。很明顯,這是不能滿足需要的。
一個已知管用的方法是,使用session_set_save_handler,接管所有的session管理工作,一般是把session信息存儲到數 據庫,這樣可以通過SQL語句來刪除所有過期的session,精確地控制session的有效期。這也是基於PHP的大型網站常用的方法。但是,一般的 小型網站,似乎沒有必要這么勞師動眾。
但是一般的Session的生命期有限,如果用戶關閉了瀏覽器,就不能保存Session的變數了!那么怎么樣可以實現Session的永久生命期呢?
大 家知道,Session儲存在伺服器端,根據客戶端提供的SessionID來得到這個用戶的檔案,然後讀取檔案,取得變數的值,SessionID可以 使用客戶端的Cookie或者Http1.1協定的Query_String(就是訪問的URL的“?”後面的部分)來傳送給伺服器,然後伺服器讀取 Session的目錄……
要實現Session的永久生命期,首先需要了解一下php.ini關於Session的相關設定(打開php.ini檔案,在“[Session]”部分):
1、session.use_cookies:默認的值是“1”,代表SessionID使用Cookie來傳遞,反之就是使用Query_String來傳遞;
2、session. name:這個就是SessionID儲存的變數名稱,可能是Cookie,也可能是Query_String來傳遞,默認值是“PHPSESSID”;
3、session.cookie_lifetime:這個代表SessionID在客戶端Cookie儲存的時間,默認是0,代表瀏覽器一關閉SessionID就作廢……就是因為這個所以Session不能永久使用!
4、session.gc_maxlifetime:這個是Session數據在伺服器端儲存的時間,如果超過這個時間,那么Session數據就自動刪除!
功能缺陷
目前ASP的開發人員都正在使用Session這一強大的功能,但是在他們使用的過程中卻發現了ASP Session有以下缺陷:
進程依賴性
ASP Session狀態存於IIS的進程中,也就是
inetinfo.exe這個程式。所以當inetinfo.exe進程崩潰時,這些信息也就丟失。另外,重起或者關閉IIS服務都會造成信息的丟失。
Session狀態使用範圍的局限性
當一個用戶從一個網站訪問到另外一個網站時,這些Session信息並不會隨之遷移過去。例如:新浪網站的WWW
伺服器可能不止一個,一個用戶登錄之後要去各個頻道瀏覽,但是每個頻道都在不同的伺服器上,如果想在這些WWW伺服器共享Session信息怎么辦呢
Cookie的依賴性
實際上客戶端的Session信息是存儲在Cookie中的,如果客戶端完全禁用掉了Cookie功能,他也就不能享受到了Session提供的功能了。
鑒於ASP Session的以上缺陷,微軟的設計者們在設計開發 ASP .NET Session時進行了相應的改進,完全克服了以上缺陷,使得ASP .NET Session成為了一個更加強大的功能。
主要特點
Session是JAVA應用程式和Hibernate進行互動時使用的主要接口,它也是持久化操作核心API,
注意這裡的Session的含義,它與傳統意思上web層的HttpSession並沒有關係,Hibernate Session之於Hibernate,相當於JDBC Connection相對與JDBC。
Session對象是有生命周期的,它以Transaction對象的
事務開始和結束邊界
Session作為貫穿Hibernate的持久化管理器核心,提供了眾多的持久化的方法,如save(),update,delete,find(Hibernate 3中已經取消了此方法,)等,通過這些方法我們可以透明的完成對象的增刪改查(CRUD-- create read update delete),這裡所謂的透明是指,Session在讀取,創建和刪除映射的實體對象的實例時,這一系列的操作將被轉換為對資料庫表中數據的增加,修改,查詢和刪除操作。
Session有以下的特點:
1,不是
執行緒安全的,應該避免多個執行緒共享同一個Session實例
2,Session實例是輕量級的,所謂輕量級:是指他的創建和刪除不需要消耗太多資源
3,Session對象內部有一個快取,被稱為Hibernate第一快取,他存放被當前工作單元中載入的對象,每個Session實例都有自己的快取。
org.hibernate Interface Session
public interface Session extends Serializable : 是一個Java application 和Hibernate之間主要的運行時接口,這是執行持久化服務的中心API
主要方法:
public Transaction beginTransaction() throws HibernateException:返回和當前Session對象相互聯繫的Transaction對象(表示在資料庫中重新開始一個
事務)
public Transaction getTransaction():返回和當前session聯繫的Transaction對象
public Connection connection close() throws HibernateExcepton:結束當前的Session對象
public void clear() :清空Session,清除所有保存在當前Session快取中的實體對象,終止所有正在執行的方法(eg: save(),update(),delete() .....)
public Serializable save(Object object)throws HibernateException 對當前參數指定的對象進行持久化(系統會首先賦予參數對象一個
標識符OID),他相當於insert語句 後面在詳細介紹
public Connection connection() throws HibernateException 得到當前Session 中包含的
Connection對象。
public boolean contains(Object object):判斷參數給出的對象(
持久化類)是否在當前Session的快取中
public void evict(Object object) throws HibernateException :將參數給出的Object從當前Session對象類中刪除,使這個對象從持久態變成游離態,這種狀態的改變不會引起對資料庫的同步,後面詳細介紹
public Object load(Class theclass,Serializable id) throws HibernateException 返回第一個參數指定類對應的表中,第二個參數指定的行(第二個參數就是要取得對象的OID,他對應表中主鍵列的值)
public void update(Object object) throws HibernateException :更新一個對象到資料庫中,後面在詳細介紹
public void delete (Object object)throws HibernateException:從資料庫中刪除和參數指定的對象對應的記錄
public Object get(Class class,Serializable id) throws HibernateException:和load()方法一樣區別在於,如果資料庫表中沒有對應的記錄,get()方法返回null,load()方法將報異常
相關接口
Transaction接口是Hibernate的資料庫
事務接口,用於管理事務,他對底層的事務作出了封裝,用戶可以使用Transaction對象定義自己的對資料庫的
原子操作,底層事務包括:JDBC API,JTA(Java Transaction API)。
一個Transaction對象的事務可能會包括多個對資料庫進行的操作
org.hibernate Interface Transaction
public interface Transaction
常用方法
public void commit() throws HibernateException 刷新當前的Session以及結束
事務的工作,這個方法將迫使資料庫對當前的事務進行提交
public void rollback() throws HibernateException :強迫
回滾當前事務
public boolean isActive() throws HibernateException:這個事務是否存活
----------------------------------------------------------------------------------------
Session:當中包含一個Connection對象
Connection c =session.getConnection();
Session的快取用於臨時保存持久化的對象,等到一定時候,再將快取中的對象保存到資料庫中。
應用程式
事務:如果一個Session中包含有多個Transaction(資料庫事務),這些Transaction的集合稱為應用程式事務
標準使用形式:
Configuration config=new Configuration().configure("hibernate.cfg.xml");
SessionFactory sessionfactory=config.buildSessionFactory();
Session session=sessionfactory.openSession();
Transaction tx=session.beginTransaction();
try
{
session.save();
tx.commit();
}
catch(Exception e)
{
if(tx!=null) tx.rollback();
}
finally
{
session.close ();
}