先看看攔截器都做些什麼:
1、日誌記錄:記錄請求信息的日誌,以便進行信息監控、信息統計、計算PV(PageView)等。
2、權限檢查:如登錄檢測,進入處理器檢測檢測是否登錄,如果沒有直接返回到登錄頁面;
3、性能監控:有時候系統在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完後記錄結束時間,從而得到該請求的處理時間(如果有反向代理,如apache可以自動記錄);
4、通用行爲:讀取cookie得到用戶信息並將用戶對象放入請求,從而方便後續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都需要的即可使用攔截器實現。
5、OpenSessionInView:如Hibernate,在進入處理器打開Session,在完成後關閉Session。
本質也是AOP(面向切面編程),也就是說符合橫切關注點的所有功能都可以放入攔截器實現。
Spring爲我們提供了:
org.springframework.web.servlet.HandlerInterceptor接口,
org.springframework.web.servlet.handler.HandlerInterceptorAdapter適配器,
實現這個接口或繼承此類,可以非常方便的實現自己的攔截器。
從源碼中可以看到接口和類的關係:
從關係中可以看到AsyncHandlerInterceptor繼承自HandlerInterceptor,而HandlerInterceptorAdapter又實現AsyncHandlerInterceptor,其實這是一種設計模式,叫適配器模式(不知道的可以點擊查看適配器模式)。
如若實現HandlerInterceptor接口則三個方法都必須實現,如果繼承HandlerInterceptorAdapter適配,則可以只實現我們需要的回調方法。
從接口HandlerInterceptor中可以看到攔截器有三個回調方法,我們來看看這3個都有什麼作用:
preHandle:預處理回調方法,實現處理器的預處理(如登錄檢查);方法返回值爲boolean,返回true標示流程繼續;返回false標示流程中斷,比如登錄失 敗,這樣就不會再調用其它攔截器,我們可以通過response來產生響應。
postHandle:後處理回調方法,實現處理器的後處理,此方法在生成視圖之前執行;在這個方法中我們可以修改modelAndView,通過modelAndView對模型數據進行處理或對視圖進行處理。
afterCompletion:最後執行,可用於釋放資源。可以根據ex是否爲null判斷是否發生了異常,進行日誌記錄。
參數中的Object handler是下一個攔截器。
自定義攔截器:
下面例子,用戶登錄之後,通過攔截器對系統中的資源進行訪問攔截,同時對於相關的資源不攔截
public class LoginInterceptor extends HandlerInterceptorAdapter {
private static final String[] IGNORE_URI = {"/login.jsp", "/Login/","backui/","frontui/"};
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean flag = false;
String url = request.getRequestURL().toString();
System.out.println(">>>: " + url);
for (String s : IGNORE_URI) {
if (url.contains(s)) {
flag = true;
break;
}
}
if (!flag) {
T_supplier_user user = LoginController.getLoginUser(request);
if (user != null) flag = true;
}
return flag; //前面介紹返回false則會中斷流程
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
super.postHandle(request, response, handler, modelAndView);
}
}
<interceptor>
<mapping path="/**"/>
<bean id="loginInterceptor" class="net.web.interceptor.LoginInterceptor"/>
<interceptor>