写点什么

Javaweb 之会话技术

作者:楠羽
  • 2022 年 9 月 26 日
    福建
  • 本文字数:4821 字

    阅读完需:约 16 分钟

1 会话技术

1.1 会话管理概述

1.1.1 什么是会话

这里的会话,指的是 web 开发中的一次通话过程,当打开浏览器,访问网站地址后,会话开始,当关闭浏览器(或者到了过期时间),会话结束。


举个例子:


​ 例如,你在给家人打电话,这时突然有送快递的配送员敲门,你放下电话去开门,收完快递回来后,通话还在保持中,继续说话就行了。

1.1.2 会话管理作用

什么时候会用到会话管理呢?最常见的就是购物车,当我们登录成功后,把商品加入到购物车之中,此时我们无论再浏览什么商品,当点击购物车时,那些加入的商品都仍在购物车中。


在我们的实际开发中,还有很多地方都离不开会话管理技术。比如,我们在论坛发帖,没有登录的游客身份是不允许发帖的。所以当我们登录成功后,无论我们进入哪个版块发帖,只要权限允许的情况下,服务器都会认识我们,从而让我们发帖,因为登录成功的信息一直保留在服务器端的会话中。


通过上面的两个例子,我们可以看出,它是为我们共享数据用的,并且是在不同请求间实现数据共享。也就是说,如果我们需要在多次请求间实现数据共享,就可以考虑使用会话管理技术了。

1.1.3 会话管理分类

在 JavaEE 的项目中,会话管理分为两类。分别是:客户端会话管理技术和服务端会话管理技术。


客户端会话管理技术


​ 它是把要共享的数据保存到了客户端(也就是浏览器端)。每次请求时,把会话信息带到服务器,从而实现多次请求的数据共享。


服务端会话管理技术


​ 它本质仍是采用客户端会话管理技术,只不过保存到客户端的是一个特殊的标识,并且把要共享的数据保存到了服务端的内存对象中。每次请求时,把这个标识带到服务器端,然后使用这个标识,找到对应的内存空间,从而实现数据共享。

1.2 客户端会话管理技术

1.2.1 Cookie 概述

1)什么是 Cookie

它是客户端浏览器的缓存文件,里面记录了客户浏览器访问网站的一些内容。同时,也是 HTTP 协议请求和响应消息头的一部分(在 HTTP 协议课程中,我们备注了它很重要)。

2)Cookie 的 API 详解

作用


它可以保存客户浏览器访问网站的相关内容(需要客户端不禁用 Cookie)。从而在每次访问需要同一个内容时,先从本地缓存获取,使资源共享,提高效率。


Cookie 的属性



细节


Cookie 有大小,个数限制。每个网站最多只能存 20 个 cookie,且大小不能超过 4kb。同时,所有网站的 cookie 总数不超过 300 个。


当删除 Cookie 时,设置 maxAge 值为 0。当不设置 maxAge 时,使用的是浏览器的内存,当关闭浏览器之后,cookie 将丢失。设置了此值,就会保存成缓存文件(值必须是大于 0 的,以秒为单位)。

3)Cookie 涉及的常用方法

创建 Cookie



/** * 通过指定的名称和值构造一个Cookie * * Cookie的名称必须遵循RFC 2109规范。这就意味着,它只能包含ASCII字母数字字符, * 不能包含逗号、分号或空格或以$字符开头。 * 创建后无法更改cookie的名称。 * * 该值可以是服务器选择发送的任何内容。 * 它的价值可能只有服务器才感兴趣。 * 创建之后,可以使用setValue方法更改cookie的值。 */public Cookie(String name, String value) {  validation.validate(name);  this.name = name;  this.value = value;}
复制代码


向浏览器添加 Cookie



/** * 添加Cookie到响应中。此方法可以多次调用,用以添加多个Cookie。 */public void addCookie(Cookie cookie);
复制代码


从服务器端获取 Cookie



/** * 这是HttpServletRequest中的方法。 * 它返回一个Cookie的数组,包含客户端随此请求发送的所有Cookie对象。 * 如果没有符合规则的cookie,则此方法返回null。 */ public Cookie[] getCookies();
复制代码

