Session经常被翻译为会话,其本来的含义是指有始有终的一系列动作/消息。比如打电话时,从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个Session。而在网络中,Session是指从一个浏览器窗口打开再到关闭的这个期间。
互联网应用层协议基本都是基于 HTTP 和 HTTPS 协议的,它们的本身都是无状态的, 也就是只负责网络的请求和响应。 我们只需要告诉服务器我们需要什么,服务器就会给我们返回相应的资源。 如果没有额外处理的话,服务器并不知道发起请求的人是谁,也无法根据请求者是谁来给你展现和你相关的内容了。
HTTP 协议之所以一开始被设计成这样,还是有一些历史原因的,当时的互联网多用于学术交流,只用于文章信息的展现,远没有像现在这么丰富多彩。所以在当时的背景下, HTTP 协议被设计成这样,其实也是很符合它的场景的。
但随着互联网应用越来越广泛,应用的形式也变得越来越多,我们的 Web 应用已不只限于提供简单的信息展现了,还需要用户能够与服务器进行交互,比如能够登录,可以在留言回复、可以进行购物、社交等。 这就需要 HTTP 协议能够记录用户的状态,而这个状态就可以由HttpSession来进行保存。

当用户第一次访问Servlet时,服务器端会给用户客户端创建一个独立的Session;
该Session会有一个Session ID(JSESSIONID),格式如:JSESSIONID=7F149950097E7B5B41B390436497CD21,其中JSESSIONID是固定的。而这个Session ID在响应浏览器的时候会被存储到Cookie中,从而被保存到浏览器中;
而后面的value值对应的则是给该客户端新创建的session的ID;
当用户再一次访问Servlet时,请求C都会携带着Cookie中的SessionID去访问;
服务器会根据这个Session ID去查看是否有对应的Session对象;
如果有就拿出来使用;如果没有就创建一个Session(相当于用户第一次访问)。#代码中设置session过期时间的方式
session.setMaxInactiveInterval(5);
#web.xml中设置session过期时间的方式
<session-config>
<session-timeout>30</session-timeout>
</session-config> Session数据保存在服务器端;
Session中可以保存任意类型的数据;
Session默认的生命周期是30分钟,可以手动设置更长或更短的时间。Cookie翻译成中文是甜饼的意思,其实就是一个小型的文本文件,用来保存一些简单的信息(浏览器对Cookie的内存大小是有限制的)。Cookie由服务器端生成,并且会发送给 User-Agent (一般是浏览器),服务器一般会告诉浏览器设置一下Cookie,然后浏览器会自动将该 Cookie 以key/value的格式保存到浏览器的某个目录下;等到下次请求同一网站时,浏览器会自动通过请求头发送该Cookie给服务器,前提是浏览器设置了启用Cookie功能。
Web应用程序是使用HTTP协议来传输数据的,而HTTP协议是无状态的协议,也就是说一旦数据交换完毕,客户端与服务器端的连接就会关闭,等再次交换数据就需要建立新的连接,这就意味着服务器无法从连接上跟踪会话。比如我们登陆一个网站的时候,会提醒你要不要记住账户和密码,这样下次来你就不用再次输入账号密码了,这就是Cookie的作用。当我们再次访问的时候,服务器会直接根据我们的Cookie来获取上一次取过的东西。
我们每次发送请求的时候,都会根据domain来设置相应的Cookie。Cookie有永久的,也有临时的,每个浏览器都有自己的Cookie,我们可以通过设置expires、max-age来设置保存日期,如果不设置的话默认是临时存储,也就是说关闭浏览器后Cookie就会消失。
document.cookie = 'expires=时间/max-age=秒'虽然网站news.baidu.com与同属于Baidu,但是域名却不一样,也就是说这两者之间是不能互相操作彼此Cookie的。只有域名和path都必须一样,才能相互访问彼此的Cooki。但是需要注意不同浏览器对path访问规定是不一样的,对于chrome,path必须为当前目录,设置为其他目录无效,当前页面只能访问当前目录的Cookie`。
Cookie有个数和大小的限制,大小一般是4k,但是不同的浏览器,具体的Cookie大小也是不同的。

Cookie是保存在浏览器本地的,是可以被修改的,所以敏感的数据不要放在Cookie里。
HttpSession是通过Servlet容器创建和管理的,像Tomcat/Jetty都是保存在内存中的。但是如果我们将Web应用横向扩展成分布式的集群,然后利用LVS或Nginx进行负载均衡,那么对来自同一用户的Http请求,将有可能被负载分发到两个不同的服务器实例中去。那么如何保证不同实例间的Session共享,就成为一个不得不解决的问题。
最简单的解决方法就是把Session数据保存到内存以外的一个统一的地方,例如Memcached/Redis中。那么问题又来了,如何替换掉Servlet容器,来创建和管理HttpSession呢?
我们都知道Session是由Web容器管理的,即一个Session只保存在一台机器上,适合于单体应用。但随着架构的演练,不断的向微服务分布式集群演进,此时传统的Session就不能工作了。如:现在有3台Web服务器,客户端通过Nginx负载均衡技术,来负载到某一台服务器上,用户此次的数据就保存到了这台服务器的Web容器中了。等用户下次请求时,如果被负载到其它机器上,那么就拿不到之前保存的数据了,这时候就需要整个服务器集群共享同一个Session。
为了解决所有服务器共享一个Session,那么Session就不能单独的保存在自己的Web容器中,而是要保存在一个公共的会话仓库(Session Repository)中,也就是说所有的服务器都要访问这同一个仓库,这样所有服务器的状态便都一致了。Spring Session支持的仓库有Reids、MongoDB、JDBC等。
默认情况下,在Spring Boot中,为Spring Session提供了几种存储方式:
在Spring Session可用的情况下,我们可以选择存储Session的存储类型StoreType。例如,按如下配置将使用JDBC作为后端存储:
spring.session.store-type=jdbc
# 通过设置`store-type`为`none`可以禁用Spring Session出于向后兼容,在Redis可用的情况下,Spring Boot中会默认自动配置及使用Redis来存储Spring Session。
另外每种存储方式都有特殊设置,例如,对于jdbc存储可自定义要存储的表名:
spring.session.jdbc.table-name=SESSIONSSpring Session是基于Servlet规范实现的一套Session管理框架,主要解决了分布式场景下的Session共享问题。Spring Session最核心的类是SessionRepositoryFilter过滤器,用于包装用户的请求和响应,我们可以在程序中直接替换掉HttpSession,而无需修改一行代码。而且也可以很方便的与Spring Security集成,增加诸如findSessionsByUserName、rememberMe等功能,限制同一个账号可以同时在线的Session数量(如设置成1,即可达到把前一次登录顶掉的效果)等等。
原文作者:;如有侵权,请联系管理员删除。