Session

Session簡單介紹

在WEB開發中,服務器可以為每個瀏覽器用戶創建一個會話對象(session對象),注意:一個瀏覽器用戶獨占一個session對象(默認情況下)。因此,在需要保存用戶數據時,服務器程序可以把用戶數據寫到瀏覽器用戶獨占的session中,當用戶使用瀏覽器訪問該web應用的其它servlet時,其它servlet可以從用戶的session中取出該用戶的數據,為用戶服務,從而實現數據在多個頁面中的共享。

Session和Cookie的主要區別

  • Cookie是把用戶的數據寫到用戶的瀏覽器。
  • Session技術把用戶的數據寫到用戶獨占的session中,tomcat服務器內存中。
  • Session對象由服務器創建,開發人員可以調用request對象的getSession方法得到session對象

session機制演示圖

image

服務器通過request對象的getSession方法創建出session對象后,會把session的id號,以cookie的形式回寫給客戶機,這樣,只要客戶機的瀏覽器不關,再去訪問服務器時,都會帶著session的id號去,服務器發現客戶機瀏覽器帶session id過來了,就會使用內存中與之對應的session為之服務。

@WebServlet(name = "TestServlet",urlPatterns = "/test")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession httpSession = request.getSession();
        httpSession.setAttribute("user","zhangsan");
        System.out.println(httpSession.getId());
    }
}

在開發者工具中查看,第一發出時請求響應頭當中有Set-Cooie


image

再次請求時(刷新),響應頭當中將沒有Set-Cookie,而請求頭當中將有Cookie發回給服務器,


image

兩個Cookie完全一樣,以后的每次請求都會找到那個session對象,完成跟蹤。

Session cookie

session通過SessionID來區分不同的客戶, session是以cookie為基礎的,系統會創造一個名為JSESSIONID的輸出cookie,這稱之為session cookie,以區別persistent cookies(也就是我們通常所說的cookie),session cookie是存儲于瀏覽器內存中的,并不是寫到硬盤上的,session cookie針對某一次會話而言,會話結束session cookie也就隨著消失了,而persistent cookie只是存在于客戶端硬盤上的一段文本。

關閉瀏覽器,只會使瀏覽器端內存里的session cookie消失,但不會使保存在服務器端的session對象消失,同樣也不會使已經保存到硬盤上的持久化cookie消失。

持久化session cookie

@WebServlet(name = "TestServlet",urlPatterns = "/test")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession httpSession = request.getSession();
        Cookie cookie = new Cookie("JESSIONID",httpSession.getId());
        cookie.setMaxAge(300);
    }
}

關閉瀏覽器,5分鐘之內打開瀏覽器,session依然有效。

HttpSession的生命周期

問題:用戶開一個瀏覽器訪問一個網站,服務器是不是針對這次會話創建一個session?
答:不是的。session的創建時機是在程序中第一次去執行request.getSession();這個代碼,服務器才會為你創建session。
問題:關閉瀏覽器,會話結束,session是不是就銷毀了呢?
答:不是的。session是30分鐘沒人用了才會死,服務器會自動摧毀session。

session何時會銷毀

A.調用invalidate()方法,該方法使HttpSession立即失效

@WebServlet(name = "TestServlet",urlPatterns = "/test")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession httpSession = request.getSession();
        httpSession.invalidate();
    }
}

B.服務器卸載了當前WEB應用

C.超出session過期時間

@WebServlet(name = "TestServlet",urlPatterns = "/test")
public class TestServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession httpSession = request.getSession();
        httpSession.setMaxInactiveInterval(30);//單位秒
    }
}

web.xml文件中也可以修改session的過期時間(全局的,所有的session的過期時間,若想單獨設置還是像上面那樣單獨設置),單位分鐘。

 <session-config>
        <session-timeout>30</session-timeout>
 </session-config>

Session的典型案例:一次性驗證碼

生成驗證碼圖像的工具類GenerateCode.java 代碼

package util;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * Created by ttc on 2018/3/15.
 */
public class GenerateCode {

    //設置驗證圖片的寬度, 高度, 驗證碼的個數
    private int width = 152;
    private int height = 40;

    //驗證碼字體的高度
    private int fontHeight = 38;

    //驗證碼中的單個字符基線. 即:驗證碼中的單個字符位于驗證碼圖形左上角的 (codeX, codeY) 位置處
    private int codeX = 25;//width / (codeCount + 2);
    private int codeY = 36;

    public BufferedImage Generate(String code)
    {
        //定義一個類型為 BufferedImage.TYPE_INT_BGR 類型的圖像緩存
        BufferedImage buffImg = null;
        buffImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);

        //在 buffImg 中創建一個 Graphics2D 圖像
        Graphics2D graphics = null;
        graphics = buffImg.createGraphics();

