如何在个人web项目中使用会话技术(cookie&session)?

编译软件:IntelliJ IDEA 2019.2.4 x64
操作系统:win10 x64 位 家庭版
服务器软件:apache-tomcat-8.5.27



一. 什么是会话?

翻开百度百科关于“会话”的词条,它是这样描述:“在计算机术语中,会话是指一个终端用户与交互系统进行通讯的过程,比如从输入账户密码进入操作系统到退出操作系统就是一个会话过程。”,诚然,也确是如此。

当客户端(终端用户)与服务器相互通信时,从客户端向服务器发出的一次请求开始,到服务器回应给客户端的一次响应结束,我们将其称为是一次交互。举个例子,比如当我们登录中国银行app上去查询银行卡的余额,当我们点击软件上的查询按钮,到app上显示余额数字时的一瞬间,就产生了一次交互。

而一次会话,则是由一次乃至n次交互共同构成。 比如当我们登录中国银行app到退出app的过程就是一个会话过程。


二. 为什么要使用会话技术?

目的:

为保持用户登录状态

什么意思?

当用户在登录之后,会在服务器中保存该用户的登录状态,当该用户后续访问该web项目中的其它动态资源经过(Servlet或者Thymeleaf)响应的时候,能够判断当前是否是已经登录过的。
这样哪怕用户手滑叉掉服务器的主页链接,而再次点击登录不必重复输入用户名与密码去登录。

好处:

扫描二维码关注公众号,回复: 14983875 查看本文章
  • 可以提高用户的使用体验和减少重复的操作
  • 有助于提供更为个性化的服务,让用户感受到更高效、便捷的使用体验。

三. 如何使用会话技术?

3.1 Cookie(客户端的会话技术)

简介:

Cookie是一种客户端的会话技术,它是服务器存放在浏览器(客户端)的一小份数据,浏览器以后每次访问该服务器的时候都会将这小份数据携带到服务器去。

作用:

  1. 在浏览器中存放数据
  2. 将浏览器中存放的数据携带到服务器

3.1.1 如何将数据保存到cookie内?

步骤:

  1. 创建Cookie对象并设置数据

  2. 将cookie添加到响应报文

案例:演示创建cookie对象并添加至响应报文中

代码演示如下:

//1.创建Cookie对象并设置数据(ke与value的结构)
Cookie cookie01=new Cookie("adminKey","adminValue");
Cookie cookie02=new Cookie("rootKey","rootValue");
//2.将cookie添加到响应报文
response.addCookie(cookie01);
response.addCookie(cookie02);

在这里插入图片描述

cookie数据的特点:

  • 一旦cookie被保存到客户端,在以后的每次请求中都会带着所有的cookie

    注意:

    假设你此时用Google浏览器保存刚设的cookie,再开个浏览器连接服务器,发出请求,你无法获得存放在Google浏览器里的cookie

  • 此时添加cookie被称为瞬时cookie,一旦浏览器关闭,cookie就会消失(浏览器关闭,会话就结束)

    思考:为什么浏览器一关闭,这个cookie就会消失?

    它之所以被称为瞬时cookie,是因为它被存放在运行内存中。我们电脑上每个程序的开启,cpu都会为该程序分配一个进程,而进程则会得到一个独立的内存,而cookie则是存储到这个独立的运行内存中。故而浏览器的进程一结束,cookie自然也就消失了。

3.1.2 如何将数据从cookie中取出来?

案例:演示把刚才设的cookie值取出来

代码演示如下:

//从请求报文中获得cookie,返回cookie列表
Cookie[] cookies = request.getCookies();
//判断cookie列表中有无空值,避免空指针异常
if (cookies!=null){
    
    
    //遍历列表中的每一个cookie
    for (Cookie cookie : cookies) {
    
    
        //获得cookie的key值
        System.out.println(cookie.getName());
        //获得cookie的value值
        System.out.println(cookie.getValue());
    }
}

3.1.3 cookie数据的有效时间

