jsp cookie

說起來,Cookie應該是一種應用較久的技術了。早在HTML剛剛出現的時候,在每個獨立的頁面之間沒有辦法記錄和標識不同的用戶。後來人們就發明了Cookie技術,當用戶訪問網頁時,它能夠在訪問者的機器上創立一個文件,我們把它叫作Cookie,寫一段內容進去,來標識不同的用戶。如果下次用戶再訪問這個網頁的時候,它又能夠讀出這個文件裏面的內容,這樣網頁就知道上次這個用戶已經訪問過該網頁了。

雖然現在網頁的製作技術比起幾年以前已經發展了許多。不過有些時候,Cookie還是能夠幫我們很多忙的。接下來,我們就來看看,如何在寫JSP文件的時候,用JSP操作Cookie。

二、 寫入Cookie

其實用JSP操作Cookie是非常簡單的,我們來看下面一段JSP程序:

........(中間略)


<%
String cookieName="Sender";
Cookie cookie=new Cookie(cookieName, "Test_Content");
cookie.setMaxAge(10);
response.addCookie(cookie);
%>
........(其他內容)


這樣我們就設置了一個Cookie,很簡單吧?

我們來仔細研究一下這段代碼:

  Cookie cookie=new Cookie(cookieName, "Test_Content");

這一行建立了一個Cookie對象,初始化有兩個參數,第一個參數cookieName定義了Cookie的名字,後一個參數,也是一個字符串,定義了Cookie的內容。也就是我們希望網頁在用戶的機器上標識的文件內容。

接下來一行:cookie.setMaxAge(10),調用了Cookie中的setMaxAge方法,設定Cookie在用戶機器硬盤上的存活期爲10秒。一個Cookie在用戶的硬盤裏面存在的時間並不是無限期的,在建立Cookie對象的時候,我們必須制定Cookie的存活期,超過了這個存活期後,Cookie文件就不再起作用,會被用戶的瀏覽器自行刪除。如果我們希望用戶在下次訪問這個頁面的時候,Cookie文件仍然有效而且可以被網頁讀出來的話,我們可以將Cookie的存活期設得稍微長一些。比如cookie.setMaxAge(365*24*60*60)可以讓Cookie文件在一年內有效。

三、 讀出Cookie

Cookie文件創建好後,自然還需要我們把它讀出來,否則我們不是白費力氣嗎?接下來我們看看如何讀出在用戶硬盤上的Cookie。

........(中間略)

Name value