        //設置一個顏色, 使 Graphics2D 對象的后續圖形使用這個顏色
        graphics.setColor(Color.WHITE);

        //填充一個指定的矩形: x - 要填充矩形的 x 坐標; y - 要填充矩形的 y 坐標; width - 要填充矩形的寬度; height - 要填充矩形的高度
        graphics.fillRect(0, 0, width, height);

        //創建一個 Font 對象: name - 字體名稱; style - Font 的樣式常量; size - Font 的點大小
        Font font = null;
        font = new Font("", Font.BOLD, fontHeight);
        //使 Graphics2D 對象的后續圖形使用此字體
        graphics.setFont(font);

        graphics.setColor(Color.BLACK);

        //繪制指定矩形的邊框, 繪制出的矩形將比構件寬一個也高一個像素
        graphics.drawRect(0, 0, width - 1, height - 1);

        //隨機產生 15 條干擾線, 使圖像中的認證碼不易被其它程序探測到
        Random random = null;
        random = new Random();
        graphics.setColor(Color.GREEN);
        for(int i = 0; i < 30; i++){
            int x = random.nextInt(width);
            int y = random.nextInt(height);
            int x1 = random.nextInt(20);
            int y1 = random.nextInt(20);
            graphics.drawLine(x, y, x + x1, y + y1);
        }

        graphics.setColor(Color.BLACK);
        for(int i = 0; i < code.length(); i++){

            //用隨機產生的顏色將驗證碼繪制到圖像中
//            graphics.setColor(Color.BLUE);
            graphics.drawString(String.valueOf(code.charAt(i)), (i + 1)* codeX, codeY);
        }

        return buffImg;
    }
}

ValidateColorServlet

@WebServlet("/validateColorServlet")
public class ValidateColorServlet extends HttpServlet {
    private int codeCount = 4;

    //驗證碼由哪些字符組成
    char [] codeSequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz23456789".toCharArray();

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //創建 randomCode 對象, 用于保存隨機產生的驗證碼, 以便用戶登錄后進行驗證
        StringBuffer randomCode = new StringBuffer();
        Random random = new Random();
        for(int i = 0; i < codeCount; i++){
            //得到隨機產生的驗證碼數字
            String strRand = null;
            strRand = String.valueOf(codeSequence[random.nextInt(36)]);
            randomCode.append(strRand);
        }

        GenerateCode generateCode = new GenerateCode();
        BufferedImage buffImg =generateCode.Generate(randomCode.toString());

        request.getSession().setAttribute("CHECK_CODE", randomCode.toString());

        //禁止圖像緩存
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        //將圖像輸出到輸出流中
        ServletOutputStream sos = null;
        sos = response.getOutputStream();
        ImageIO.write(buffImg, "jpeg", sos);
        sos.close();

    }
}

check.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>Insert title here</title>
</head>
<body>
    <form action="checkCodeServlet" method="post">
        username:<input type="text" name="username">
        checkCode:<input type="text" name="check">
        <img src="${pageContext.request.contextPath }/validateColorServlet">
        <input type="submit" value="Submit">
    </form>
</body>
</html>

CheckCodeServlet

package com.neusoft.javaweb.checkcode;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class CheckCodeServlet
 */
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String strCheckCode = request.getParameter("check");
        String checkCode = (String)request.getSession().getAttribute("CHECK_CODE");
        
        if(strCheckCode.equalsIgnoreCase(checkCode)) {
            response.sendRedirect("hello.jsp");
        }else {
            response.setContentType("text/html");
            response.setCharacterEncoding("utf-8");
            PrintWriter pr = response.getWriter();
            pr.println("驗證碼錯誤");
        }
    }

}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容

  • 會話(Session)跟蹤是Web程序中常用的技術,用來跟蹤用戶的整個會話。常用的會話跟蹤技術是Cookie與Se...
    chinariver閱讀 5,645評論 1 49
  • 目錄Cookie機制什么是CookieCookie的不可跨域名性Unicode編碼:保存中文BASE64編碼:保存...
    Tomatoro閱讀 16,970評論 7 186
  • 寫在前面 cookie和session的區別: 1、cookie數據存放在客戶的瀏覽器上,session數據放在服...
    Pitfalls閱讀 1,529評論 0 17
  • 一個流浪中的小女孩,一個孤單著的小女孩,一個失去母親的小女孩在水泥地上簡單的勾勒出母親的懷抱,然后依偎在這個虛擬的...
    忻州遠影閱讀 265評論 0 1
  • 今天下午三點,爸爸把我送到我上籃球課的籃球場上,我高高興興地進來了,我趕緊到集體里,之后老師說要玩游戲,我太高興了...
    11小溪流連星皓閱讀 250評論 0 1