天天看點

Servlet詳解(三):會話技術與Cookie

會話技術

什麼是會話技術呢?

藝術來源于生活,技術也來源于生活。兩個總統在一起聊天,我們稱作一次會話。兩個人進行會話,有兩個前提:1. 兩個人的語言可以互相溝通 2. 兩個人要有記憶力,可以記住對方所說的内容。

在javaweb中,浏覽器和伺服器之間的通訊也可以看作是兩個人在聊天,為了聊天盡興,是以雙方也要擁有"記憶力",可以儲存之前的聊天狀态。

會話範圍:

打開網站,完成所需要的所有需求,是一次會話。

會話技術常見應用:

使用者登入後在一段事件内,并不需要再次登入。

浏覽器的記憶力:Cookie

伺服器的記憶力:Session

Cookie

在浏覽器端記錄一些資訊

原理:

Servlet詳解(三):會話技術與Cookie

這個響應頭的資訊是一個鍵值對

set-Cookie:name=Feathers
           

原理即使設定響應頭,浏覽器接受響應頭儲存,然後浏覽器下次的請求都會帶這這個頭的資訊。

伺服器發送cookie

// 建立Cookie 并添加到響應頭中
Cookie cookie = new Cookie("name", "Feathers");
response.addCookie(cookie);
           

浏覽器擷取Cookie:

Cookie[] cookies = request.getCookies();
Cookie nameCookie = c;
if (cookies != null){
	for (int i = 0; i < cookies.length; i++){
		if (cookie.getName().equals("name")){
			nameCookie = cookie;
		}
	}
}
if (nameCookie != null)
	System.out.println(nameCookie.getValue());
           

設定Cookie時間

  1. 預設Cookie時間:

    浏覽器關閉時,即會話結束時。’

  2. 指定Cookie時間:
Cookie c = new Cookie("name","Feathers");
c.setMaxAge(60 * 60 * 24 * 7); // Cookie有效期,告訴浏覽器儲存Cookie兩周
// c.setMaxAge(-1); // 在會話結束後删除Cookie,即預設值
// c.setMaxAge(0); // 使用一個0秒後過期的Cookie,将會覆寫原來的Cookie,達到删除Cookie,達到删除Cookie的效果
response.addCookie(c);
           

浏覽器發送Cookie

浏覽器發送Cookie的條件:

  • 網站域(主機名)相同
  • 網站路徑是Cookie的子路經
Servlet詳解(三):會話技術與Cookie

有一個cookie的路徑為

/CookieDemo

,主機域是localhost

通路如下路徑:

http://localhost:8080/CookieDemo

,會發送

http://localhost:8080/CookieDemo/BServlet

,會發送

http://baidu:8080/CookieDemo/AServlet

,不會發送

http://localhost:8080/Test

,不會發送

Cookie主機和路徑的設定

設定路徑

  1. 預設情況

    發送Cookie的資源的所在路徑

    例如:發送Cookie的資源路徑為

    http://localhost:8080/CookieDemo/AServlet

    那麼Cookie的預設路徑就為

    /CookieDemo

  2. 手動設定
Cookie c = new Cookie("name","Feathers");
c.setPath("/MyCookie/MyServlet");
response.addCookie(c);
           

設定主機

  1. 預設主機

    發送Cookie資源的伺服器主機名

  2. 手動設定
Cookie c = new Cookie("name","Feathers");
// 隻能設定目前主機,可以是目前主機的主機的一部分,不能仿造别的網站的Cookie,有安全隐患
c.setDomain("loaclhost"); // Domain 域的意思
response.addCookie(c);
           

删除Cookie

cookie.setMaxAge(0)

覆寫達到删除的目的,需要注意:

隻有cookie的路徑、鍵、主機一緻才可以覆寫。

###Cookie記錄中文的鍵值對

Cookie為什麼不能使用中文?

在HTTP協定中,除了正文,其他地方都不能使用Latin碼表以下的碼表

要想發送中文,需要使用

URLEncode

類進行轉化,類似Get請求的參數。

URLEncode會将漢字轉化為 二進制,然後每八位二進制數轉化為兩位16進制數,每兩位十六進制數之間又使用%隔開。

是以我們經常看到

4C%45%7E%3A

這樣的字元串。

然後,在伺服器端進行decode解析,就完成了cookie傳遞中文的效果。

使用Cookie實作記住帳号的功能

<!-- index.jsp 登入界面界面 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登入</title>
<%
	String username = "";
	System.out.println("==" + username);
	Cookie[] cookies = request.getCookies();
	for (int i = 0; i < cookies.length; i++){
		if ("username".equals(cookies[i].getName())){
			username = cookies[i].getValue();
			System.out.println("==" + username);
		}
	}
	
	if (username == null){
		username = "";
	}