如果我们不设置Cookie的有效时间,默认情况下Cookie的有效期是一次会话范围内,我们可以通过cookie的 setMaxAge() 方法让Cookie持久化保存到浏览器上

  • 会话级Cookie(未设置有效时间)
    • 服务器端并没有明确指定Cookie的存在时间
    • 在浏览器端,Cookie数据存在于内存中
    • 只要浏览器还开着,Cookie数据就一直都在
    • 浏览器关闭,内存中的Cookie数据就会被释放
  • 持久化Cookie(设置了有效时间)
    • 服务器端明确设置了Cookie的存在时间
    • 在浏览器端,Cookie数据会被保存到硬盘上
    • Cookie在硬盘上存在的时间根据服务器端限定的时间来管控,不受浏览器关闭的影响
    • 持久化Cookie到达了预设的时间会被释放

cookie.setMaxAge(int expiry)参数单位是,表示cookie的持久化时间,如果设置参数为0,表示将浏览器中保存的该cookie删除

设置的位置:在添加到响应报文之前设置它的有效时间

代码示例如下:

//设置cookie的有效时间,在该时间段内,该cookie会存放在磁盘,时间一过,它会消失
cookie01.setMaxAge(60);//单位是秒

3.1.4 设置cookie的携带条件

释义:

希望在什么样的请求路径下去携带该cookie

举例:

如果我们希望在访问"http://localhost:8080/day11_ajax_war_exploded/root"下
携带某一个cookie并已设置好条件,在浏览器网址栏键入该请求路径,浏览器发出请求后,请求报文中会包含该cookie值传给服务器,服务器可以获取到该cookie。

设置的位置:在添加响应报文之前设置一个请求路径

代码示例如下:

//设置cookie01只有在访问当前项目下的user下的请求时才会携带
cookie01.setPath(request.getContextPath()+"/user");//设置一个uri

3.1.5 案例(登录页面:实现记住用户和密码)

案例需求:在登录页面上实现记住用户名和密码

代码示例如下:

①搭建Thymeleaf的环境

a. 导入Thymeleaf的相关jar包

在这里插入图片描述

b. 粘贴viewBaseServlet
c. 在web.xml中配置Thymeleaf前缀和后置

<!--thymeleaf的前缀和后缀-->
<context-param>
    <param-name>view-prefix</param-name>
    <param-value>/WEB-INF/pages/</param-value>
</context-param>
<context-param>
    <param-name>view-suffix</param-name>
    <param-value>.html</param-value>
</context-param>

②在index.html内引入访问登录界面的超链接,准备登录界面(login.html)与登录成功界面(login_success.html),并引入Thymeleaf渲染表达式

//准备登录界面(login.html)并引入Thymeleaf渲染表达式
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <base th:href="@{/}">
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="cookie?flag=login" method="post">
        用户名:<input type="text" name="username" th:value="${username}"><br>
        密码:<input type="password" name="password" th:value="${password}"><br>
        <input type="checkbox" name="confirm"/>记住用户名和密码<br>
        <input type="submit" value="登录">
    </form>
</body>
</html>
//准备登录成功界面(login_success.html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登录成功</h1>
</body>
</html>

③在cookieServlet内编写相关代码实现功能

实现功能思路:

在登录界面上用户输入用户名与密码后,点击登录,浏览器发出请求,CookieServlet接收请求,调用login()方法,判定用户名与密码正确且用户已勾选“记住用户名与密码”时,它会从请求报文中获取请求参数username与password赋给两个cookie对象,将这两个cookie对象存放到响应报文中,目的是在响应给浏览器时让浏览器存储这两个cookie。然后在首页访问“登录”界面时,请求给CookieServlet,CookieServlet调用tologin()f方法,把请求报文中的cookie拿出来,存放在请求域内,最后用thymeleaf渲染登录界面,渲染的时候会把两个cookie从请求域拿出来替换进login.html中表单里的用户名与密码的thymeleaf渲染表达式【th:value=“${password}”】中,生成一个view对象响应给浏览器

//转发至login.html
protected void tologin(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
    String username="";
    String password="";
    Cookie[] cookies = request.getCookies();
    if (cookies!=null){
    
    
        for (Cookie cookie : cookies) {
    
    
            if ("username".equals(cookie.getName())){
    
    
                username=cookie.getValue();
            }else if ("password".equals(cookie.getName())){
    
    
                password=cookie.getValue();
            }
        }
    }
    request.setAttribute("username",username);
    request.setAttribute("password",password);
    this.processTemplate("login",request,response);
}

