web开发会话技术-Session



Session是什么

  1. Session是服务器端技术,服务器在运行时为每一个用户的浏览器创建一个其独享的session对象/集合
  2. 由于session为各个用户浏览器独享,所以用户在访问服务器的不同页面时,可以从各自的session中读取/添加数据,从而完成相应任务

理解Session

  1. 你可以把session看作是一容器类似HashMap,有两列(K-V),每一行就是session的一个属性。
  2. 每个属性包含有两个部分,一个是该属性的名字(String),另外一个是它的值(Object)

Session常用方法

API解释
request.getSession()第1次调用是创建Session 会话,之后调用是获取创建好的Session对象
session.setAttribute(String name,Object val);向session添加属性
session.getAttibute(String name)从session得到某个属性
session.removeAttribute(String name)从session删除某个属性
session.isNew()判断是不是刚创建出来的
session.getId()获得sessionId(唯一标识Id值)

Session创建流程

  1. 浏览器A请求服务端时,并获取Session
  2. 服务端执行getSession(),如果发现该浏览器没有对应的Session对象,就会在内存中创建一个和浏览器A本次会话关联的Session对象(key-value),并分配SessionId
    ● 这个session只属于浏览器A
    ● 只与本次会话有关联:当会话结束(浏览器关闭)或者session超过了存活时间,下次获得Session就会重新创建
  3. 获得Session后(无论是新Session还是原本存在),可以对Session进行一些操作(crud)
  4. 当浏览器访问服务端其他资源时,服务端就可以通过浏览器发送过来的JsessionId在内存中获取到与当前浏览器关联的Session对象,进行操作(一个浏览器对应一个Session)
  5. 当有其他浏览器请求服务端,服务端就会重新创建与该浏览器对应的Session对象,对其使用

在这里插入图片描述

服务端如何通过浏览器找到对应Session

  1. 浏览器向服务器发出请求
  2. 服务端接收到请求后,会执行getSession()
  3. 判断浏览器是否带有JsessionID
    ● 如果没有携带JsessionID,那么会创建Session对象,并分配sessionID,在内存中布局<sessionID,session对象>
    ● 如果携带JsessionID,会判断在内存中是否有与sessionID=JsessionID对应的session对象
        ○ 如果没有对应的session对象,那么会创建Session对象,并分配sessionID
        ○ 如果有对应的session对象,直接操作session对象
  4. 如果这次会话,创建了session对象,则会将sessionID以cookie的方式(Set-Cookie: JessionID = xx)发送给浏览器
  5. 浏览器接收到cookie后,会将JsessionID保存到浏览器内存
  6. 当下次浏览器再次访问该服务端时,会将JessionID带上,通过http请求发送给服务端(Cookie: JSESSIONID=xx)

在这里插入图片描述

Session生命周期

  1. public void setMaxInactiveInterval(int interval)设置 Session的超时时间(以秒为单位),超过指定的时长,Session就会被销毁。
  2. 值为正数的时候,设定Session 的超时时长。
  3. 负数表示永不超时
  4. public int getMaxInactiveInterval();获取Session的超时时间
  5. public void invalidate(); 让当前Session会话立即无效
  6. 如果没有调用setMaxInactiveInterval()来指定Session的生命时长,Tomcat会以Session默认时长为准,Session默认的超时为30分钟,可以在tomcat的web.xml设置
  7. Session的生命周期指的是﹔客户端/浏览器两次请求最大间隔时长,而不是累积时长。即当客户端访问了自己的session,session的生命周期将从0开始重新计算。(指的是同一个会话两次请求之间的间隔时间)
  8. 底层:Tomcat用一个线程来轮询会话状态,如果某个会话的空闲时间超过设定的最大值,则将该会话销毁

在session生命周期内,如果有至少一次访问服务端,那么session的存活时间将被刷新,从最近一次访问的时间开始计算,也就是 最近一次访问session时间 + session设置的过期时间 = session死亡时间

最近一次访问session时间 : 浏览器再访问服务端时,服务端调用了getSession()方法

