客戶端與服務器通信過程中,會產生一些數據。比如,A和B分別登陸了某寶購物網站,A買了一個Android手機,B買了一個iPhone手機,當結賬時,web服務器需要分別對用戶A和B的信息分別保存。根據Java Web之Servlet技術中所說,HttpServletRequest對象和ServletContext對象都可以保存數據,但是這二者在該情形下是不適合使用的。
- 客戶端的每次請求,服務器都會產生一個HttpServletRequest對象,該對象只保存本次請求所傳遞的數據。由於購買和結賬是兩個不同的請求,所以使用HttpServletRequest對象保存信息會造成丟失。
- 同一個Web應用共享一個ServletContext對象,所以當多個用戶結賬時無法區分哪個商品是哪個用戶購買的,這顯然是不可行的。
1、Cookie對象
Cookie是一種會話技術,它用於將會話過程中的數據保存在用戶的瀏覽器中,從而使瀏覽器和服務器更好的交互。服務器向客戶端發送Cookie時,會在HTTP響應頭字段增加Set-Cookie字段,該字段設置的Cookie遵循一定規則,比如以鍵值對形式保存,Cookie屬性值可以有多個,但是這些屬性之間必須以分號和空格分隔。以下是一個Cookie示例:
Set-Cookie:"lastTime="2016-05-21 12:03:10"; Version=1"
Cookie使用
為了封裝Cookie信息,Servlet API中提供了一個javax.servlet.http.Cookie類,該類包含了生成Cookie信息和提取Cookie信息各個屬性的方法,Cookie唯一的構造方法下:
public Cookie(java.lang.String name, java.lang.String value)
構造方法中,name用於指定Cookie名稱,value指定Cookie的值,注意,Cookie一旦創建后,其名稱就不允許更改了,Cookie值是可以更改的。Cookie類常用的方法如下:
方法 | 功能 |
String getName() | 返回Cookie名稱 |
void setValue(String newValue)/String getValue() | 設置/獲取Cookie值 |
void setMaxAge(int expiry)/int getMaxAge() | 設置/獲取Cookie在瀏覽中保存有效的秒數 |
void setPath(String uri)/public String getPath() | 設置/獲取Cookie向有效目錄路徑 |
void setDomain(String pattern)/String getDomain() | 設置/獲取Cookie的有效域 |
void setSecure(boolean flag)/boolean getSecure() | 設置/獲取Cookie是否只能使用安全的協議傳送 |
Cookie示例
利用Cookie技術實現提示上次訪問時間功能。
package zzz; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(name="CookieTest", urlPatterns={"/CookieTest"}) public class CookieTest extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 指定響應編碼方式 response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String lastTime = null; Cookie[] cookies = request.getCookies(); for (int i = 0; cookies != null && i < cookies.length; i++) { if (cookies[i].getName().equals("lastTime")) { lastTime = cookies[i].getValue(); } } if (lastTime == null) { out.println("你好,這是你首次訪問網站"); } else { out.println("你好,你上次訪問該網站時間為:" + lastTime); } // 創建cookie,將當前時間記錄到cookie中並返回 String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); Cookie cookie = new Cookie("lastTime", time); response.addCookie(cookie); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { this.doGet(request, response); } }
2、Session技術
Cookie技術可以將用戶信息保存在瀏覽器中,並且可在多次請求中共享數據,但是如果傳遞的信息比較多, 使用Cookie技術明顯加大服務端程序的處理難度。此時,可以使用Session技術來實現,其通過將會話數據保存在服務端。注意:Session對象對應着一個ID,所以一般是需要客戶端記錄該對象的ID,通常情況下,Session是通過Cookie技術來傳遞Session對象ID的。
Session對象是與每個請求緊密相關的,HttpServletRequest定義了用於獲取Session對象的getSession()方法,如下所示:
public HttpSession getSession(boolean create); public HttpSession getSession();
第一個getSession()根據參數值決定是否創建新的Session對象,如果參數為true,則相關的HttpSession對象不存在時創建新的HttpSession對象,如果參數為false,則不會創建新的HttpSession對象。第二個getSession()方法則相當於第一個方法參數為true的情況。HttpSession常用方法如下:
方法 | 功能 |
String getId() | 返回該HttpSession對象關聯的會話標識號 |
int getMaxInactiveInterval() | 返回當前HttpSession對象最大生存周期,單位為s |
void invalidate() | 強制使HttpSession對象失效 |
void setAttribute(String name, Object value) | 將一個對象與一個名稱關聯后存儲到HttpSession對象中 |
Object getAttribute(String name) | 返回當前HttpSession對象中指定名稱的屬性對象 |
void removeAttribute(String name) | 從當前HttpSession對象中刪除指定名稱屬性對象 |
Web服務器管理HttpSession對象時,會采用超時管理機制判斷客戶單是否還在繼續訪問。一定時間內,某個客戶一直沒有訪問,Web服務器就會認為該客戶端已經結束請求,將與該客戶會話所關聯的HttpSession對象給垃圾回收掉。如果之后該客戶端再次訪問,則重新創建一個新的HttpSession對象。會話的有效時間可以再web.xml中設置,默認值有Servlet容器定義,在tomcat的安裝目錄中的web.xml中有如下配置,就是設置Session超時時間的,單位為分鍾。
<session-config> <session-timeout>30</session-timeout> </session-config>
Session示例
利用Session技術實現提示上次訪問時間功能。
package zzz; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @WebServlet(name="SessionTest", urlPatterns={"/SessionTest"}) public class SessionTest extends HttpServlet { @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { // 指定響應編碼方式 response.setContentType("text/html;charset=utf-8"); PrintWriter out = response.getWriter(); String user = null; Cookie[] cookies = request.getCookies(); for (int i = 0; cookies != null && i < cookies.length; i++) { if (cookies[i].getName().equals("user")) { user = cookies[i].getValue(); } } HttpSession session = request.getSession(); if (user == null) { out.println("你好,這是你首次訪問網站"); Cookie cookie = new Cookie("user", "luoxn28"); response.addCookie(cookie); } else { String time = (String) session.getAttribute("lastTime"); out.println("你好,你上次訪問該網站時間為:" + time); } String lastTime = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); session.setAttribute("lastTime", lastTime); } @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { this.doGet(request, response); } }
參考資料
2、《Java Web程序開發入門》6章