先看看攔截器都作些什麼:html
1、日誌記錄:記錄請求信息的日誌,以便進行信息監控、信息統計、計算PV(PageView)等。java
2、權限檢查:如登陸檢測,進入處理器檢測檢測是否登陸,若是沒有直接返回到登陸頁面;web
3、性能監控:有時候系統在某段時間莫名其妙的慢,能夠經過攔截器在進入處理器以前記錄開始時間,在處理完後記錄結束時間,從而獲得該請求的處理時間(若是有反向代理,如apache能夠自動記錄);spring
4、通用行爲:讀取cookie獲得用戶信息並將用戶對象放入請求,從而方便後續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都須要的便可使用攔截器實現。apache
5、OpenSessionInView:如Hibernate,在進入處理器打開Session,在完成後關閉Session。編程
本質也是AOP(面向切面編程),也就是說符合橫切關注點的全部功能均可以放入攔截器實現。設計模式
Spring爲咱們提供了:cookie
org.springframework.web.servlet.HandlerInterceptor接口,app
org.springframework.web.servlet.handler.HandlerInterceptorAdapter適配器,jsp
實現這個接口或繼承此類,能夠很是方便的實現本身的攔截器。
從源碼中能夠看到接口和類的關係:
從關係中能夠看到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>