Java Servlet和JSP教程(9)(轉)

發表於2007-08-11
Java Servlet和JSP教程(9)(轉)[@more@]

此篇是本站CnJSP小組核心成員鈍刀原創作品

9 Cookie

9.1 Cookie概述

Cookie 是伺服器傳送給瀏覽器的體積很小的純文字資訊,使用者以後訪問同一個Web伺服器時瀏覽器會把它們原樣傳送給伺服器。透過讓伺服器讀取它原先儲存到客戶端的資訊,網站能夠為瀏覽者提供一系列的方便,例如線上交易過程中標識使用者身份、安全要求不高的場合避免使用者重複輸入名字和密碼、入口網站的主頁定製、有針對性地投放廣告,等等。

Cookie的目的就是為使用者帶來方便,為網站帶來增值。雖然有著許多誤傳,事實上Cookie並不會造成嚴重的安全威脅。Cookie永遠不會以任何方式執行,因此也不會帶來病毒或攻擊你的系統。另外,由於瀏覽器一般只允許存放300個Cookie,每個站點最多存放20個Cookie,每個Cookie的大小限制為4 KB,因此Cookie不會塞滿你的硬碟,更不會被用作“拒絕服務”攻擊手段。

9.2 Servlet的Cookie API

要把Cookie傳送到客戶端,Servlet先要呼叫new Cookie(name,value)用合適的名字和值建立一個或多個Cookie (2.1節),透過cookie.setXXX設定各種屬性(2.2節),透過response.addCookie(cookie)把cookie加入應答頭(2.3節)。

要從客戶端讀入Cookie,Servlet應該呼叫request.getCookies(), getCookies()方法返回一個Cookie物件的陣列。在大多數情況下,你只需要用迴圈訪問該陣列的各個元素尋找指定名字的Cookie,然後對該Cookie呼叫getValue方法取得與指定名字關聯的值,這部分內容將在2.4節討論。

9.2.1 建立Cookie

呼叫Cookie物件的建構函式可以建立Cookie。Cookie物件的建構函式有兩個字串引數:Cookie名字和Cookie值。名字和值都不能包含空白字元以及下列字元:

[ ] ( ) = , " / ? @ : ;

9.2.2 讀取和設定Cookie屬性

把Cookie加入待傳送的應答頭之前,你可以檢視或設定Cookie的各種屬性。下面摘要介紹這些方法:

getComment/setComment

獲取/設定Cookie的註釋。

getDomain/setDomain

獲取/設定Cookie適用的域。一般地,Cookie只返回給與傳送它的伺服器名字完全相同的伺服器。使用這裡的方法可以指示瀏覽器把Cookie返回給同一域內的其他伺服器。注意域必須以點開始(例如.sitename.com),非國家類的域(如.com,.edu,.gov)必須包含兩個點,國家類的域(如.com.cn,.edu.uk)必須包含三個點。

getMaxAge/setMaxAge

獲取/設定Cookie過期之前的時間,以秒計。如果不設定該值,則Cookie只在當前會話內有效,即在使用者關閉瀏覽器之前有效,而且這些Cookie不會儲存到磁碟上。參見下面有關LongLivedCookie的說明。

getName/setName

獲取/設定Cookie的名字。本質上,名字和值是我們始終關心的兩個部分。由於HttpServletRequest的getCookies方法返回的是一個Cookie物件的陣列,因此通常要用迴圈來訪問這個陣列查詢特定名字,然後用getValue檢查它的值。

getPath/setPath

獲取/設定Cookie適用的路徑。如果不指定路徑,Cookie將返回給當前頁面所在目錄及其子目錄下的所有頁面。這裡的方法可以用來設定一些更一般的條件。例如,someCookie.setPath("/"),此時伺服器上的所有頁面都可以接收到該Cookie。

getSecure/setSecure

獲取/設定一個boolean值,該值表示是否Cookie只能透過加密的連線(即SSL)傳送。

getValue/setValue

獲取/設定Cookie的值。如前所述,名字和值實際上是我們始終關心的兩個方面。不過也有一些例外情況,比如把名字作為邏輯標記(也就是說,如果名字存在,則表示true)。

getVersion/setVersion

獲取/設定Cookie所遵從的協議版本。預設版本0(遵從原先的Netscape規範);版本1遵從RFC 2109 , 但尚未得到廣泛的支援。

9.2.3 在應答頭中設定Cookie

Cookie可以透過HttpServletResponse的addCookie方法加入到Set-Cookie應答頭。下面是一個例子:

Cookie userCookie = new Cookie("user", "uid1234");

response.addCookie(userCookie);

9.2.4 讀取儲存到客戶端的Cookie

