会话技术之Session详解_session数-程序员宅基地

技术标签: Java Web  java  cookie  session  

上一文中,我们详细的讨论了会话、会话技术,细致的分析了Cookie的作用和使用方法。我们知道,Cookie是用于在浏览器中保存会话信息的,并且可以在多次Http请求之间实现数据的共享。但是如果每次请求携带的Cookie信息过多,则会明显的增大服务器端程序的处理难度和降低传输效率。

​鉴于上面提出的问题,有请我们今日的主角—Session。

​注:关于会话、会话技术的描述请参考上篇博客

资源分配图

1.Session的概念

​Session同样也是会话技术的一种,和存储于客户端的Cookie不同,Session是存储于服务器端的。我们可以先简单的把Session理解为个人的储物柜,每个人有一个唯一对应的储物柜,用户可以根据手里的钥匙来操作储物柜。

资源分配图

​就在上面的例子中,比如说是一家健身房,当我们进入健身房后,前台小妹会给我们一把储物柜的钥匙(Cookie),我们拿着钥匙找到对应的柜子(Session),换装,健身…,换装,归还钥匙,此次健身结束。

​在上面这次健身经历中,从我们进入健身房到离开健身房就是一次完整的会话,前台小妹给我们的钥匙就是一个Cookie,钥匙上号码牌对应的柜子就是Session,每位健身者都只拥有一个储物柜,可以将衣服、背包、手机等物品存放其中,中间健身过程中比如买了瓶水、炸鸡等物品,一样可以放入储物柜中或拿在身边,这些内容即是会话过程中产生的数据,可以存储于客户端或服务器。

​想象一下,如果没有储物柜的存在(Session),我们则需将所有衣服、鞋子等等带在身边,每换一个项目就得将所有的东西一起携带过去,这也是我们说的如果把过多的信息存储在客户端的弊端。

2.如何获取Session

​在上面的例子中,我们讲到,一把钥匙对应一个储物柜。在Web应用中,一个客户端在服务器上也有一个对应这的Session,在当前会话结束前,这个Session被此客户端独享,当会话结束后,此Session会被销毁,内存会被回收。这个过程类似于健身房中储物柜的使用,使用结束归还钥匙,一个储物柜在不同的时间可以供多个健身者使用。

​Session的获取主要通过HttpServletRequest来完成的,我们来看下request中提供的两个方法:

//如果create为true,如果与request对应的Session不存在,则返回一个新创建的Session;
//如果create为false,如果与request对应的Session不存在,则返回null;
//如果与request对应的Session存在,则直接返回该Session,create的值true或false,效果相同
public HttpSession getSession(boolean create);
    
//等价于getSession(true)
public HttpSession getSession();

​上面两个方法有提到,与request对应的Session,这句话应该如何理解呢?我们知道,当浏览器发起请求时,请求参数,Cookie等信息都被封装在HttpServletRequest中,即request中包含客户端的Cookie信息(钥匙),当通过request去获取Session时,就会从request中得到钥匙信息,来判断当前服务器中是否有与之对应的Session存在。

​下面我们通过一个小示例来看下,request是怎么通过Cookie来找到与此次请求相关的Session的。我们新建一个SessionServlet,urlPattern默认,其中的doGet方法如下:

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

  //获取Session
  HttpSession session = request.getSession();
  //输出SessionId
  System.out.println("服务器端request的对应的SessionId:" + session.getId());
}

​浏览器中输入URL:http://localhost:8080/FirstProject/SessionServlet,访问此Servelt后,我们打开Chrome的控制态F12->Application->Storage->Cookies->http://localhost:8080(根据你输入的url来定),截图如下:

资源分配图

​后端的运行截图如下,我们可以看到,服务器端Session的sessionId属性和浏览器端保存的Cookie(name为JSESSIONID)的值是相同的。这里可不是一个巧合,而是一个非常精妙的设计,我们在上面一直提到一个开储物柜的钥匙是一个Cookie,更精确的来讲,是一个name=JSESSIONID的Cookie,其中存储的值我们就可以理解成号码牌,这个号码牌唯一对应一个Session(储物柜,其编号为sessionId)。

资源分配图

​这里还有一点让人比较疑惑的地方,我在服务端并没有创建一个name=JSESSIONID的Cookie呀,也没有添加任何Cookie到response中,怎么在Chrome中的是有的这个JSESSIONID这个Cookie?这里主要是因为,如果通过request获取Session时,如果新建了一个Session,则会自动创建一个Cookie,并将其添加到response中。

​下图为第一访问http://localhost:8080/FirstProject/SessionServlet时,此次Http请求对应的响应头消息,当我们刷新页面后,可以看到,响应头中没有了Cookie信息。

资源分配图
资源分配图

3.HttpSession API

​和Cookie相同,Tomcat在Servlet Api中提供了一个HttpSession接口,其中提供一些方法,让我们可以方便的操作Session,比如存储会话数据,设置一些属性等。

​下面我们来看下HttpSession提供的方法:

