Session

Session簡單介紹

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

Session和Cookie的主要區(qū)別

  • Cookie是把用戶的數(shù)據(jù)寫到用戶的瀏覽器。
  • Session技術(shù)把用戶的數(shù)據(jù)寫到用戶獨占的session中,tomcat服務(wù)器內(nèi)存中。
  • Session對象由服務(wù)器創(chuàng)建,開發(fā)人員可以調(diào)用request對象的getSession方法得到session對象

session機制演示圖

image

服務(wù)器通過request對象的getSession方法創(chuàng)建出session對象后,會把session的id號,以cookie的形式回寫給客戶機,這樣,只要客戶機的瀏覽器不關(guān),再去訪問服務(wù)器時,都會帶著session的id號去,服務(wù)器發(fā)現(xiàn)客戶機瀏覽器帶session id過來了,就會使用內(nèi)存中與之對應(yīng)的session為之服務(wù)。

@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());
    }
}

在開發(fā)者工具中查看,第一發(fā)出時請求響應(yīng)頭當(dāng)中有Set-Cooie


image

再次請求時(刷新),響應(yīng)頭當(dāng)中將沒有Set-Cookie,而請求頭當(dāng)中將有Cookie發(fā)回給服務(wù)器,


image

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

Session cookie

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

關(guān)閉瀏覽器,只會使瀏覽器端內(nèi)存里的session cookie消失,但不會使保存在服務(wù)器端的session對象消失,同樣也不會使已經(jīng)保存到硬盤上的持久化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);
    }
}

關(guān)閉瀏覽器,5分鐘之內(nèi)打開瀏覽器,session依然有效。

HttpSession的生命周期

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

session何時會銷毀

A.調(diào)用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.服務(wù)器卸載了當(dāng)前WEB應(yīng)用

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的過期時間,若想單獨設(shè)置還是像上面那樣單獨設(shè)置),單位分鐘。

 <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 {

    //設(shè)置驗證圖片的寬度, 高度, 驗證碼的個數(shù)
    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 中創(chuàng)建一個 Graphics2D 圖像
        Graphics2D graphics = null;
        graphics = buffImg.createGraphics();

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

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

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

        graphics.setColor(Color.BLACK);

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

        //隨機產(chǎn)生 15 條干擾線, 使圖像中的認(rèn)證碼不易被其它程序探測到
        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++){

            //用隨機產(chǎn)生的顏色將驗證碼繪制到圖像中
//            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 {

        //創(chuàng)建 randomCode 對象, 用于保存隨機產(chǎn)生的驗證碼, 以便用戶登錄后進行驗證
        StringBuffer randomCode = new StringBuffer();
        Random random = new Random();
        for(int i = 0; i < codeCount; i++){
            //得到隨機產(chǎn)生的驗證碼數(shù)字
            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("驗證碼錯誤");
        }
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

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