• js--Ajax的小知识(二):处理ajax的session过期的请求


    问题的产生:  

      现如今Ajax在Web项目中应用广泛,几乎可以说无处不在。

      有时会碰到这样个问题:当Ajax请求遇到Session超时,应该怎么办?

      显而易见,传统的页面跳转在此已经不适用,因为Ajax请求是XMLHTTPRequest对象发起的而不是浏览器,在验证失败后的页面跳转无法反应到浏览器中,因为服务器返回(或输出)的信息被JavaScript(XMLHTTPRequest对象)接到了。

      那么应该怎么处理这种情况呢?

    问题的解决之法:

      既然服务器返回的消息被XMLHTTPRequest对象接收,而XMLHTTPRequest对象又是在JavaScript的掌控之中,那么我们是否可以利用JavaScript来完成页面跳转呢?

      当然可以,而且很容易实现!但有一点,我们需要判断一下HTTP请求是否为Ajax请求(因为AJAX请求和普通的请求需要分开处理),这又如何判断呢?其实Ajax请求和普通的HTTP请求是不同的,这体现在HTTP请求的头信息中,如下所示:

    上面两张图片是用火狐的Firebug截取的,前者为Ajax请求的请求头信息;后者是普通的HTTP请求头信息。注意第一图片被红框圈起来的部分,这就是Ajax请求与普通请求不同的地方,AJAX请求头中带有X-Requested-With信息,其值为XMLHttpRequest,这正是我们可以利用的地方。

    Javascript代码

    $.ajaxSetup方法是来设置AJAX请求默认选项的,我们可以认为是全局的选项设置,因此可以将这段代码提到外部JS文件中,在需要的页面引用。

    /**
     * 设置未来(全局)的AJAX请求默认选项
     * 主要设置了AJAX请求遇到Session过期的情况
     */
    $.ajaxSetup({
        type: 'POST',
        complete: function(xhr,status) {
            var sessionStatus = xhr.getResponseHeader('sessionstatus');
            if(sessionStatus == 'timeout') {
                var top = getTopWinow();
                var yes = confirm('由于您长时间没有操作, session已过期, 请重新登录.');
                if (yes) {
                    top.location.href = '/skynk/index.html';            
                }
            }
        }
    });
    
    /**
     * 在页面中任何嵌套层次的窗口中获取顶层窗口
     * @return 当前页面的顶层窗口对象
     */
    function getTopWinow(){
        var p = window;
        while(p != p.parent){
            p = p.parent;
        }
        return p;
    }

    拦截器的部分代码:

    import java.io.IOException;
    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;
    /**
     * 登录过滤器
     *  拥有Session是否失效和用户是否登录2个条件判断
     *  如果是ajax请求则设置session超时
     * @author Merlin.Ma
     *
     */
    public class LoginFilter implements Filter{
      private String redirectUrl = "/login.html";
      private String sessionKey = "userName";
      @Override
      public void destroy() {
      }
      @Override
      public void doFilter(ServletRequest request, ServletResponse response,
          FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rep = (HttpServletResponse) response;
        HttpSession session = req.getSession();
        if( session == null || session.getAttribute(sessionKey) == null){
          //如果判断是 AJAX 请求,直接设置为session超时
          if( req.getHeader("x-requested-with") != null && req.getHeader("x-requested-with").equals("XMLHttpRequest") ) {
            rep.setHeader("sessionstatus", "timeout"); 
          } else {
            rep.sendRedirect( req.getContextPath() + redirectUrl);
          }
        }else {
          chain.doFilter(request, response);
        }   
      }
      @Override
      public void init(FilterConfig filterConfig) throws ServletException {
        String url = filterConfig.getInitParameter("redirectUrl");
        String key = filterConfig.getInitParameter("sessionKey");
        redirectUrl = url == null? redirectUrl:url;
        sessionKey = key == null ? sessionKey : key ;
      }
    }

    由上面代码可以看出,当Session验证失败(即Session超时)后,我们通过HttpServletRequest取得请求头信息X-Requested-With的值,如果不为空且等于XMLHttpRequest,那么就说明此次请求是Ajax请求,我们作出的反应就是向响应中添加一条头信息(自定义)并且使响应对象HttpServletResponse返回服务器错误信息(518状态是自己随便定义的);这些信息都会被JavaScript接收,那么下面的工作就要将由JavaScript代码了。

  • 相关阅读:
    jvm 指令 invokedynamic
    go switch
    JVM指令 bytecode invokespecial
    babel插件开发
    go 循环依赖 循环引用 最佳实践
    go module 使用入门
    搞懂gopath golang go go项目结构
    SQL Server 工具
    SQLServer Management Studio登录框中的“服务器名”填写
    win2008下安装SQL SERVER 2005出现IIS功能要求 警告解决方案
  • 原文地址:https://www.cnblogs.com/renxiaoren/p/5411657.html
Copyright © 2020-2023  润新知