//登录功能实现
protected void login(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    String confirm = request.getParameter("confirm");


    if ("admin".equals(username) && "123456".equals(password)){
    
    
        if (confirm!=null){
    
    
            //设置cookie
            Cookie usernameCookie=new Cookie("username",username);
            Cookie passworCookie=new Cookie("password",password);

            //设置cookie的有效时间
            /*usernameCookie.setMaxAge(60*3);
            passworCookie.setMaxAge(60*3);*/

            //在响应报文中添加cookie
            response.addCookie(usernameCookie);
            response.addCookie(passworCookie);
        }
        //登录成功跳转至login_success.html
        System.out.println(username+"登录成功");
        this.processTemplate("login_success",request,response);
    }else {
    
    
        //登录失败停留在当前页面(login.html)
        System.out.println("用户名或密码错误");
        this.processTemplate("login",request,response);
    }


}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.2 Session(服务器端的会话技术)

简介:

session是服务器端的技术,数据存放在服务器端。 服务器为每一个浏览器开辟一块内存空间,即session对象。由于session对象是每一个浏览器特有的,所以用户的记录可以存放在session对象中

注意:

  • 服务器会为每一个客户端创建一个Session对象,该客户端每次访问如果需要session对象,就返回之前创建的
  • 服务器端的会话从第一次获得Httpsession对象开始的,至到Httpsession对象销毁结束

3.2.1 什么是会话域?

在 Web 应用中,会话域(Session Scope)是指一个会话周期内可见的范围。它通常用于存储在整个会话期间需要跨多个请求共享和访问的数据。

它与请求域,应用域之间的关系:

在 Java Web 开发中,会话域(Session Scope)、 请求域(Request Scope)和 应用域(Application Scope)都是指在不同范围内可见的数据存储方式。它们之间有以下关系:

  1. 会话域一个会话对应一个 HttpSession 对象,生命周期与会话保持一致。会话域中存储的数据在整个会话期间均可访问,包括多次请求过程中涉及到的数据。 可以使用 HttpSession对象提供的方法向会话中添加、获取或删除数据。
  2. 请求域一个请求对应一个 HttpServletRequest 对象,请求域中存储的数据只在当前请求中有效。 通过HttpServletRequest 对象提供的 setAttribute() ,getAttribute()等方法可以往请求域中添加和获取数据。
  3. 应用域一个应用对应一个 ServletContext 对象,应用域中存储的数据在整个应用程序运行过程中均可访问。 可以使用ServletContext 对象提供的方法向应用域中添加、获取或删除数据。

综上:它们之间的区别主要在于存储数据的范围和生命周期。会话域适合存储需要跨多个请求共享和访问的数据,在整个会话周期中保存;请求域适合存储只在当前请求中有效的数据;应用域适合存储全局通用的数据,在整个应用程序运行期间都可以访问。

它们之间的关系是一个包含关系,也就是应用域是所有范围的顶层容器,会话域是请求域的顶层容器,而请求域则包含了自身作用域以及转发或者包含的子请求所绑定的请求域数据。在进行数据存储和访问时,需要根据实际使用场景灵活选择合适的作用域,并使用相应的 API 进行操作。

3.2.2 session有哪些方法?

①得到Httpsession对象

注意:获得session(如果第一次调用的时候其实是创建session,第一次之后通过sessionId找到session进行使用)

代码示例如下:

request.getsession();

②设置共享数据

代码示例如下:

//在会话域内设置共享数据(key为sessionMsg,value为sessionvalue),根据key找到对应的value
session.setAttribute("sessionMsg","sessionvalue");

③获得共享数据

代码示例如下:

//在会话域内根据key为sessionMsg找对应的共享数据
object sessionMsg=session.getAttribute("sessionMsg");

④移除共享数据

代码示例如下:

//从请求域内删除key为sessionMsg的共享数据
session.removeAttribute("sessionMsg");

案例:在index.html中创建“得到Httpsession对象”,“设置共享数据”,“获得共享数据”,“移除共享数据”等四个方法的超链接以访问SessionServlet,依次调用其中创建的方法,开启两个浏览器点击上述四个超链接观察演示效果

代码演示如下:

①创建SessionServlet并在web.xml中配置其访问路径 /session

//创建SessionServlet并在web.xml中配置其访问路径 /session
<servlet>
    <servlet-name>SessionServlet</servlet-name>
    <servlet-class>Servlet.module.SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>SessionServlet</servlet-name>
    <url-pattern>/session</url-pattern>
