在Web发展史中,咱们知道浏览器与服务器间采用的是http协议,而这种协议是无状态的,因此这就致使了服务器没法知道是谁在浏览网页,但很明显,一些网页须要知道用户的状态,例如登录,购物车等。java
因此为了解决这一问题,前后出现了四种技术,分别是隐藏表单域,URL重写,cookie,session。而用的最多也是比较重要的就是cookie和session了。apache
首先来了解cookie浏览器
cookie是浏览器保存在用户电脑上的一小段文本,通俗的来说就是当一个用户经过http访问到服务器时,服务器会将一些Key/Value键值对返回给客户端浏览器,并给这些数据加上一些限制条件,在条件符合时这个用户下次访问这个服务器时,数据经过请求头又被完整地给带回服务器,服务器根据这些信息来判断不一样的用户。bash
也就是说,cookie是服务器传给客户端并保存在客户端的一段信息,这个Cookie是有大小,数量限制的!!服务器
当前Cookie有两个版本,分别对应两种设置响应头:“Set-Cookie”和“Set-Cookie2”。在Servlet中并不支持Set-Cookie2,因此咱们来看看Set-Cookie的属性项:cookie
属性项 | 属性项介绍 |
NAME=VALUE | 键值对,能够设置保存的Key/Value,这里NAME不能和其余属性项名字同样 |
Expires | 过时时间,在这个时间点后Cookie失效 |
Domain | 生成Cookie域名 |
Path | 该Cookie是在当前那个路径下生成的 |
Secure | 加密设置,设置他以后,只会在SSH链接时才会回传该Cookie |
如今,咱们假设这里有两个域名:session
域名A:a.b.f.com.cn
域名B:c.d.f.com.cndom
显然,域名A和域名B都是f.com.cn的子域名加密
综上所述,咱们知道了domain的用处,聪明的小伙伴已经发现了,单点登录就是用这个原理实现的。spa
Web服务器经过发送一个称为Set-Cookie的http消息来建立一个Cookie:
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]
这里咱们思考一个问题,当咱们在服务器建立多个Cookie时,这些Cookie最终是在一个Header项中仍是以独立的Header存在的呢?
int size = headers.size();
for(int i = 0;i < size;i++){
outputBuffer.sendHeader(headers.getName(i),headers.getValue(i));
}
复制代码
++ 接着,在客户端进行保存,如何保存呢?这里又要对Cookie进行进一步的了解。 ++
所谓会话级别Cookie,就是在浏览器关闭以后Cookie就会失效。
保存在硬盘的Cookie,只要设置了过时时间就是硬盘级别Cookie。
好的,如今cookie保存在了客户端,当咱们去请求一个URL时,浏览器会根据这个URL路径将符合条件的Cookie放在请求头中传给服务器。
各位客官看到这里实属不易,😀,但咱们仍是要想一想,Cookie是有大小限制和数量限制的,而且愈来愈多的Cookie表明客户端和服务器的传输量增长,可不能够每次传的时候不传全部cookie值,而只传一个惟一ID,经过这个ID直接在服务器查找用户信息呢?答案是有的,这就是咱们的session。
Session是基于Cookie来工做的,同一个客户端每次访问服务器时,只要当浏览器在第一次访问服务器时,服务器设置一个id并保存一些信息(例如登录就保存用户信息,视具体状况),并把这个id经过Cookie存到客户端,客户端每次和服务器交互时只传这个id,就能够实现维持浏览器和服务器的状态,而这个ID一般是NAME为JSESSIONID的一个Cookie。
当浏览器不支持Cookie功能时,浏览器会将用户的SessionCookieName(默认为JSESSIONID)重写到用户请求的URL参数中。格式:/path/Servlet;name=value;name2=value2?Name3=value3
会根据javax.servlet.request.ssl_session属性值设置SessionID。
注:若是客户端支持Cookie,又经过URL重写,Tomcat仍然会解析Cookie中的SessionID并覆盖URL中的SessionID
咱们先看session工做的时序图
当客户端访问到服务器,服务器会为这个客户端经过request.getSession()方法建立一个Session,若是当前SessionID尚未对应的HttpSession对象,就建立一个新的,并添加到org.apache.catalina.Manager的sessions容器中保存,这就作到了对状态的保持。固然,这个SessionID是惟一的
由图可知,session对象已经保存在了Manager类中,StandardManager做为实现类,经过requestedSessionId从StandardManager的sessions集合中取出StandardSession对象。
当Servlet容器关闭:
StandardManager将持久化没过时的StandardSession对象(必须调用Servlet容器中的stop和start命令,不能直接kill)
当Servlet容器重启时:
StandardManager初始化会重读这个文件,解析出全部session对象。
这里有一个误区,也是我以前的错误理解,就是我将session的生命周期理解成一次会话,浏览器打开就建立,浏览器关闭就销毁,这样理解是错的!!
session的声明周期是从建立到超时过时
也就是说,当session建立后,浏览器关闭,会话级别的Cookie被销毁,若是没有超过设定时间,该SessionID对应的session是没有被销毁的,
检查每一个Session是否失效是在Tomcat的一个后台线程完成的(backgroundProcess()方法中);除了后台进程检验session是否失效外,调用request.getSession()也会检查该session是否过时,固然,调用这种方法若是过时的话又会从新建立一个新的session。
Session将信息保存到服务器,Cookie将信息保存在客户端
当浏览器第一次访问服务器时,服务器建立Session并将SessionID经过Cookie带给浏览器保存在客户端,同时服务器根据业务逻辑保存相应的客户端信息保存在session中;客户端再访问时上传Cookie,服务器获得Cookie后获取里面的SessionID,来维持状态。
参考:alibaba丛书《深刻分析Java Web》