资源分配图

​其中的setAttribute、getAttribute、removeAtrribute方法是用来向Session这个储物柜中存取数据的,Session的也是一个域对象。

​我们还可以通过setMaxInactiveInterval方法,来设置Session的空闲超时间隔,默认的空闲超时间隔为30分钟。这里简单的解释下空闲超时间隔,比如客户端A在9点登入系统,创建了对应的Cookie和Session,此时对应Session的失效时间为9点30;如果用户在9点25时,在页面上向服务器发起了请求,那么对应Session的过期时间则变为9点55;如果在接下来的半小时,也就是9点55之前,客户端没有向服务器发起任何请求,则此Session会自动被销毁,解绑所有的绑定在此Session上的属性。如果想修改当前应用中所有Session的默认超时间隔,则可以在web.xml中增加如下配置:

<session-config>
  <session-timeout>30</session-timeout>
</session-config>

​在web.xml中配置的最大空闲超时间隔的单位是分钟,默认配置为30分钟。当session-timeout的值为0或者负数时,表示会话永不超时。不过不建议这么设置,因为Session中空闲超时时间存在的目的,就是可以让服务器能自动回收那些近期不在活跃的客户端对应的Session,这样才能保证内存资源不会因为积累大量的不活跃Session而耗尽。当然,当用户点击退出,主动结束会话时,我们同样可以使用invalidate方法来立即回收此Session。

4.Cookie与Session的区别与联系

​这部分属于面试时经常问到的问题,因此这里也简单的进行一下总结。

区别:Cookie是存储于客户端(浏览器)的,可以通过Http响应头和JavaScript存储到浏览器端;Session是存储在服务器端的,可以通过request来获取Session;一个客户端中一个domain下的Cookie的数量是有限的,尽量数量不超过50个;服务器端总的Session数量不限,只要内存空间允许即可,但一个客户端唯一对应一个Session;Cookie中的值只能是字符串,Session中绑定的属性为Object,可以存储任意的数据类型;Cookie的安全性低于Session。

联系:客户端存储的Cookie中,存在一个名为JSESSIONID的Cookie,用于唯一对应服务端的一个Session(当Session没有失效,并且没有被invalidate时);当获取Session时,如果是新建一个Session,会自动向客户端发送JSESSIONID这个Cookie,如果客户端已经存在,则更新此Cookie。

​上面技术两者之间的区别与联系了,其实Cookie和Session都是会话技术的一种,其出现的目的就是为了方便会话信息的追踪,但是这两者之间有可通过JSESSIONID来关联到一起,解决"一人一柜"的独立性需求,可以说是很精髓了。

​浏览器中的Cookie,如果在下次请求时自动将domain、path都符合Cookie自动装入request Header中,可在服务端通过request获取传来的Cookie,同样可以通过request获取与客户端唯一对一个的Session;而Session的功能就像是一个储物柜,客户端可以通过JSESSIONID这把钥匙找到session,我们可以将数据存储在此柜子中。

​我们在上面的例子中,Session的功能完全没有被体现出来,因为只做一个柜子的话,与申请一块内存直接存储信息相比,Session似乎没有什么飞跃性的优化,如果单独的讲Session,这里是这样的,功能很鸡肋,但是,如果是在JSP中,Session就是一个bug性的功能了,因为Session是JSP的内置对象,这么来理解吧,Session这个储物柜可以被你携带到JSP页面中,你可以在JSP页面中直接从Session中获取数据。想想吧,这样子直接省去了JS对数据的解析等问题,多么美好啊。

5.总结

​Session技术的出现,极大的促进了Web的发展,让JSP开发变得更简单快捷,再加上EL表达式对Session的加持,Session变得更加强劲。

​不过,现在的趋势是前后端分离,JSP的使用率目前非常低咯,估计再过个十年就要退出历史舞台了。和JSP荣誉与共的Session,也难逃此命运。现在更多的是用token技术,比如JWT(Json Web Token),让存储于客户端的信息更安全,而Session的储物柜的功能则可使用文件存储、数据库(关系型数据库,MySQL、Oracle等)、Redis等等来进行替代。

​江山代有才人出,各领风骚数百年。吾辈共勉!

参考阅读:

  1. Servlet基础之HttpServletRequest详解
  2. Servlet基础之HttpServletResponse详解
  3. 会话技术之Cookie详解

​又到了分隔线以下,本文到此就结束了,本文内容全部都是由博主自己进行整理并结合自身的理解进行总结,如果有什么错误,还请批评指正。

​Java web这一专栏会是一个系列博客,喜欢的话可以持续关注,如果本文对你有所帮助,还请还请点赞、评论加关注。

​有任何疑问,可以评论区留言。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_34666857/article/details/105546951

智能推荐

QML ListView 实现 滚动条方式_qml listview滚动条-程序员宅基地