</servlet-mapping>

②在index.html中创建四个方法的超链接以访问SessionServlet

//在index.html中创建四个方法的超链接以访问SessionServlet
<a href="session?flag=getsession">获得session对象</a><br>
<a href="session?flag=setValuesession">在session会话域内设置共享数据</a><br>
<a href="session?flag=getValuesession">在session会话域内获得之前设置的共享数据</a><br>
<a href="session?flag=removeValuesession">在session会话域内删除之前设置的共享数据</a><br>

③SessionServlet实现其四个方法

//SessionServlet实现其四个方法
import Servlet.base.BaseServlet;

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;

public class SessionServlet extends BaseServlet {
    
    
    protected void getsession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获得session对象,从这开启会话
        HttpSession session = request.getSession();
        System.out.println("session = "+session);

    }

    protected void setValuesession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获得并打印session对象,
        HttpSession session = request.getSession();
        System.out.println("session = "+session);
        //在会话域设置共享数据(key与value)【sessionKey=sessionValue】
        session.setAttribute("sessionKey","sessionValue");
    }

    protected void getValuesession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获得并打印session对象,
        HttpSession session = request.getSession();
        System.out.println("session = "+session);
        //获取在会话域设置的共享数据(key与value)
        Object sessionKey = session.getAttribute("sessionKey");//【sessionValue】
        System.out.println("sessionKey = "+sessionKey);
    }

    protected void removeValuesession(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //获得并打印session对象,
        HttpSession session = request.getSession();
        System.out.println("session = "+session);
        //删除在会话域设置的共享数据(key与value)【sessionValue】
        session.removeAttribute("sessionKey");
        Object sessionKey = session.getAttribute("sessionKey");
        System.out.println("sessionKey = "+sessionKey);
    }
}

在这里插入图片描述

在这里插入图片描述

3.2.3 服务器如何区分客户端和session对象的对应关系?

why?

是通过cookie实现区分的!session依赖于cookie。

实现原理:

①当客户端第一次访问服务器,调用getsession(),新建一个session对象,并且设置一个cookie给浏览器(jsessionid)

在这里插入图片描述

②当客户端第二次访间服务器,调用getsession(),就去获得请求中的jsessionid这个cookie,通过cookie的value值找到session对象

在这里插入图片描述

3.2.4 会话什么时候结束?

①客户端关闭(jsessionid这个cookie消失)

②强制失效

代码示例如下:

session.invalidate();//强制失效

③自动失效(达到最大空闲时间)

默认半小时 (无操作,没有往服务器发送过请求),从无操作之前的最后一次请求开始计算最大空闲时间

代码示例如下:

session.setMaxInactiveInterval(30);//单位是秒

3.2.5 session的应用场景

①通常是用于在 Web 应用程序中存储特定用户相关信息的,如

登录界面:保持用户的登录状态,注销

实现思路:

在servlet里登录的方法中将根据业务层查询返回的bean对象放在会话域内,利用会话域内bean对象的存亡来保持登录状态

②还可以存储各种用户相关的数据,例如用户 ID、用户名、角色、购物车等等。这些数据可以通过服务器端代码来设置、获取和删除。 使用 Session,可以实现以下功能:

1.用户认证和授权:使用 Session 来存储用户登录时输入的用户名和密码、对应的权限等信息,确保只有经过身份验证的用户才能访问应用程序中的受保护资源。

2.数据持久化:Session 可以使用 Cookie 或者 URL Rewriting 技术将数据保存在客户端,也可以在服务器端内存或文件中保存,从而实现数据持久化。

3.业务逻辑处理:根据当前 Session 中保存的信息,可以在后台执行逻辑操作,如购物车计算等。

3.2.6 getsession()方法的工作机制是怎样的?

前提:

浏览器正常访问服务器

工作机制:

1.调用getsession()创建session对象,判断请求中是否存在JSESSIONID这个cookie

判断存在根据JSESSIONID对应的cookie值去,然后在服务器中寻找对应的session对象

a.如果找到了session对象直接返回该session对象即可

b.找不到session对象新建一个session对象,并且设置JSESSIONID这个cookie

判断不存在新建一个session对象,并且设置JSESSIONID这个cookie

在这里插入图片描述


猜你喜欢

转载自blog.csdn.net/siaok/article/details/130296507