<%
Cookie cookies[]=request.getCookies();
Cookie sCookie=null;
String svalue=null;
String sname=null;
for(int i=0;i{
sCookie=cookies[i];
svalue=sCookie.getValue();
sname=sCookie.getName();
%>

<%
}
%>

name value
<%=name%> <%=svalue%>

........(其他內容)

這一小段JSP文件可以讀出用戶硬盤上的所有有效的Cookie,也就是仍然在存活期內的Cookie文件。並用表格的形式列出每個Cookie的名字和內容。

我們來逐行分析一下這段代碼:

Cookie cookies[]=request.getCookies() 我們用request.getCookies()讀出用戶硬盤上的Cookie,並將所有的Cookie放到一個cookie對象數組裏面。

接下來我們用一個循環語句遍歷剛纔建立的Cookie對象數組,我們用sCookie=cookies[i]取出數組中的一個Cookie對象,然後我們用sCookie.getValue()和sCookie.getName()兩個方法來取得這個Cookie的名字和內容。

通過將取出來的Cookie的名字和內容放在字符串變量中,我們就能對其進行各種操作了。在上面的例子裏,可通過循環語句的遍歷,將所有Cookie放在一張表格中進行顯示。

四、 需要注意的一些問題

通過上面兩個簡單的例子,可以看到,用JSP進行Cookie的操作,是非常簡單的。不過我們在實際操作中還要注意一些問題:

1. Cookie的兼容性問題

Cookie的格式有2個不同的版本,第一個版本,我們稱爲Cookie Version 0,是最初由Netscape公司制定的,也被幾乎所有的瀏覽器支持。而較新的版本,Cookie Version 1,則是根據RFC 2109文檔制定的。爲了確保兼容性,JAVA規定,前面所提到的涉及Cookie的操作都是針對舊版本的Cookie進行的。而新版本的Cookie目前還不被Javax.servlet.http.Cookie包所支持。

2. Cookie的內容

同樣的Cookie的內容的字符限制針對不同的Cookie版本也有不同。在Cookie Version 0中,某些特殊的字符,例如:空格,方括號,圓括號,等於號(=),逗號,雙引號,斜槓,問號,@符號,冒號,分號都不能作爲Cookie的內容。這也就是爲什麼我們在例子中設定Cookie的內容爲"Test_Content"的原因。

雖然在Cookie Version 1規定中放寬了限制,可以使用這些字符,但是考慮到新版本的Cookie規範目前仍然沒有爲所有的瀏覽器所支持,因而爲保險起見,我們應該在Cookie的內容中儘量避免使用這些字符。(karry/大衆網絡報)

  ====================================
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; i<cookies.length; i++) {
   Cookie 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) +
   "<BODY BGCOLOR=\"#FDF5E6\">\n" +
   "<H1 ALIGN=\"CENTER\">Searching the Web</H1>\n" +
   "\n" +
   "<FORM ACTION=\"/servlet/hall.CustomizedSearchEngines\">\n" +
   "<CENTER>\n" +
   "Search String:\n" +
   "<INPUT TYPE=\"TEXT\" NAME=\"searchString\"\n" +
   " VALUE=\"" + searchString + "\"><BR>\n" +
   "Results to Show Per Page:\n" +
   "<INPUT TYPE=\"TEXT\" NAME=\"numResults\"\n" +
   " VALUE=" + numResults + " SIZE=3><BR>\n" +
   "<INPUT TYPE=\"RADIO\" NAME=\"searchEngine\"\n" +
   " VALUE=\"google\"" +
   checked("google", searchEngine) + ">\n" +
   "Google |\n" +
   "<INPUT TYPE=\"RADIO\" NAME=\"searchEngine\"\n" +
   " VALUE=\"infoseek\"" +
   checked("infoseek", searchEngine) + ">\n" +
   "Infoseek |\n" +
   "<INPUT TYPE=\"RADIO\" NAME=\"searchEngine\"\n" +
   " VALUE=\"lycos\"" +
   checked("lycos", searchEngine) + ">\n" +
   "Lycos |\n" +
   "<INPUT TYPE=\"RADIO\" NAME=\"searchEngine\"\n" +
   " VALUE=\"hotbot\"" +
   checked("hotbot", searchEngine) + ">\n" +
   "HotBot\n" +
   "<BR>\n" +
   "<INPUT TYPE=\"SUBMIT\" VALUE=\"Search\">\n" +
   "</CENTER>\n" +
   "</FORM>\n" +
   "\n" +
   "</BODY>\n" +
   "</HTML>\n");
   }
  
   private String checked(String name1, String name2) {
   if (name1.equals(name2))
   return(" CHECKED");
   else
   return("");
   }
  }
  
  
  
  
     CustomizedSearchEngines.java
  
      前面的SearchEnginesFrontEnd Servlet把數據發送到CustomizedSearchEngines Servlet。本例在許多方面與前面介紹HTTP狀態代碼時的例子相似,區別在於,本例除了要構造一個針對搜索引擎的URL並向用戶發送一個重定向應答 之外,還要發送保存用戶數據的Cookies。
  package hall;
  
  import java.io.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import java.net.*;
  
  public class CustomizedSearchEngines extends HttpServlet {
   public void doGet(HttpServletRequest request,
   HttpServletResponse response)
   throws ServletException, IOException {
  
   String searchString = request.getParameter("searchString");
   Cookie searchStringCookie =
   new LongLivedCookie("searchString", searchString);
   response.addCookie(searchStringCookie);
   searchString = URLEncoder.encode(searchString);
   String numResults = request.getParameter("numResults");
   Cookie numResultsCookie =
   new LongLivedCookie("numResults", numResults);
   response.addCookie(numResultsCookie);
   String searchEngine = request.getParameter("searchEngine");
   Cookie searchEngineCookie =
   new LongLivedCookie("searchEngine", searchEngine);
   response.addCookie(searchEngineCookie);
   SearchSpec[] commonSpecs = SearchSpec.getCommonSpecs();
   for(int i=0; i<commonSpecs.length; i++) {
   SearchSpec searchSpec = commonSpecs[i];
   if (searchSpec.getName().equals(searchEngine)) {
   String url =
   searchSpec.makeURL(searchString, numResults);
   response.sendRedirect(url);
   return;
   }
   }
   response.sendError(response.SC_NOT_FOUND,
   "No recognized search engine specified.");
   }
  
   public void doPost(HttpServletRequest request,
   HttpServletResponse response)
   throws ServletException, IOException {
   doGet(request, response);
   }
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章