拦截器拦截请求可以分ajax请求/非ajax请求.
ajax请求在用户session过期之后,需要跳转到登录页面.
这个时候就需要在拦截器里判断我们的请求是否是ajax请求.
但是不能直接的跳转页面,只能通用response返回响应.

我们有两种方式:
1.在ajax里获取响应信息作出执行请求或者session过期跳转到登录页面的操作.
2.修改jQuery源码,这个是比较推荐的做法,要是每次的ajax请求都判断一次,就太扯淡了,比较麻烦,所以就修改源码吧.

1.配置拦截器,list里配置需要放行的请求URL

spring-mvc.xml

<!-- 登录拦截器 -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <!-- 需要排除拦截的请求 -->
            <bean id="LoginInterceptor" class="com.ys.interceptors.LoginInterceptor">
                <property name="interceptorList">
                    <list>
                        <value>/user/checkLogin</value>
                        <value>/user/login.html</value>
                    </list>
                </property>     
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

2.编写登录拦截器实现HandlerInterceptor

package com.ys.interceptors;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.ys.entity.User;
import com.ys.listeners.UserSessionListener;

/** 
*@Title LoginInterceptor.java 
*@description:  登录拦截
*@author lihaichao
*@time 创建时间:2018年5月22日 上午11:49:37 
**/
public class LoginInterceptor implements HandlerInterceptor{

    private static final Logger logger = Logger.getLogger(LoginInterceptor.class);

    /**
     * 获取拦截器放行路径
     */
    private List<String> interceptorList;
    public List<String> getInterceptorList() {
        return interceptorList;
    }
    public void setInterceptorList(List<String> interceptorList) {
        this.interceptorList = interceptorList;
    }

    /**
     *  该方法将在请求处理之前进行调用 判断URL是否放行
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String requestName = request.getServletPath();
        logger.debug("拦截器启动 拦截路径为 :"+requestName);
        String requestType = request.getHeader("X-Requested-With");
        //放行路径 与 请求路径对比   存在则放行
        if(interceptorList.contains(requestName)){
            return true;
        }
        User user = (User)request.getSession().getAttribute("user");
        if(user != null && UserSessionListener.isContainsKey(user.getId())){
            return true;
        }else{
            if ("XMLHttpRequest".equals(requestType)) {
                response.getWriter().write("IsAjax");
            } else {
                request.getRequestDispatcher("/WEB-INF/view/login/login.jsp").forward(request, response);
            }
            return false;
        }
    }


    /**
     * 该方法将在整个请求结束之前执行
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        logger.debug("处理请求:"+request.getRequestURI());
    }


    /**
     * 该方法将在整个请求结束之后执行
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        logger.debug("请求完成:"+request.getRequestURI());
    }

}

在拦截器中添加了是否ajax请求的判断

if ("XMLHttpRequest".equals(requestType)) {
                response.getWriter().write("IsAjax");
            } else {
                request.getRequestDispatcher("/WEB-INF/view/login/login.jsp").forward(request, response);
            }

3.接着就是修改jQuery源码,我这里是jquery-2.1.1.min.js
不同版本的jQuery应该差别不大,对比着修改一下就好了.

找到下边的方法

/*function x(a, b, f, h) {
                var j, r, s, u, w, x = b;
                2 !== t && (t = 2, g && clearTimeout(g), c = void 0, e = h || "", v.readyState = a > 0 ? 4 : 0, j = a >= 200 && 300 > a || 304 === a, 
                f && (u = uc(k, v, f)), u = vc(k, u, v, j), j ? (k.ifModified && (w = v.getResponseHeader("Last-Modified"), 
                w && (n.lastModified[d] = w), w = v.getResponseHeader("etag"), w && (n.etag[d] = w)), 
                204 === a || "HEAD" === k.type ? x = "nocontent": 304 === a ? x = "notmodified": (x = u.state, r = u.data, s = u.error, j = !s)) : (s = x, (a || !x) && (x = "error", 0 > a && (a = 0))), v.status = a, v.statusText = (b || x) + "", j ? o.resolveWith(l, [r, x, v]) : o.rejectWith(l, [v, x, s]), v.statusCode(q), q = void 0, i && m.trigger(j ? "ajaxSuccess": "ajaxError", [v, k, j ? r: s]), p.fireWith(l, [v, x]), i && (m.trigger("ajaxComplete", [v, k]), --n.active || n.event.trigger("ajaxStop")))
            }*/

替换为

function x( a, b, f, h ) {
    var j, r, s, u, w,x = b;
    if ( t === 2 ) { return; }
    t = 2;
    if ( g ) { clearTimeout( g ); }
    c = void 0;
    e = h || "";
    v.readyState = a > 0 ? 4 : 0;
    j = a >= 200 && a < 300 || a === 304;
    if ( f ) { 
        u = uc(k, v, f);
    }
    u = vc(k, u, v, j);
    if ( j ) {
        if ( k.ifModified ) {
            w = v.getResponseHeader("Last-Modified");
            if ( w ) {
                n.lastModified[d] = w;
            }
            w = v.getResponseHeader("etag");
            if ( w ) {
                n.etag[d] = w;
            }
        }

        if ( 204 === a || "HEAD" === k.type ) {
            x = "nocontent";
        } else if ( a === 304 ) {
            x = "notmodified";
        } else {

            x = u.state, r = u.data, s = u.error, j = !s
             //解决ajax拦截问题
                  var result = f.text;
                  if(result.indexOf("IsAjax")>=0){// 拦截登陆
                      window.parent.location.href=getPath+"user/login.html";
                      return;
                  }
        }
    } else {
        s = x;
        if ( a || !x ) {
            x = "error";
            if ( a < 0 ) {
                a = 0;
            }
        }
    }
    v.status = a;
    v.statusText = (b || x) + "";
    if ( j ) {
        o.resolveWith(l, [r, x, v]);
    } else {
        o.rejectWith(l, [v, x, s]);
    }
    // Status-dependent callbacks
    v.statusCode( q );
    q = void 0;

    if ( i ) {
        m.trigger( j ? "ajaxSuccess": "ajaxError",
                [v, k, j ? r: s]);
    }
    // Complete
    p.fireWith(l, [v, x]);

    if ( i ) {
        m.trigger("ajaxComplete", [v, k]);
        // Handle the global AJAX counter
        if ( !( --n.active ) ) {
            n.event.trigger("ajaxStop");
        }
    }
}

主要的地方在这里

if ( 204 === a || "HEAD" === k.type ) {
    x = "nocontent";
} else if ( a === 304 ) {
    x = "notmodified";
} else {

x = u.state, r = u.data, s = u.error, j = !s
//解决ajax拦截问题
             var result = f.text;
             if(result.indexOf("IsAjax")>=0){// 拦截登陆
                 window.parent.location.href=getPath+"user/login.html";
                 return;
             }
}

其中 var result = f.text ; f对应的是responses 获取的就是我们请求的响应数据信息.

在我们的拦截器中 response.getWriter().write(“IsAjax”); 返回了信息.

所以我们直接判断请求响应信息是否有”IsAjax” 就可以了,如果有的话就跳转到登录页面.

在我们请求的时候,如果session过期的话 ,那么ajax就会走error:function(e){alert(e.status);} ,这时获取ajax的请求状态就会是200 . 状态200 代表执行成功 , 用户登录状态都过期了怎么可能会成功呢 .所以让用户重新登录就好了. 这时我们再执行window.parent.location.href = “你的登录页面”; ajax就会在你的session过期而返回状态是200时直接跳转到登录页.

over!

记录错误.