当session失效时,我们可以通过filter来拦截并重定向到登陆页面,可是请求如果是ajax请求,页面并不会重定向,这是因为ajax返回的是数据,无法返回页面。
ajax异步请求不同于其他请求,其在请求头里包含有X-Requested-With:XMLHttpRequest,看下面两张图的区别。
我们可以在filter中通过它来判断一个请求是不是异步的,如果是,我们可以返回一个sessionstatus,在页面上通过判断sessionstatus的值来判断session是否失效。
第一张是普通请求:
第二张是ajax的
可是,如果每个ajax都这样写,工作量也是很大的。
由于我使用的是Extjs,而Ext的ajax是单例的,这样我们可以单独写一个js文件,在里边写入session超时验证的代码,其他页面只要引入这个js就可以了。
下面看代码,首先是filter:
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class SessionFilter implements Filter { public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; HttpSession session = httpRequest.getSession(); String url = httpRequest.getRequestURI(); String path = url.substring(url.lastIndexOf("/")); if (check(path)&& session.getAttribute("user") == null) { // 拦截ajax if (httpRequest.getHeader("x-requested-with") != null && httpRequest.getHeader("x-requested-with") .equalsIgnoreCase("XMLHttpRequest")) { httpResponse.addHeader("sessionstatus", "timeout"); chain.doFilter(request, response);// 不可少,否则请求会出错 }else { String str = "<script language=‘javascript‘>alert(‘会话过期,请重新登录‘);" + "window.top.location.href=index.jsp‘" + "‘;</script>"; response.setContentType("text/html;charset=UTF-8");// 解决中文乱码 try { PrintWriter writer = response.getWriter(); writer.write(str); writer.flush(); writer.close(); } catch (Exception e) { e.printStackTrace(); } } } else { chain.doFilter(request, response); } } /** * 判断该路径是否要拦截:true【是】 * @param path * @return */ public boolean check(String path){ if(path.indexOf("login") != -1||path.indexOf("logout") != -1) //不拦截登入登出 return false; return true; } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
然后是web.xml中的配置:
<filter> <filter-name>sessionFilter</filter-name> <filter-class>com.web.helper.session.SessionFilter</filter-class> </filter> <filter-mapping> <filter-name>sessionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
下面是ajax超时验证的代码[ajax_timeout.js],页面引入该js后,每次ajax请求都会调用这段代码
// ajax回调函数处理session过期 Ext.Ajax.on(‘requestcomplete‘,checkUserSessionStatus, this); function checkUserSessionStatus(conn,response,options){ var status = response.getResponseHeader("sessionstatus"); //Ext重新封装了response对象 if(status=="timeout"){ window.location.href="index.jsp"; } }
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
后来发现如果代码中还是用了form的submit提交进行上传,这个submit的返回值接收不到,这是因为ajax和submit的返回值不同:
我们要做不同的处理:
// ajax回调函数处理session过期 Ext.Ajax.on(‘requestcomplete‘,checkUserSessionStatus, this); function checkUserSessionStatus(conn,response,options){ console.info(response); console.info(response.status); if(response.status==undefined){ //解决表单提交不响应的问题 }else{ var status = response.getResponseHeader("sessionstatus"); //Ext重新封装了response对象 if(status=="timeout"){ window.location.href="index.jsp"; } } }