导语:
目前所写项目遇到几个问题:前后端分离下如何验证用户身份、用户登录后如何持久化,虽用cookie解决,但在编写过程中深感代码效率低下,希望寻求更高优质的解决思路,深入了解一下Session的背景、使用原理、使用环境。
1、http协议:
简单了解一下http协议可以更好理解session机制
- http协议是 “连接-请求-应答-关闭连接” 模式,是一种无状态协议(http只是一个传输协议)
- 因为http是无状态协议,所以客户端和服务端交互过程中,服务端无法判断客户端发来的请求是来自一个或者多个客户的,因此当服务端使用HttpSession存储会话数据时,客户端的每个请求应该包含一个唯一的session标识(sessionid、jsessionid)来告诉服务端,且该用户随后的所有请求都应包括这个标识号
- cookie规范是为了给http增加状态跟踪用的,但不是唯一的手段
2、HttpSession的概念:
- session可以理解成是客户端与服务端之间的一种通讯,服务端有能力区分不同的Session
- 当需要为客户端建立一个session时,servlet容器就创建了一个HttpSession对象。其中存储了和本session相关的信息(其中包括本session的唯一标志号)。所以,在一个servlet中有多少个不同用户连接,就会有多少个HttpSession对象。
- 对于session标识号(sessionID),有两种方式实现:cookies和URL重写。后边会讲解两种方式的使用环境
使用机理:
(1)从请求中提取HttpSession对象;
通过方法重载有两种方法来获取HttpSession对象
第一:HttpSession getSession(boolean creat) 和 HttpSession getSession()
(2)增加或删除HttpSession中的属性;
获取到HttpSession对象后,可以使用一些方法新增or修改一些参数:
第一:void setAttribute(String name, Object value)
第二:Object getAttribute(String name)
第三:void removeAttribute(String name)
(3)根据需要关闭HttpSession或使其失效
第一:服务器会把长时间没有活动的Session从服务器内存中清除,此时Session便失效。Tomcat中Session的默认失效时间为20分钟。
第二:前后两次请求超出了session指定的生命周期时间。其中Session的生命周期时间可以在web.xml配置,默认30分钟。
第三:成功地调用了session.invalidate()方法。
3、session的创建和存储:
- session在用户访问第一次访问服务器时创建,只有访问JSP、Servlet等程序时才会创建session(一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用
HttpServletRequest.getSession(true)这样的语句时才被创建),只访问HTML、IMAGE等静态资源并不会创建session,可调用request.getSession(true)强制生成session。 - session的存储位置有两种,一种是存储在客户端,另一种是存储在服务端
(1)存储在客户端
session存储在客户端,有且仅有一种方法 —— cookie,rewritting 和 hidden input 因为无法实现持久化管理,只能算做为交换sessionid的一种方式(我们称为:a method of session tracking/一种会话跟踪方法)
(2)存储在服务端
由于B/S计算模型中计算是在服务器端完成的,客户端只有简单的显示逻辑,所以,Session数据对客户端应该是透明的不可理解的并且应该受控于服务端,但它的正常运行仍然需要客户端浏览器的支持。 因为HTTP协议的无状态性,Session不能依据HTTP连接来判断是否为同一客户,所以需要通过cookie作为session的唯一标识号进行区分。因此服务器向客户端浏览器发送一个名为JSESSIONID的Cookie,它的值为该Session的id(也就是HttpSession.getId()的返回值)。Session依据该Cookie来识别是否为同一用户。
两种方式实现session唯一标识:cookies和URL重写
参考:https://blog.csdn.net/seagal890/article/details/41623955
使用服务端还是客户端session存储要看应用的实际情况的。一般来说不要求用户注册登录的公共服务系统,无需用户登录的系统唯一能够标识用户的就是用户的电脑;而有用户管理的系统则可以通过用户id来管理用户个人数据,从而提供任意复杂的个性化服务;
4、session监听接口:
在javax.servlet.http包里一共定义了四个session监听器接口和与之关联的两个session事件。分别是:
HttpSessionListener and HttpSessionEvent;
HttpSessionActivationListener and HttpSessionEvent.
HttpSessionAttributeListener and HttpSessionBindingEvent;
HttpSessionBindingListener and HttpSessionBindingEvent;
他们的继承关系是:
所有四个接口的父类是java.util.EventListener;
HttpSessionEvent扩展java.util.EventObject;
而HttpSessionBindingEvent又扩展了HttpSessionEvent。
-
HttpSessionListener
对于session的创建和取消感兴趣。需要在web.xml中登记。
共有两个方法:
void sessionCreated(HttpSessionEvent se);
void sessionDestroyed(HttpSessionEvent se);
使用它我们可以容易的创建一个类来对session计数。
也许我们会简单的考虑使用sessionDestroyed方法来在session结束后做一些清理工作。但是,请注意,当这个方法被调用的时候,session已经结束了,你不能从中提取到任何信息了。因此,我们要另辟蹊径。
一种通常采用的方法是使用HttpSessionBindingListener接口。在session创建时增加一个属性,而在session结束前最后一件事将这个属性删除,这样就会触发valueUnbound方法,所有对session的清理工作可以在这个方法中实现。 -
HttpSessionActivationListener
当session在分布式环境中跨JVM时,实现该接口的对象得到通知。共两个方法:
void sessionDidActivate(HttpSessionEvent se);
void sessionWillPassivate(HttpSessionEvent se); -
HttpSessionAttributeListener
当session中的属性被添加,更改,删除时得到通知。 -
HttpSessionBindingListener
当一个实现了HttpSessionBindingListener的类被加入到HttpSession中(或从中移出)时,会产生HttpBindingEvent事件,而这些事件会被它本身接收到。
本接口定义了两个方法:
void valueBound(HttpSessionBindingEvent e);
void valueUnbound(HttpSessionBindingEvent e);
valueUnbound的触发条件是以下三种情况:
a.执行session.invalidate()时。
b.session超时,自动销毁时。
c.执行session.setAttribute(“onlineUserListener”, “其他对象”);或session.removeAttribute(“onlineUserListener”);将listener从session中删除时。
每个servlet中用new创建实例,且仅对本实例向session中的加入(或移出)感兴趣。触发事件的对象仅仅是自己。
用服务端还是客户端session存储要看应用的实际情况的。一般来说不要求用户注册登录的公共服务系统采用cookie做客户端session存储,而有用户管理的系统则使用服务端存储,从而提供任意复杂的个性化服务
更多参考:https://blog.csdn.net/qq_39949109/article/details/82454060