Session的理解

  • Post author:
  • Post category:其他




一.Session简介


  • Session的使用场景

  • 当我们登陆电商网站时,无论浏览哪个页面都会显示登陆人的名字,还可以随时查看购物车里面的商品

  • 也就是说当一个用户浏览一个网站的不同页面时,服务器怎么知道此时是张三在访问还是李四在访问

这也就引出我们的另一个会话技术Session 与cookie不同session是保存在服务器端上,在每一次与浏览器的会话中,服务器都会创建该会话独享的session空间用于存储数据,用户浏览多个页面时可以从session对象中读取数据进行相关操作


  • 会话

在解释session前,我们要先了解什么是会话。会话就是用户通过浏览器访问多个网站页面,并关闭浏览器这一过程,严谨的讲一次会话和浏览器保存的JSessionID和服务器端保存的Session对象有关

总之,用户通过浏览器访问服务器,并操作Session时,服务器会在内存中为这次会话分配一个Session对象,被该浏览器所独占。

这个session可以看作一个容器/集合,默认存在时间为30分钟(可以在web.xml文件中修改)



二.Session的简单理解


1. Session的存储结构


session的存储结构类似于HashMap,相当于一张表

请添加图片描述


2. Session简单的执行流程

请添加图片描述


总结session的实现基于cookie,服务器端通过得到cookie来判断是一个新的会话,还是以前的会话



三.Session的使用


  • 创建session

getSession方法的调用在某些情况下就相当于创建了一个Session对象

HttpSession session = request.getSession();

什么时候创建session

  • 浏览器的HTTP请求cookie中没有携带JSESSIONID
  • 浏览器的HTTP请求cookie中携带了JSESSIONID,但在服务器内存中没有与其匹配的JESSIONID


    抓包分析


    如果浏览器没有携带JESSIONID,操作session时服务器会为该浏览器分配一个ID以cookie的形式返回给浏览器进行保存

    请添加图片描述

再此访问该服务器资源时浏览器会携带上次分配的JSESSIONID,到服务器端找到对应的session对象进行数据的操作

请添加图片描述


  • 向session添加/读取属性
session.setAttribute("user", "jbc");
session.getAttribute("user");

  • 移除session中的属性
session.removeAttribute("user");

  • 获取JESSIONID

每一个session对象都有与之唯一对应的JSESSIONID

session.getID();

  • 判断是否是新创建的session
session.isNew();



四.Session的生命周期

  • setMaxInterval方法设置session的生命周期(以秒为单位)

    正数是session的超时时间

    负数为永不超时

  • getMaxInterval()得到该session的生命周期

  • invalidate()销毁该session

  • 在没有设置session的超时时长时默认为30分钟失效

  • Tomcat会在底层轮询存储JSESSIONID-session的容器,如果最近访问时间

    lastAccessDate与现在的时间超过session的MaxInterval,就会销毁该session

要说明的是session的生命周期是:

浏览器能够访问到该session间隔的最大时长

,而不是累计时长,

在每次访问session时都会重置session的MaxInterval


代码举例

创建与访问该资源的浏览器关联的session对象,设置超时时长60秒

		HttpSession session = request.getSession();
        System.out.println("JSessionID= " + session.getId());
        session.setMaxInactiveInterval(60);
        session.setAttribute("user", "jbc");

读取当前会话的session中的数据

		HttpSession session = request.getSession();
        System.out.println("JSessionID= " + session.getId());
        System.out.println(session.getAttribute("user"));


抓包分析

由于我们没有携带JSESSIONID,服务器分配了这次会话的ID

请添加图片描述

分析可知,在超过60秒后,服务器会将这次会话的session销毁,

这时我们再想要读取该session中的数据时,我们发现服务器端又返回了一个新的JSESSIONID,说明原来的会话已经被销毁,再对session进行操作时,服务器认为当前是新的会话,会创建session对象并返回给浏览器SID

请添加图片描述



需要再次说明的是session的生命周期是指,间隔的最大时长,如果在间隔时间内再次访问就会重置他的生命周期



五.应用实例

1.只要密码为 666666, 我们认为就是登录成功 ,用户名不限制

2. 如果验证成功,则进入管理页面 ManageServelt.java ,否则进入 error.html

3. 如果用户直接访问 ManageServet.java , 重定向到到 login.html

此案例只是为了理解session做的简单案例

package homework;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebServlet(name = "LoginCheck", value = "/LoginCheck")
public class LoginCheck extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pwd = request.getParameter("pwd");
        //如果密码正确就创建一个会话
        if ("666666".equals(pwd)) {
            HttpSession session = request.getSession();
            session.setAttribute("username", request.getParameter("username"));
            request.getRequestDispatcher("/Manger").forward(request, response);
        } else {
        //否则请求转发到error.html         
        request.getRequestDispatcher("/error.html").forward(request, response);
        }
    }

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

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "Manger", value = "/Manger")
public class Manager extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        String username = (String) session.getAttribute("username");
        //获得一个session对象如果该session对象是刚刚创建的
        //该对象就不会存储username这一属性,就可以判断用户是非法访问的该资源
        if (username == null) {
        //重定向到login.html
            response.sendRedirect("/session/login.html");
        } else {
        //如果是通过CheckLogin通过的就显示成功登陆
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.print("<h1>欢迎" + username + "登陆</h1>");
        }
    }

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



版权声明:本文为m0_67883947原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。