tomcat在启动时,会启动一个线程,这个线程的作用就是查看各个session对象是否过期

  • 服务端在保存session对象时,会将session对象的最近一次访问时间和存活时间记录下来,线程会每隔一段时间,扫描所有session对象,如果发现最近一次访问session时间 + session设置的过期时间 > 当前时间,那么线程就会删除这个session,当浏览器要调用这个session对象,就只能重新创建。
  • session的生命周期:两次访问session的最大间隔时间,也就是说,只要浏览器两次访问服务端的时间没有超过设置的过期时间,那么该cookie会一直存活下去(最近一次访问时间在不断的刷新)
  • session是否过期,取决于服务器是否还存在这个session对象。就算浏览器还保留着过期的JsessionID,只要访问服务端,服务端就会创建一个新的session对象,并把新的sessionID返回给浏览器,浏览器便会更新JsessionID

Session的作用

在这里插入图片描述

在这里插入图片描述

Session基本原理

当用户访问服务端,并操作session时,服务端就会在(服务端)内存配置一个session对象,该session对象是用户当前这个浏览器独享,当用户访问当前服务端的其他的网页时,服务端就会根据JSESSIONID(用户第一次访问服务端就会从服务端传回来一个JSESSIONID cookie对象)来查找对应的session对象,根据需要来读取Session对象中的数据来为用户提供服务
在这里插入图片描述

在这里插入图片描述

Session可以做什么

在这里插入图片描述

理解Session

在这里插入图片描述

Session常用方法

在这里插入图片描述
在这里插入图片描述

Session底层机制分析

Session创建流程

  1. 浏览器A请求服务端时,并获取Session
  2. 服务端执行getSession(),如果发现该浏览器没有对应的Session对象,就会在内存中创建一个和浏览器A本次会话关联的Session对象(key-value),并分配SESSIONID
    ● 这个session只属于浏览器A
    ● 只与本次会话有关联:当会话结束(浏览器关闭)或者session超过了存活时间,下次获得Session就会重新创建
  3. 获得Session后(无论是新Session还是原本存在),可以对Session进行一些操作(crud)
  4. 当浏览器访问服务端其他资源时,服务端就可以通过浏览器发送过来的JSESSIONID在内存中获取到与当前浏览器关联的Session对象,进行操作(一个浏览器对应一个Session)
  5. 当有其他浏览器请求服务端,服务端就会重新创建与该浏览器对应的Session对象,对其使用
    在这里插入图片描述

服务端如何通过浏览器找到对应Session

  1. 浏览器向服务器发出请求
  2. 服务端接收到请求后,会执行getSession()
  3. 判断浏览器是否带有JsessionID
    ● 如果没有携带JsessionID,那么会创建Session对象,并分配sessionID,在内存中布局<seeionID,session对象>
    ● 如果携带JsessionID,会判断在内存中是否有与sessionID=JsessionID对应的session对象
        ○ 如果没有对应的session对象,那么会创建Session对象,并分配sessionID
        ○ 如果有对应的session对象,直接操作session对象
  4. 如果这次会话,创建了session对象,则会将sessionID以cookie的方式(Set-Cookie: JessionID = xx)发送给浏览器
  5. 浏览器接收到cookie后,会将JsessionID保存到浏览器内存
  6. 当下次浏览器再次访问该服务端时,会将JessionID带上,通过http请求发送给服务端(Cookie: JSESSIONID=xx)
    在这里插入图片描述
    在这里插入图片描述

创建Session实例分析

CreateSession

public class CreateSession extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取session,同时也可能创建session
        HttpSession session = request.getSession();
        //2.给session获取id
        System.out.println("当前session" + session.getId());
        //3.给session存放数据
        session.setAttribute("email","px@qq.com");
    }

浏览器携带JsessionID,服务器内存中不存在该ID的session

这个JsessionID是在tomcat启动,默认访问的首页时,给浏览器发送了一个
但在服务端是不存在与这个JsessionID对应的session对象
在这里插入图片描述
访问http://localhost:8080/cs/CreateSession
请求头携带了JsessionID
在这里插入图片描述
服务端判断浏览器是否携带JsessionID-->携带JsessionID-->判断该JsessionID是否有对应的session对象-->没有对应的session对象-->创建session对象,并分配sessionID-->服务端将sessionID封装为cookie对象,并返回给浏览器-->浏览器保存(替换)JsessionID
在这里插入图片描述
在这里插入图片描述
查看后端 发现与发送的JsessionID确实是一样
在这里插入图片描述

浏览器携带JsessionID,服务器内存中存在该ID的session

