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!
記錄錯誤.