简单demo,基于版本1.2
一.流程概述
主要是通过扩展ServletRequestWraper来实现的。
1.SessionRepositoryFilter.doFilterInternal
2.会创建SessionRepositoryRequestWrapper,这里面的getSession(boolean)会从外部存储创建session
---sessionRepository是RedisOperationsSessionRepository
---new redissession的时候会设置一些默认属性,比如间隔时间,lastAccessTime等
这些属性关联保存在MapSession中,创建完session会设置lastAccessTime
---过滤器链执行完后,有commitSession,会把session存储到外部存储,比如redis
try {
filterChain.doFilter(strategyRequest, strategyResponse);
}
finally {
wrappedRequest.commitSession();//这里实际会到RedisSession的saveDelta方法
}
这种方式即使我们在session里面放了一个list,然后往list里面添加元素,且未显示更新session的时候,session的过期时间依然会更新。如下。
List list = (List) session.getAttribute("list");
if (list == null) {
list = new ArrayList<>();
session.setAttribute("list", list);
}
list.add(new Date().toString()); //2
在2的时候session的时间会被更新
---当后续访问到来时,会通过sessionId获取session,同时更新lastAccessTime。
3.这个filter是在SpringHttpSessionConfiguration里面创建的,当然redis的实现也有对应的实现,RedisHttpSessionConfiguration,是上面class的子类
---如果想配置session的过期时间,那么需要在RedisHttpSessionConfiguration里面配置,有个参数maxInactiveIntervalInSeconds,默认1800秒。因为session的管理被放到了外部的存储,所以web.xml里面的关于session过期的配置不在生效。
简单配置
二.sessionListener support
1.在RedisOperationSessionRepository实现了MessageListener接口,redis有消息通知的时候,onMessage方法被调用,然后接下来把消息封装成各种事件
然后通过ApplicationEventPublisher和listener协作(观察者模式),
前者发送事件,后者监听处理。
2.SessionEventHttpSessionListenerAdapter实现了ApplicationListener,有新事件时,onApplicationEvent方法被调用。所以只需要在这个类里面添加我们所需要的处理逻辑的listener即可。
public SessionEventHttpSessionListenerAdapter(List listeners){
super();
this.listeners = listeners;
}
注:假如我们启动2个tomcat,那么当一个session过期时,那么我们的listener在这2个tomcat都会收到事件通知。会导致重复。如果需要基于session listener做一些事情,则需要注意这点。
Reference:
http://www.infoq.com/cn/articles/Next-Generation-Session-Management-with-Spring-Session?utm_campaign=rightbar_v2&utm_source=infoq&utm_medium=articles_link&utm_content=link_text