文章浏览阅读3.2k次。import QtQuick 2.0import QtQuick.Controls 2.1Rectangle { id: rect width: 1920 height:1180 color:"black" ListView { id: list_view anchors.fill:parent mod..._qml listview滚动条

Windows如何通过Anaconda定时调用python脚本_anaconda中的python怎么做定时调用-程序员宅基地

文章浏览阅读1.3k次。如果你用的是Anaconda环境下的python,先把.ipybn文件转为.py文件在win 搜索框输入: 任务计划程序_anaconda中的python怎么做定时调用

Laravel-admin 后台的自定义页面用法_laravel-admin $form->action-程序员宅基地

文章浏览阅读1.7w次。Laravel-admin 这个后台很好用,几乎省去了html和js的困扰,让后台CURD变得优雅简洁。这是一个自定义面的Demo路由定义: $router-&gt;get('mails/send', 'MailController@send'); $router-&gt;post('mails/send', 'MailController@send');控制中写法..._laravel-admin $form->action

flink sql读取kafka数据写入数据湖Apache Hudi_kafka队列 flink 数据湖-程序员宅基地

文章浏览阅读781次。创建生产者[bigdata@bigdata1 bin]$ sh kafka-console-producer.sh --broker-list bigdata1:9092,bigdata2:9092,bigdata3:9092 --topic test_topic>{"id":13,"name":"justin"}创建kafka表CREATE TABLE user_behavior ( id BIGINT, name STRING) WITH ( 'connecto._kafka队列 flink 数据湖

如何使用 Yahoo! Finance stock API 获取股票数据_yahoo finance api 下载数据-程序员宅基地

文章浏览阅读6.9k次。如何使用 Yahoo! Finance stock API 获取股票数据本站曾介绍过,通过代码添加雅虎财经的股票走势图到自己网站的方法(添加美国股市,添加沪深股市),调用的是一张图片。今天在德馨网站,看到了从雅虎财经频道获取股票数据的API(Yahoo! Finance stoc_yahoo finance api 下载数据

SpringMVC+Spring+Mybatis框架整合MQTT通信协议+ActiveMQ作为中间件进行消息的发布与订阅_mqtt +activemq-程序员宅基地

文章浏览阅读5.2k次,点赞2次,收藏17次。最近做了一个小项目,简单描述下项目结构,主要是java与单片机进行通信,为了实现通信可以采用中间件和http的方式,但是本人因为最近在学习ActiveMQ,所以更加偏向前者,最终确定了采用消息中间件的方式进行通信。 首先完成的步骤分为这两步: 1、单片机采用MQTT的通信协议将一个消息发送到一个消息中间件(本人采用ActiveMQ,也可以采用其他的消息中间件),这里需要注意下..._mqtt +activemq

随便推点

Sawyer机械臂学习系列之Moveit!配置_ros2 sawyer-程序员宅基地

文章浏览阅读1.6k次,点赞5次,收藏19次。Sawyer机械臂学习系列之Moveit!配置_ros2 sawyer

信噪比讨论(matlab加噪方式、案例分析)_信道加噪-程序员宅基地

文章浏览阅读9.2k次,点赞8次,收藏87次。信噪比讨论11 参数确定首先明确几个符号的意义 :S:信号的平均功率 ..._信道加噪

页面平滑过渡全屏切换-程序员宅基地

文章浏览阅读118次。实现效果为页面平滑过渡全屏切换,点击导航和鼠标滚动都可以切换。效果图:代码:<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title> <meta http-..._页面 全屏 切换

Android中使用MD5对密码进行加密_安卓 用md5对用户密码进行加密的案例-程序员宅基地

文章浏览阅读4.9k次。Android中使用MD5对密码进行加密最近在做一个小小的项目,其中用到了登录和注册,登录注册的demo网上很多,这里就不详细描述,在注册新用户和登录时候,Android设备都要向服务器发送密码,为了用户的安全,密码一定不能明文发送,所以这里采用了MD5对密码进行加密,比较简单,直接看代码。在工程目录下先创建一个MD5类可以直接复制以下代码//此处导入你的包名import java.security_安卓 用md5对用户密码进行加密的案例

何时启用CheckPoint操作_什么时候启用checkpoint-程序员宅基地

文章浏览阅读1.2k次。1. 使用了有状态的transformation操作--比如updateStateByKey,或者reduceBykeyAndWindow操作,被使用了,那么checkpoint目录要求是必须提供的,也就是必须开启checkpoint机制,从而进行周期性的RDD checkpoint2. 要保证可以从Driver失败中进行恢复--元数据checkpoint需要启用,来进行这种情况的恢复要注意,并不..._什么时候启用checkpoint

VTK笔记——合并数据(vtkAppendPolyData)-程序员宅基地

文章浏览阅读4.8k次。数据的合并在3D应用中时常会用到,怎样合并数据,对于不同类型的数据,合并的方法却不相同。vtk中的数据集有很多类,主要包括结构化网络数据集、非结构化网络数据集、多边形数据集、结构化点集、线性网络数据集、非结构化点集等几类。_vtkappendpolydata

推荐文章

热门文章

相关标签