Servlet詳解(三):會話技術

會話技術

什麼是會話技術呢?
藝術來源於生活,技術也來源於生活。兩個總統在一起聊天,我們稱作一次會話。兩個人進行會話,有兩個前提:1. 兩個人的語言可以互相溝通 2. 兩個人要有記憶力,可以記住對方所說的內容。
在javaweb中,瀏覽器和服務器之間的通訊也可以看作是兩個人在聊天,爲了聊天盡興,所以雙方也要擁有”記憶力”,可以保存之前的聊天狀態。

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

會話技術常見應用:
用戶登錄後在一段事件內,並不需要再次登錄。

瀏覽器的記憶力:Cookie
服務器的記憶力:Session

在瀏覽器端記錄一些信息

原理:

這裏寫圖片描述

這個響應頭的信息是一個鍵值對

set-Cookie:name=Feathers

原理即使設置響應頭,瀏覽器接受響應頭保存,然後瀏覽器下次的請求都會帶這這個頭的信息。

response.setHeader("setCookie","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的子路經

這裏寫圖片描述

有一個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…
這裏寫圖片描述

瀏覽器第一次訪問服務器,服務器返回給瀏覽器一個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的壽命:

session.setMaxInactiveInterval(int interval); // 隻影響一個具體的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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章