1. 程式人生 > 其它 >狂神Java Web (六)Cookie & Session

狂神Java Web (六)Cookie & Session

Cookie & Session

會話:使用者開啟瀏覽器,點選很多連結,訪問多個web資源,關閉瀏覽器,該過程可以稱為會話。

有狀態會話:一個網站,怎麼證明你來過?
客戶端 服務端

  1. 服務端給客戶端一個信件,客戶端下次訪問服務端帶上信件就可以了; cookie
  2. 伺服器登記你來過了,下次來的時候匹配你; session

儲存會話的兩種技術

  • cookie
    • 客戶端技術(響應,請求)
  • session
    • 伺服器技術,可以儲存使用者的會話資訊。可以把資訊或資料放在Session中。

應用場景:自動登入

  1. 從請求中拿到cookie資訊
  2. 伺服器響應給客戶端cookie
Cookie[] cookies = req.getCookies(); 	// 獲得Cookie
cookie.getName();						// 獲得Cookie中的鍵key
cookie.getValue();						// 獲得Cookie中的值value
new Cookie("lastLoginTime", System.currentTimeMillis() + "");	// 新建一個Cookie
cookie.setMaxAge(24 * 60 * 60);			// 設定Cookie的有效期
resp.addCookie(cookie);					// 響應給客戶端一個Cookie

Cookie:一般儲存在本地的使用者目錄下, appdata;

儲存上次登入時間的例子:

package com.maple.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

/**
 * 儲存使用者上一次訪問的時間
 *
 * @author maple_w
 * Created on 21/07/28 028 19:59
 */
public class CookieServlet01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        PrintWriter out = resp.getWriter();

        // Cookie, 伺服器端從客戶端獲取
        Cookie[] cookies = req.getCookies();

        // 判斷Cookie是否存在
        if (cookies != null) {
            out.write("上次訪問的時間:");
            for (Cookie cookie : cookies) {
                String name = cookie.getName();
                String value = cookie.getValue();
                if (name.equals("lastLoginTime")) {
                    long l = Long.parseLong(value);
                    Date date = new Date(l);
                    out.write(date.toLocaleString());
                }
            }
        } else {
            out.write("首次訪問");
        }

        // 伺服器給客戶端響應一個cookie
        Cookie cookie = new Cookie("lastLoginTime", System.currentTimeMillis() + "");

        // 設定cookie有效期為1天
        cookie.setMaxAge(24 * 60 * 60);

        resp.addCookie(cookie);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

一個網站的Cookie是否存在上限?

  • 一個Cookie只能儲存一個資訊;
  • 一個web站點可以給瀏覽器傳送多個cookie,最多存放20個;
  • 300個Cookie,瀏覽器上限;
  • Cookie大小有限制,4kb;

刪除Cookie:

  • 不設定有效期,關閉瀏覽器,自動失效;
  • 設定有效期為0;(手動刪除)

編碼解碼:

URLEncoder.encode("狂神", "utf-8")
URLDecoder.decode(cookie.getValue(), "utf-8"))

如果要讀取中文Cookie,後臺顯示中文正常也不行,如果要瀏覽器顯示正常,還需要新增:

	// 新增這個才能有效讓頁面顯示中文不亂碼
	resp.setContentType("text/html;charset=utf-8");

讀取中文的小例子:

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		req.setCharacterEncoding("utf-8");
		resp.setCharacterEncoding("utf-8");
		// 新增這個才能有效讓頁面顯示中文不亂碼
		resp.setContentType("text/html;charset=utf-8");

		PrintWriter out = resp.getWriter();

		Cookie[] cookies = req.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				out.write(cookie.getName());
				out.write(URLDecoder.decode(cookie.getValue(), "utf-8"));
				System.out.println(cookie.getName());
				System.out.println(URLDecoder.decode(cookie.getValue(), "utf-8"));
			}
		}

		Cookie cookie = new Cookie("name", URLEncoder.encode("狂神", "utf-8"));
		resp.addCookie(cookie);
	}

Session (重點)

什麼是session:

  • 伺服器會給每個使用者(瀏覽器)建立一個Session物件。
  • 每個Session獨佔一個瀏覽器,只要瀏覽器沒有關閉,這個Session就存在。
  • 使用者登入後,整個網站都可以訪問。--> 儲存使用者資訊、儲存購物車資訊等

Session和Cookie的區別:

  • Cookie把使用者的資料寫給使用者的瀏覽器,瀏覽器儲存;(可以儲存多個)
  • Session把使用者的資料寫到使用者獨佔的Session中,伺服器端儲存;(儲存重要資訊,減少伺服器資源的浪費)
  • Session物件由伺服器建立,

使用場景:

  • 儲存一個登入使用者的資訊;
  • 購物車資訊;
  • 在整個網站中經常會使用的資料,將其儲存在session中;

使用session:
往Session中寫資訊:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解決亂碼問題
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 得到Session
        HttpSession session = req.getSession();

        // 給Session中存東西
        // session.setAttribute("name", "狂神");
        session.setAttribute("name", new Person("狂神", 33));

        // 獲取Session的ID
        String id = session.getId();
        // 判斷是否是新的Session
        if (session.isNew()) {
            resp.getWriter().write("session 建立成功, ID: " + id);
        } else {
            resp.getWriter().write("session 已經在伺服器中存在了, ID: " + id);
        }

        // 猜想Session做了什麼事情:
        // Cookie cookie = new Cookie("JSESSIONID",id);
        // resp.addCookie(cookie);

    }

從Session中讀取資訊:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 解決亂碼問題
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        // 得到Session
        HttpSession session = req.getSession();

        // String name = (String) session.getAttribute("name");
        Person person = (Person) session.getAttribute("name");
        System.out.println(person);

    }

清除Session:

@Override  
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
 HttpSession session = req.getSession();  
 session.removeAttribute("name");  
 // 手動登出session,但因為瀏覽器在訪問,會立即生成一個新的session  
 session.invalidate();  
}

或是在web.xml中設定預設失效時間:

    <!-- 設定session預設失效時間 -->
    <session-config>
        <!-- 15分鐘後session自動失效,分鐘為單位 -->
        <session-timeout>1</session-timeout>
    </session-config>

ServletContext (ApplicationContext)是在Session之上更高階的一個概念,可以儲存多個不同使用者的共享資訊,如使用者統計等。