一 问题概述
最近在练习redis的相关使用,就考虑在自己写的一个课程大作业(生鲜超市),用redis缓存原来应该放在session的数据,比如用户的订单和用户的地址信息。
在删除缓存,我的考虑是使用session的监听器,在session被销毁的时候,把redis中的缓存删除掉。但是由于我的Redis缓存类是被spring管理的,引出这么个问题
new 对象和spring 管理bean是会有冲突的。
二 详细情况
我开始写的代码是这样的:
public class SessionListener implements HttpSessionListener { @Override public void sessionCreated(HttpSessionEvent httpSessionEvent) { } @Override public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("51615616"); HttpSession session = httpSessionEvent.getSession(); User user = (User) session.getAttribute("user"); System.out.println("001"+user); ShardedJedis jedis = new CacheMapper().getJedis(); //CacheMapper 是我自己简单封装的一个spring 管理的类 if(user!=null){ jedis.del("USER_ITEM:" + user.getId()); // USER_ITEM:user.getId()是存储用户相关信息的键 } jedis.close(); } }
查看日志发现:
然后百度 ,就得到的结论 :spring 管理的bean new无法获得实例对象(单例模式下,多例模式我没测试,估计也是的)
然后我把代码改成了这样
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("51615616"); HttpSession session = httpSessionEvent.getSession(); User user = (User) session.getAttribute("user"); System.out.println("001"+user); CacheMapper cacheMapper = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext()).getBean(CacheMapper.class); ShardedJedis jedis = cacheMapper.getJedis(); if(user!=null){ jedis.del("USER_ITEM:" + user.getId()); } System.out.println("success del"); jedis.close(); }
这里 还遇到一个问题,要保证spring的配置文件先执行,也就是我们一般使用spring 的监听器加载spring的配置文件,要把spring的监听器 写到自定义监听器前面。这里还遇到一个问题,我还用到了spring mvc的框架,我为了省事,扫描器全部配在了spring mvc的配置文件中。第一遍测试发现
No qualifying bean of type 异常
我先是拿了一个spring使用非注解方式管理的类做测试,发现可以拿到。于是就想到可能是spring mvc的配置文件,在监听器加载之后加载。把扫描器配置到spring 的配置文件中 顺利解决这个小问题。
<context:component-scan base-package="controller"/>
<context:component-scan base-package="service"/>
<context:component-scan base-package="dao"/>
<context:component-scan base-package="common"/>
三 另外
session失效的几类情况
1. 服务器异常关闭 正常关闭session不会失效,会被持久化
2. 超出时间没于服务器交互 可以通过配置文件设置 默认是30分钟 貌似
<session-config>
<session-timeout>
15
</session-timeout>
</session-config>
3. 手动销毁 ,本次测试就是写了个手动销毁的接口
很简单调用 以下方法就可以了
session.invalidate();