%>
</head>
<body>

	<form action="FirstServlet" method="get">
		<table>
			<tr>
				<td>使用者名:</td>
				<td>
					<input type="text" name="username" value=<%= username%>/>
					<font color="red"><%=request.getAttribute("error") == null ? "":request.getAttribute("error") %></font>
				</td>
			</tr>
			<tr>
				<td>密碼:</td>
				<td><input type="password" name="password" value=""/></td>
			</tr>
			<tr>
				<td><input type="checkbox" name="remember" value="yes"/>記住使用者名</td>
			</tr>
			<tr>
				<td><input type="submit" value="送出"/></td>
			</tr>
		</table>
	</form>
</body>
</html>

           
/* FirstServlet.java  處理登入資訊、用來轉發的類 */

package com.feathers.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
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("/FirstServlet")
public class FirstServlet extends HttpServlet {

    public FirstServlet() {
        super();
    }
    
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		System.out.println("1");
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String remember = request.getParameter("remember");
		
		System.out.println("2" + remember);
  		if (username == null || "".equals(username.trim())){
			request.setAttribute("error", "對不起,使用者名不能為空");
			request.getRequestDispatcher("/index.jsp").forward(request, response);
			return;
		}
  		System.out.println("3");
		if (password == null || "".equals(password.trim())){
			request.setAttribute("error", "對不起,密碼不能為空");
			request.getRequestDispatcher("/index.jsp").forward(request, response);
			return;
		}
		System.out.println("4" + remember);
		
		if (remember != null && remember.equals("yes")){
			System.out.println("添加了");
			Cookie cookie = new Cookie("username", username);
			cookie.setMaxAge(60*60*24*7*2);//儲存兩周
			response.addCookie(cookie);
			// 重定向到成功頁面
			response.sendRedirect("/ServletDemo1/response.jsp");
		}
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}
           
<!-- response.jsp 登入成功後,重定向的頁面 -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登入成功</title>
</head>
<body>
	<h1>登入成功</h1>
</body>
</html>
           

Session

在伺服器記錄一些資訊。

###Session原理

類似Cookie…

Servlet詳解(三):會話技術與Cookie

浏覽器第一次通路伺服器,伺服器傳回給浏覽器一個sessionId,以後浏覽器每次請求,都攜帶着這個sessionID,用來驗證自己的身份。

常見用例:購物車,使用者将商品加入到購物車中,第一次加入時,伺服器給一個sessionId,以後每次加入都向這個ID的購物車加入商品。而且使用者在檢視購物車時,也會傳入sessionID(key),伺服器接受到sessionID後,根據SessionID擷取Session(即value,購物車的内容)。

那麼伺服器是怎麼傳回給浏覽器一個sessionID的呢?

通過給浏覽器設定一個cookie,即在響應頭中添加

set-cookie:JSESSIONID=39FECEA2F;Path=/項目路徑

,且有效時間未設定(浏覽會話結束時)的cookie。

是以浏覽器也就是通過request對象攜帶cookie進而攜帶sessionID給伺服器的。

Session主要用途

最常見的最基本的用于儲存登入狀态,以及上文的購物車(未登入也會有)

###使用Session

// 擷取伺服器的session
HttpSession session = request.getSession(true); // true,如果伺服器沒有session,那麼伺服器就會建立一個session傳回給浏覽器。false,相反,如果沒有session,不會建立,不會傳回session。
// request.getSession(); // 即 request.getSession(true)

// session的操作
session.setAttribute("key","value"); // 向session域中添加一個鍵值對
session.getAttributeNames();
session.removeAttribute("key");
           

Session的壽命

web.xml

中修改标簽

<session-config>

标簽

<session-config>
	<!-- 配置session的過期時間,預設30分鐘,國際标準 -->
	<session-timeout>30</session-timeout>
</session-config>
           

在Session對象中也有方法進行設定session的壽命:

sessionID的存在時間?

就是cookie的時間,可以通過擷取cookie設定setMaxAge 控制

Session域的範圍

  • session的範圍就是一次會話期間。
  1. 浏覽器第一次通路伺服器,伺服器建立session對象,會話開始
  2. 浏覽器關閉,會話結束,儲存的sessionID也就丢失(預設有效事件為一個會話),session也就無效了。
  3. 或者session已經過期了。
  4. session對象在伺服器内被手動銷毀了

API

boolean session.isNew() // 判斷session是否是新的,即session是否是第一次通路,通路第二次就是舊的
session.getCreationTime() // 擷取session建立事件
session.getID() // 擷取session的ID
session.getLastAccessTime() // 擷取最後一次通路session的時間
session.getMaxInactiveInterval(60) // 設定session最大有效時間60s
session.invalidate(); // 立即銷毀session