最近因为业务需要,需要给系web系统加了个session过期的监听功能,下面是代码:
web.xml配置:
<session-config>
<session-timeout>10</session-timeout>
</session-config>
listener代码:
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
HttpSession session = arg0.getSession();
UserTab user = (UserTab)session.getAttribute("USER");
if(user!=null){
自己需要做的其他操作
}
}
}
好啦,到这就完成了,大功告成,启动猫,在10分钟后死活不见触发sessionDestoryed的方法,坏了,我一个想法就是肯定和web里的什么东东冲突了,然后在web.xml发现dwr的配置,
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>
org.directwebremoting.servlet.DwrServlet
</servlet-class>
<init-param>
<init-param>
<param-name>activeReverseAjaxEnabled</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
于是先把dwr的配置注释掉,走你猫,10分钟后,期盼已久的sessionDestoryed方法终于有了动静,好像现在基本可以确定是和dwr有关系了。以前用过dwr也看过源码,记着dwr的底层也是依赖servlet地,赶紧download一份源码看看,果然就是,于是在dwr的配置释放出来,在里面加上scriptSessionTimeout这个参数,也设成10分钟,我想这下应该没有问题了吧,满心欢喜的启动猫,10分钟后,我去,再次崩溃,还是不触发sessionDestoryed方法,各种怀疑人生,这次又是哪里出现了问题,于是怀疑到init-param的这个初始化参数activeReverseAjaxEnabled,去掉参数后,能正常进入dessiondestoryed,但是猫启动的时候我发现一个错误:Polling and Comet are disabled. To enable them set the init-param activeReverseAjaxEnabled to true,再试dwr得消息推送,我去也用不成了,这下进退两难了,去掉activeReverseAjaxEnabled参数,dwr用不成了,不去掉sessionlistener又不触发,我勒个去,咋整啊,就算activeReverseAjaxEnabled参数不影响,dwr的推送间隔时间也远远小于session的失效时间,这样还是不会使session失效,除非是dwr的推送间隔时间大于session的失效时间才行,这样又和业务违背,最后在自定义的拦截器中添加了一段时间拦截并计算的功能,由于session彼此独立,只需要记录每个用户第一个访问系统的时候就行了,代码如下:
//记录session每次活动的最后时间
request.getSession().setAttribute("cross_time", System.currentTimeMillis());
然后在filter中拦截每次访问的action地址,取出配置文件中的配置的过期时间,再取系统当前时间减掉当前用户第一次登陆时记录的时间,比较一下如果大于配置的过期时间,就提示过期,然后跳转到登录页面,同时invalidate当前session,清除其中所以得变量,代码如下:
*****sessiontime.properties为配置session过期时间的properties文件
FileInputStream fis=new FileInputStream(this.getClass().getClassLoader().getResource("").getPath()+"/sessiontime.properties");
Properties pro= new Properties();
pro.load(fis);
String session_time_out =pro.getProperty("session_time");
if(StringHelp.isNotNull(session_time_out)){
long cross_time = Long.parseLong(request.getSession().getAttribute("login_time").toString());
if(((System.currentTimeMillis()-cross_time)/1000)>(Long.parseLong(session_time_out)*60)){
request.getSession().invalidate();
request.getSession().setAttribute("msgStr","会话过期,请重新登录");
response.setContentType("text/html;charset=UTF-8");
PrintWriter writer = response.getWriter();
writer.write("<script type='text/javascript'>window.top.location.href='"+contextPath+"/index.jsp;'</script>");
writer.flush();
writer.close();
return;
}
}
经测试,符合需求要求的功能,算是解决了这个问题,但我总觉得不完美,如果哪位童鞋有更好的办法,请留言告知,不胜感激,相互学习一下。