浏览器带有上次访问浏览器的JsessionID
在这里插入图片描述
访问http://localhost:8080/cs/CreateSession
在这里插入图片描述
服务端判断是否浏览器是否携带JsessionID-->携带JsessionID-->判断该JsessionID是否有对应的session对象-->有对应的session对象-->直接操作session对象

只有创建了session对象,服务端才会返回JsessionID
在这里插入图片描述
并没有发生变化
在这里插入图片描述
在这里插入图片描述

浏览器没有携带JessionID

浏览器不存在JessionID在这里插入图片描述
访问http://localhost:8080/cs/CreateSession
没有携带JessionID
在这里插入图片描述
服务端判断是否浏览器是否携带JsessionID-->没有携带JsessionID-->创建session对象,并分配sessionID-->服务端将sessionID封装为cookie对象,并返回给浏览器-->浏览器保存JsessionID
在这里插入图片描述
在这里插入图片描述
与后端一致
在这里插入图片描述

读取Session实例分析

ReadSession

public class ReadSession extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //演示读取session
        //1.获取session,如果没有session,也会创建
        HttpSession session = request.getSession();
        //2.读取属性
        Object email = session.getAttribute("email");
        //3.获取id
        System.out.println("ReadSession 当前sessionId: " + session.getId());
        if (email != null) {
            System.out.println("session属性email=" + (String) email);
        } else {
            System.out.println("session没有email属性");
        }
    }

http://localhost:8080/cs/createSession
在服务端创建与此浏览器对应的Session,并分配SessionID -->将SessionID封装到http响应包中的Cookie-set(Cookie-set: JessionID=xxx)响应头中,返回给浏览器-->浏览器保存JessionID
在这里插入图片描述
http://localhost:8080/cs/readSession
将jessionID发送给浏览器
在这里插入图片描述
响应头没有返回JsessionID,证明找到了JessionID对应的session
在这里插入图片描述
在这里插入图片描述
查看后端,证明是同一个Session
在这里插入图片描述

Session生命周期

在这里插入图片描述

在这里插入图片描述
tomcat会起一个线程,来轮询每个session的上一次的会话时间,如果当前时间 -上一个会话时间 > 设置的存活时间,那么会直接删除掉这个session
在这里插入图片描述

Session实例应用举例

在这里插入图片描述
createSession2

public class CreateSession2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建cookie
        HttpSession session = request.getSession();
        //设置生命周期 - 30秒
        session.setMaxInactiveInterval(30);
        System.out.println("createSession2 SID: " + session.getId());
        //写入数据
        session.setAttribute("job", "java");
    }

readSession2

public class ReadSession2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取Session
        HttpSession session = request.getSession();
        System.out.println("readSession2 SID: " + session.getId());
        //读取Session属性
        Object job = session.getAttribute("job");
        if(job != null){
            System.out.println("读取到session属性 job=" + (String)job);
        } else {
            System.out.println("读取不到session属性 job,说明原来的session被销毁");
        }
    }

http://localhost:8080/cs/createSession2
浏览器并没有携带JsessionID,因此服务器创建了session对象(设置存活时间: 30秒),并将sessionID传回给浏览器
获取到了的JsessionID为A2F7E09286F59D8DC12981D42D4AAD52
在这里插入图片描述
在这里插入图片描述

在30秒内,去访问http://localhost:8080/cs/readSession2
将上次访问服务端获得的JessionID以cookie的形式发送给服务端
发送给服务端的JessionID为A2F7E09286F59D8DC12981D42D4AAD52
在这里插入图片描述
可以发现,服务端并没有发送新的JsessionID过来,证明获取到了session对象
在这里插入图片描述
在这里插入图片描述


此后30秒内,没有在对服务端进行访问

30秒后,再次访问http://localhost:8080/cs/readSession2
将上次访问的JsessionID以cookie的形式发送给服务端
发送给服务端的JessionID为A2F7E09286F59D8DC12981D42D4AAD52
在这里插入图片描述
发现响应包里,有一个响应头为Set-Cookie: JSESSIONID=776ACB536D6AA99C6C2B7D1995592139; Path=/cs; HttpOnly
证明上一个session已经过期,服务端在getSession()时,找不到浏览器发送过来JessionID对应的session对象-->自然会创建一个新的session对象-->并将session对象对应的sessionID包装成cookie的形式,发送给浏览器-->浏览器保存(替换)JsessionID
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