1.2.2 Cookie 的 Path 细节:浏览器什么时候带给服务器,什么时候不带

1)需求说明

创建一个 Cookie,设置 Cookie 的 path,通过不同的路径访问,从而查看请求携带 Cookie 的情况。

2)案例目的

通过此案例的讲解,同学们可以清晰的描述出,客户浏览器何时带 cookie 到服务器端,何时不带。

3)案例步骤

第一步:创建 JavaWeb 工程


沿用第一个案例中的工程即可。


第二步:编写 Servlet


/** * Cookie的路径问题 * 前期准备: *   1.在demo1中写一个cookie到客户端 *  2.在demo2和demo3中分别去获取cookie *    demo1的Servlet映射是   /servlet/PathQuestionDemo1 *    demo2的Servlet映射是   /servlet/PathQuestionDemo2 *    demo3的Servlet映射是   /PathQuestionDemo3 * */public class PathQuestionDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.创建一个Cookie Cookie cookie = new Cookie("pathquestion","CookiePathQuestion"); //2.设置cookie的最大存活时间 cookie.setMaxAge(Integer.MAX_VALUE); //3.把cookie发送到客户端 response.addCookie(cookie);//setHeader("Set-Cookie","cookie的值") }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
复制代码


/** * 获取Cookie,名称是pathquestion */public class PathQuestionDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取所有的cookie Cookie[] cs = request.getCookies(); //2.遍历cookie的数组 for(int i=0;cs!=null && i<cs.length;i++){ if("pathquestion".equals(cs[i].getName())){ //找到了我们想要的cookie,输出cookie的值 response.getWriter().write(cs[i].getValue()); return; } } }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
复制代码


/** * 获取Cookie,名称是pathquestion */public class PathQuestionDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.获取所有的cookie Cookie[] cs = request.getCookies(); //2.遍历cookie的数组 for(int i=0;cs!=null && i<cs.length;i++){ if("pathquestion".equals(cs[i].getName())){ //找到了我们想要的cookie,输出cookie的值 response.getWriter().write(cs[i].getValue()); return; } } }
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
复制代码


第三步:配置 Servlet


<!--配置Cookie路径问题案例的Servlet--><servlet>    <servlet-name>PathQuestionDemo1</servlet-name>    <servlet-class>com.itheima.web.servlet.pathquestion.PathQuestionDemo1</servlet-class></servlet><servlet-mapping>    <servlet-name>PathQuestionDemo1</servlet-name>    <url-pattern>/servlet/PathQuestionDemo1</url-pattern></servlet-mapping>
<servlet> <servlet-name>PathQuestionDemo2</servlet-name> <servlet-class>com.itheima.web.servlet.pathquestion.PathQuestionDemo2</servlet-class></servlet><servlet-mapping> <servlet-name>PathQuestionDemo2</servlet-name> <url-pattern>/servlet/PathQuestionDemo2</url-pattern></servlet-mapping>
<servlet> <servlet-name>PathQuestionDemo3</servlet-name> <servlet-class>com.itheima.web.servlet.pathquestion.PathQuestionDemo3</servlet-class></servlet><servlet-mapping> <servlet-name>PathQuestionDemo3</servlet-name> <url-pattern>/PathQuestionDemo3</url-pattern></servlet-mapping>
复制代码


第四步:部署工程


沿用第一个案例中的工程部署即可。

4)测试结果

通过分别运行 PathQuestionDemo1,2 和 3 这 3 个 Servlet,我们发现由 demo1 写 Cookie,在 demo2 中可以取到,但是到了 demo3 中就无法获取了,如下图所示:


5)路径问题的分析及总结

