1. 程式人生 > >SSM攔截器攔截ajax請求

SSM攔截器攔截ajax請求

攔截器攔截請求可以分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!

記錄錯誤.