WEB开发会话技术03

10.问题引出

11.Session基本介绍

day21-web开发会话技术03 day21-web开发会话技术03

  1. 当用户打开浏览器,访问某个网站,操作session时,服务器就会在内存(在服务端)为该浏览器分配一个session对象,该session对象被这个浏览器独占,如上图

  2. 这个session对象也可以看做是一个容器/集合,session对象默认存在的时间为30min(在tomcat/conf/web.xml中可以修改)

    day21-web开发会话技术03

11.1session可以做什么

  1. 网上商城的购物车
  2. 保存登录用户的信息
  3. 将数据放入到Session中,供用户在访问不同页面时,实现跨页面访问数据
  4. 防止用户非法登录到某个页面
  5. .......

11.2如何理解session

  1. session存储结构示意图

    day21-web开发会话技术03

  2. 你可以把session看做是一容器(类似HashMap),有两列(k-v),每一行就是session的一个属性

  3. 每个属性包含有两个部分,一个是该属性的名字(String),一个是该属性的值(Object)

12.Session常用方法

  1. 创建和获取session(api一样)

    HttpSession session = request.getSession();
    

    第一次调用是创建Session会话,之后调用是获取创建好的Session对象

  2. 向session添加属性

    session.setAttribute(String name,Object val);
    
  3. 从session得到某个属性

    Object obj = session.getAttribute(String name);
    
  4. 从session删除某个属性

    session.removeAttribute(String name);
    
  5. isNew(); 判断是不是刚创建出来的Session

  6. 每个Session都有一个唯一标识的Id值(即JSESSIONID),通过getId()得到Session的会话Id值

13.Session底层实现机制

13.1原理分析图

day21-web开发会话技术03
day21-web开发会话技术03

整个过程如下:

一个浏览器向服务器发送请求,要操作session时,一定会调用request.getSession()方法。

如果服务器在本次会话中,创建了session,则在响应头中将以Set-Cookie:JSESSIONID=xxxx的形式返回一个cookie给浏览器保存。下一次浏览器发送请求时,服务器就可以拿到cookie中的JSESSIONID的值,在map中找到该浏览器对应的session,直接操作。

这里的map可以理解为在Tomcat中还维护了一个容器HashMap<String,HttpSession>,这个容器中以JSESSIONID为key,以session为value,完成两者的绑定。

13.2代码演示

演示Session底层实现机制-创建和读取Session

13.2.1创建session的实例分析

web.xml:

<servlet>
    <servlet-name>CreateSession</servlet-name>
    <servlet-class>com.li.session.CreateSession</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>CreateSession</servlet-name>
    <url-pattern>/createSession</url-pattern>
</servlet-mapping>

CreateSession:

package com.li.session;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class CreateSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println("CreateSession doPost被调用...");
        //1.获取session(同时也可能创建session)
        HttpSession session = request.getSession();//注意这个地方已经把sessionId分配了
        //2.给session获取id
        System.out.println("当前sessionid= " + session.getId());
        //3.给session存放一些数据
        session.setAttribute("email", "zs@qq.com");
        //4.给浏览器发送一个回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("<h1>创建/操作session成功...</h1>");
        writer.flush();
        writer.close();
    }
}
  1. 首先访问http://localhost:8080/cs/createSession:

    day21-web开发会话技术03

  2. 抓包显示:

    day21-web开发会话技术03

    走的是如下流程:

    day21-web开发会话技术03

  3. 服务器后端显示:

    day21-web开发会话技术03

  4. 此时浏览器存储的JSESSIONID变成了新的值:

    day21-web开发会话技术03

  5. 此时,如果再次访问服务器,就会携带cookie中新的jsessionid给服务器,服务器不再返回jsessionid。

    day21-web开发会话技术03

    ​ 走的是如下流程:

    day21-web开发会话技术03

  6. 如果redeployTomcat,关闭浏览器并重新打开,直接访问http://localhost:8080/cs/createSession,这时候的请求头将不会携带jsessionid(因为关闭浏览器时默认删除了cookie),服务器返回的响应头将会携带一个jsessionid(因为重新发布tomcat,会清空服务器内存,这时请求的资源createSession程序会创建一个session,因此服务器会返回一个与之关联的jsessionid)

    这时候走的就是如下流程:

    day21-web开发会话技术03

13.2.2读取session的实例分析

web.xml:

<servlet>
    <servlet-name>ReadSession</servlet-name>
    <servlet-class>com.li.session.ReadSession</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>ReadSession</servlet-name>
    <url-pattern>/readSession</url-pattern>
</servlet-mapping>

ReadSession:

package com.li.session;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
public class ReadSession extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //System.out.println("ReadSession doPost被调用...");
        //演示读取session
        //1.获取session,如果没有session也会创建
        HttpSession session = request.getSession();
        //2.给session获取id
        System.out.println("ReadSession 当前sessionid= " + session.getId());
        //3.读取属性
        Object email = session.getAttribute("email");
        if (email != null) {
            System.out.println("session属性 email= " + (String) email);
        } else {
            System.out.println("session中没有 email属性");
        }
        //3.给浏览器发送一个回复
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print("<h1>读取session成功...</h1>");
        writer.flush();
        writer.close();
    }
}
  1. redeployTomcat,首先在浏览器中访问http://localhost:8080/cs/createSession(目的是创建一个和浏览器关联的session,因为redeployTomcat会删除服务器的session)

  2. 然后访问http://localhost:8080/cs/readSession,并抓包:

    day21-web开发会话技术03

  3. 在服务器后台输出如下:第一行输出是我们创建session时获取的sessionid,第二行是我们读取session时获取的sessionid,并获取其属性。

    day21-web开发会话技术03

14.Session生命周期

  1. public void setMaxInactiveInterval(int interval):设置session的超时时间(以秒为单位),超过指定的时长,session就会被销毁。

  2. 值为正数的时候,设置session的超时时长。

  3. 值为负数时,表示永不超时

  4. public int getMaxInactiveInterval()表示获取session的超时时间

  5. public void invalidate()表示让当前的session会话立即无效

  6. 如果没有调用setMaxInactiveInterval(int interval)来指定session的生命时长,Tomcat会以session的默认时长为准,session的默认时长为30分钟,可以在tomcat目录的conf目录下的web.xml中设置。

    day21-web开发会话技术03

  7. Session的生命周期指的是:客户端两次请求的最大间隔时长,而不是累积时长。即当客户端访问了自己的session,session的生命周期将将从0开始重新计算。(指的是同一个会话两次请求之间的间隔时间)

    cookie的生命周期指的是累积时长

  8. 底层:Tomcat用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值,则将该会话销毁。