SpringMVC 中的Interceptor 攔截器也是相當重要和相當有用的,它的主要作用是攔截用戶的請求並進行相應的處理。比如通過它來進行權限驗證,或者是來判斷用戶是否登陸等。
一. 使用場景
1、日志記錄:記錄請求信息的日志,以便進行信息監控、信息統計、計算PV(Page View)等。
2、權限檢查:如登錄檢測,進入處理器檢測檢測是否登錄,如果沒有直接返回到登錄頁面;
3、性能監控:有時候系統在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完后記錄結束時間,從而得到該請求的處理時間(如果有反 向代理,如apache可以自動記錄);
4、通用行為:讀取cookie得到用戶信息並將用戶對象放入請求,從而方便后續流程使用,還有如提取Locale、Theme信息等,只要是多個處理器都需要的即可使用攔截器實 現。
5、OpenSessionInView:如Hibernate,在進入處理器打開Session,在完成后關閉Session。
本質也是AOP(面向切面編程),也就是說符合橫切關注點的所有功能都可以放入攔截器實現。
二. 攔截接口
public interface HandlerInterceptor { boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
preHandle:預處理回調方法,實現處理器的預處理(如登錄檢查),第三個參數為響應的處理器;
返回值:true表示繼續流程(如調用下一個攔截器或處理器);
false表示流程中斷(如登錄檢查失敗),不會繼續調用其他的攔截器或處理器,此時我們需要通過response來產生響應;
postHandle:后處理回調方法,實現處理器的后處理(但在渲染視圖之前),此時我們可以通過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行 處理,modelAndView也可能為null。
afterCompletion:整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中我們可以在此記錄結束時間並輸出消耗時間,還可以進行一些資源清理,類似 於try-catch-finally中的finally,但僅調用處理器執行鏈中preHandle返回true的攔截器的afterCompletion。
三. 以下通過一個用戶是否登錄實例。
1. 在beans.xml中加入
<!-- 自定義攔截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.haut.phonemanage.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
2、LoginInterceptor
public class LoginInterceptor implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) throws Exception { } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView view) throws Exception { } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { final String ENC = "UTF-8"; String fullPath = request.getRequestURI(); String queryString = request.getQueryString(); String contextPath = request.getContextPath(); String controllerPath = fullPath.replace(contextPath, ""); HttpSession session = request.getSession(); Object account = session.getAttribute("account"); if(queryString != null && !queryString.trim().equals("")) { queryString = "?" + queryString; } if(!controllerPath.startsWith("/passport") && account == null) { response.sendRedirect(contextPath + "/passport?path=" + URLEncoder.encode(contextPath + controllerPath + queryString, ENC)); } return true; } }
總結:很明顯攔截器也是aop面向切面編程的一種用法,那么它也就是使用代理模式了。