问题:demo2 和 demo3 谁能取到 cookie?答案:demo2 能取到,demo3 取不到分析:首先,我们要知道如何确定一个 cookie?那就是使用 cookie 的三个属性组合:<font color='red'><b>domain+path+name</b></font>这里面,同一个应用的 domain 是一样的,在我们的案例中都是 localhost。​ 并且,我们取的都是同一个 cookie,所以 name 也是一样的,都是 pathquestion。​ 那么,不一样的只能是 path 了。但是我们没有设置过 cookie 的 path 属性,这就表明 path 是有默认值的。接下来,我们打开这个 cookie 来看一看,在 ie 浏览器访问一次 PathQuestionDemo1 这个 Servlet:


Cookie 中的内容:



客户端什么时候带 cookie 到服务器,什么时候不带?​ 就是看请求资源 URI 和 cookie 的 path 比较。


​ <font color='red'>请求资源 URI.startWith(cookie 的 path) </font> 如果返回的是 true 就带,如果返回的是 false 就不带。


​ 简单的说: 就是看谁的地址更精细


​ 比如:Cookie 的 path: /国家 /省份 /城市


      请求资源URI  :       /国家      /省份                              不带      请求资源URI   :     /国家      /省份      /城市      /区县        带
复制代码



在我们的案例中:


1.3 服务端会话管理概述

1.3.1 HttpSession 概述

1)HttpSession 对象介绍

它是 Servlet 规范中提供的一个接口。该接口的实现由 Servlet 规范的实现提供商提供。我们使用的是 Tomcat 服务器,它对 Servlet 规范进行了实现,所以 HttpSession 接口的实现由 Tomcat 提供。该对象用于提供一种通过多个页面请求或访问网站来标识用户并存储有关该用户的信息的方法。简单说它就是一个服务端会话对象,用于存储用户的会话数据。


同时,它也是 Servlet 规范中四大域对象之一的会话域对象。并且它也是用于实现数据共享的。但它与我们之前讲解的应用域和请求域是有区别的。


2)HttpSession 的获取

获取 HttpSession 是通过 HttpServletRequest 接口中的两个方法获取的,如下图所示:



这两个方法的区别:



3)HttpSession 的常用方法

1.3.2 HttpSession 的入门案例

1)需求说明

在请求 HttpSessionDemo1 这个 Servlet 时,携带用户名信息,并且把信息保存到会话域中,然后从 HttpSessionDemo2 这个 Servlet 中获取登录信息。

2)案例目的

通过本案例的讲解,同学们可以清楚的认识到会话域的作用,即多次请求间的数据共享。因为是两次请求,请求域肯定不一样了,所以不能用请求域实现。


最终掌握 HttpSession 对象的获取和使用。

3)原理分析

HttpSession,它虽然是服务端会话管理技术的对象,但它本质仍是一个 Cookie。是一个由服务器自动创建的特殊的 Cookie,Cookie 的名称就是 JSESSIONID,Cookie 的值是服务器分配的一个唯一的标识。


当我们使用 HttpSession 时,浏览器在没有禁用 Cookie 的情况下,都会把这个 Cookie 带到服务器端,然后根据唯一标识去查找对应的 HttpSession 对象,找到了,我们就可以直接使用了。下图就是我们入门案例中,HttpSession 分配的唯一标识,同学们可以看到两次请求的 JSESSIONID 的值是一样的:


1.3.3 HttpSession 的钝化和活化

什么是持久态


​ 把长时间不用,但还不到过期时间的 HttpSession 进行序列化,写到磁盘上。


​ 我们把 HttpSession 持久态也叫做钝化。(与钝化相反的,我们叫活化。)


什么时候使用持久化


​ 第一种情况:当访问量很大时,服务器会根据 getLastAccessTime 来进行排序,对长时间不用,但是还没到过期时间的 HttpSession 进行持久化。


​ 第二种情况:当服务器进行重启的时候,为了保持客户 HttpSession 中的数据,也要对 HttpSession 进行持久化


注意


​ HttpSession 的持久化由服务器来负责管理,我们不用关心。


​ 只有实现了序列化接口的类才能被序列化,否则不行。

发布于: 刚刚阅读数: 3
用户头像

楠羽

关注

还未添加个人签名 2022.08.04 加入

还未添加个人简介

评论

发布
暂无评论
Javaweb之会话技术_技术_楠羽_InfoQ写作社区