要把Cookie傳送到客戶端,先要建立Cookie,然後用addCookie傳送一個Set-Cookie HTTP應答頭。這些內容已經在上面的 2.1節介紹。從客戶端讀取Cookie時呼叫的是HttpServletRequest的getCookies方法。該方法返回一個與HTTP請求頭中的內容對應的Cookie物件陣列。得到這個陣列之後,一般是用迴圈訪問其中的各個元素,呼叫getName檢查各個Cookie的名字,直至找到目標 Cookie。然後對這個目標Cookie呼叫getValue,根據獲得的結果進行其他處理。

上述處理過程經常會遇到,為方便計下面我們提供一個getCookieValue方法。只要給出Cookie物件陣列、Cookie名字和預設值,getCookieValue方法就會返回匹配指定名字的Cookie值,如果找不到指定Cookie,則返回預設值。

9.3 幾個Cookie工具函式

下面是幾個工具函式。這些函式雖然簡單,但是,在和Cookie打交道的時候很有用。

9.3.1 獲取指定名字的Cookie值

該函式是ServletUtilities.java的一部分。getCookieValue透過迴圈依次訪問Cookie物件陣列的各個元素,尋找是否有指定名字的Cookie,如找到,則返回該Cookie的值;否則,返回引數中給出的預設值。getCookieValue能夠在一定程度上簡化 Cookie值的提取。

public static String getCookieValue(Cookie[] cookies,

String cookieName,

String defaultValue) {

for(int i=0; iCookie cookie = cookies[i];

if (cookieName.equals(cookie.getName()))

return(cookie.getValue());

}

return(defaultValue);

}

9.3.2自動儲存的Cookie

下面是LongLivedCookie類的程式碼。如果你希望Cookie能夠在瀏覽器退出的時候自動儲存下來,則可以用這個LongLivedCookie類來取代標準的Cookie類。

package hall;

import javax.servlet.http.*;

public class LongLivedCookie extends Cookie {

public static final int SECONDS_PER_YEAR = 60*60*24*365;

public LongLivedCookie(String name, String value) {

super(name, value);

setMaxAge(SECONDS_PER_YEAR);

}

}

9.4.例項:定製的搜尋引擎介面

下面也是一個搜尋引擎介面的例子,透過修改前面HTTP狀態程式碼的例子得到。在這個Servlet中,使用者介面是動態生成而不是由靜態HTML檔案提供的。Servlet除了負責讀取表單資料並把它們傳送給搜尋引擎之外,還要把包含表單資料的Cookie傳送給客戶端。以後客戶再次訪問同一表單時,這些 Cookie的值將用來預先填充表單,使表單自動顯示最近使用過的資料。

SearchEnginesFrontEnd.java

該Servlet構造一個主要由表單構成的使用者介面。第一次顯示的時候,它和前面用靜態HTML頁面提供的介面差不多。然而,使用者選擇的值將被儲存到 Cookie(本頁面將資料傳送到CustomizedSearchEngines Servlet,由後者設定Cookie)。使用者以後再訪問同一頁面時,即使瀏覽器是退出之後再啟動,表單中也會自動填好上一次搜尋所填寫的內容。

注意該Servlet用到了 ServletUtilities.java,其中getCookieValue前面已經介紹過,headWithTitle用於生成HTML頁面的一部分。另外,這裡也用到了前面已經說明的LongLiveCookie類,我們用它來建立作廢期限很長的Cookie。

package hall;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.net.*;

public class SearchEnginesFrontEnd extends HttpServlet {

public void doGet(HttpServletRequest request,

HttpServletResponse response)

throws ServletException, IOException {

Cookie[] cookies = request.getCookies();

String searchString =

ServletUtilities.getCookieValue(cookies,

"searchString",

"Java Programming");

String numResults =

ServletUtilities.getCookieValue(cookies,

"numResults",

"10");

String searchEngine =

ServletUtilities.getCookieValue(cookies,

"searchEngine",

"google");

response.setContentType("text/html");

PrintWriter out = response.getWriter();

String title = "Searching the Web";

out.println(ServletUtilities.headWithTitle(title) +

"

" +

"

Searching the Web

" +

"

" +

"

" +

"

" +

"Search String:

" +

"" +

" VALUE="" + searchString + "">

" +

"Results to Show Per Page:

" +

"" +

" VALUE=" + numResults + " SIZE=3>

" +

"" +

" VALUE="google"" +

checked("google", searchEngine) + ">

" +

"Google |

" +

"" +

" VALUE="infoseek"" +

checked("infoseek", searchEngine) + ">

" +

"Infoseek |

" +

"" +

" VALUE="lycos"" +

checked("lycos", searchEngine) + ">

" +

"Lycos |

" +

"" +

" VALUE="hotbot"" +

checked("hotbot", searchEngine) + ">

" +

"HotBot

" +

"

" +

"

" +

"

" +

"

" +

"

" +

"

" +

"

相關文章