在这30秒,如果有至少一次访问服务端,那么session的存活时间将被刷新,从最近一次访问的时间开始计算,也就是 最近一次访问session时间 + session设置的过期时间 = session死亡时间

最近一次访问session时间 : 浏览器再访问服务端时,服务端调用了getSession()方法

tomcat在启动时,会启动一个线程,这个线程的作用就是查看各个session对象是否过期

  • 服务端在保存session对象时,会将session对象的最近一次访问时间和存活时间记录下来,线程会每隔一段时间,扫描所有session对象,如果发现最近一次访问session时间 + session设置的过期时间 > 当前时间,那么线程就会删除这个session,当浏览器要调用这个session对象,就只能重新创建。
  • session的生命周期:两次访问session的最大间隔时间,也就是说,只要浏览器两次访问服务端的时间没有超过设置的过期时间,那么该cookie会一直存活下去(最近一次访问在不断的刷新)
  • session是否过期,取决于服务器是否还存在这个session对象。就算浏览器还保留着过期的JsessionID,只要访问服务端,服务端就会创建一个新的session对象,并把新的sessionID返回给浏览器,浏览器便会更新JsessionID

Session生命周期-删除

deleteSession

public class DeleteSession extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //演示如何删除session
        HttpSession session = request.getSession();
        System.out.println("DeleteSession 的ID 为 " + session.getId());
        session.invalidate();
    }

访问:http://localhost:8080/cs/createSession,服务端创建session对象,浏览器获得JsessionID
在这里插入图片描述

访问:http://localhost:8080/cs/readSession,读取存放与session的值,是可以正常读取到的
在这里插入图片描述
在这里插入图片描述

访问:http://localhost:8080/cs/deleteSession ,删除浏览器发送来的JsessionID
在这里插入图片描述

访问:http://localhost:8080/cs/readSession,读取存放与session的值,此时,与浏览器发送来的JsessionID:51FE5D359F8A4ADAF160F761BCB08B14对应的session对象已经被删除,所以当调用getSession方法时,是会重新创建一个session,并把sessionID发送给浏览器
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Session经典案例–防止非法进入管理页面

在这里插入图片描述
在这里插入图片描述
login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录界面</title>
</head>
<body>
<h1>用户登录</h1>
<form action="/cs/loginCheckServlet" method="post">
    用户名: <input type="text" name="username"><br/>
    密 码: <input type="password" name="pwd"><br/>
    <input type="submit" value="登录">
</form>
</body>
</html>

error.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>失败界面</title>
</head>
<body>
<h1>登录失败</h1>
<a href="/cs/login.html">点击返回重新登录</a>
</body>
</html>

LoginCheckServlet

package com.study.session.HW;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * @author 珀筱
 */
public class LoginCheckServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pwd = request.getParameter("pwd");
        String username = request.getParameter("username");
        HttpSession session = request.getSession();
        if ("123".equals(pwd)) {
            session.setAttribute("login", "yes");
            session.setAttribute("username", username);
//            request.getRequestDispatcher("/manageServlet").forward(request, response);
            response.sendRedirect("/cs/manageServlet");
        } else {
            session.setAttribute("login", "no");
//            request.getRequestDispatcher("/error.html").forward(request, response);
            response.sendRedirect("/cs/error.html");
        }
    }

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

ManageServlet

package com.study.session.HW;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * @author 珀筱
 */
public class ManageServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//        System.out.println("MangeServlet()...");

        //获得session,用于该用户验证成功
        HttpSession session = request.getSession();
        Object login = session.getAttribute("login");
        if (login != null && "yes".equals((String)login)) {
            response.setContentType("text/html;charset=utf-8");
            PrintWriter writer = response.getWriter();
            Object username = session.getAttribute("username");
            writer.print("<h1>欢迎你管理员 " + (String) username + "</h1>");
            writer.flush();
            writer.close();
        } else {
//            request.getRequestDispatcher("/login.html").forward(request, response);
            response.sendRedirect("/cs/login.html");
        }
    }

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

cookie与session的区别

  1. cookie与session共同之处:cookie和session都是用来跟踪浏览器用户身份的会话方式。
  2. cookie是保存在浏览器内存中,而session是保存在服务端
  3. cookie中的数据在浏览器中是可以修改的,因此不安全,而session虽然安全,但如果访问量过多,会占用大量的服务器资源
  4. session中保存的是对象,cookie中保存的是字符串
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值