權限檢查:如是否已經登陸,或則對某些數據具備增刪改查等權限;html
日誌記錄:能夠記錄請求信息的日誌,以便進行信息監控,信息統計等;java
性能監控:慢日誌等。web
public interface HandlerInterceptor { /** * 預處理回調方法,實現處理器的預處理(如檢查登錄),第三個參數爲響應的處理器,自定義Controller * 返回值:true表示繼續流程(如調用下一個攔截器或處理器);false表示流程中斷(如登陸檢查失敗),不會繼續調用其餘的攔截器或處理器,此時咱們須要經過response來產生響應; */ boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /** * 後處理回調方法,實現處理器的後處理(但在渲染視圖以前),此時咱們能夠經過modelAndView(模型和視圖對象)對模型數據進行處理或對視圖進行處理,modelAndView也可能爲null。 */ void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception; /** * 整個請求處理完畢回調方法,即在視圖渲染完畢時回調,如性能監控中咱們能夠在此記錄結束時間並輸出消耗時間,還能夠進行一些資源清理,相似於try-catch-finally中的finally,但僅調用處理器執行鏈中 */ void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception; }
若是隻須要實現三個回調方法中的某些方法,能夠繼承該抽象類,該抽象類至關於對HandlerIntercepto進行簡單實現。如記錄日誌,須要在程序跑完後,記錄相應的增刪改查,只需實現afterConcurrentHandlingStarted()方法。spring
注:該攔截器中多了一個afterConcurrentHandlingStarted()方法,該方法用於處理異步請求,當Controller中有異步請求方法的時候會觸發該方法時,異步請求先支持preHandle、而後執行afterConcurrentHandlingStarted。異步線程完成以後執行preHandle、postHandle、afterCompletion。session
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor { /** * 默認是true */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } /** * This implementation is empty. */ @Override public void postHandle( HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } /** * This implementation is empty. */ @Override public void afterCompletion( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } /** * 不是HandlerInterceptor的接口實現,是AsyncHandlerInterceptor的,AsyncHandlerInterceptor實現了HandlerInterceptor */ @Override public void afterConcurrentHandlingStarted( HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { } }
1.1攔截器執行順序按照Spring配置文件中定義的順序執行;mvc
1.2首先按照執行順序執行全部攔截器的preHandle()方法【用於預處理等】,若是遇到返回值是false,則不會執行還未執行的攔截器,而是直接倒序執行afterCompletion()方法,若是爲true,則依次執行剩下的攔截器;app
1.3若是全部攔截器的preHandle()方法返回值都爲true,則執行相應的控制層接口(controller),若是在該接口中有異常拋出,則和preHandle()方法返回false同樣,不會執行postHandle(),而是直接倒序執行afterCompletion()方法;異步
1.4若是接口(controller)中業務邏輯執行完成(頁面還未渲染數據),會倒序執行postHandle()方法,渲染完數據後,而後倒序執行afterCompletton()方法。ide
package com.swpu.o2o.interceptor.shopadmin; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.swpu.o2o.entity.PersonInfo; /** * 管理系統攔截器 * @author ASUS * */ public class ShopLoginInterceptor extends HandlerInterceptorAdapter{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //從session中取出用戶信息 Object userObj=request.getSession().getAttribute("user"); if(userObj!=null){ //若用戶信息不爲空則將session裏的用戶信息轉換成PersonInfos實體類對象 PersonInfo user=(PersonInfo)userObj; if(user!=null&&user.getUserId()!=null&&user.getUserId()>0&&user.getEnableStatus()==1){ //若經過驗證則返回true,攔截器返回true,控制層業務執行 return true; } } //若不滿驗證,則直接跳轉到登陸界面 PrintWriter out=response.getWriter(); out.println("<html>"); out.println("<script>"); out.println("window.open ('" + request.getContextPath() + "/local/login?usertype=2','_self')"); out.println("</script>"); out.println("<html>"); return false; } }
package com.swpu.o2o.interceptor.shopadmin; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.swpu.o2o.entity.Shop; public class ShopPermissionInterceptor extends HandlerInterceptorAdapter{ /** * 在控制層執行業務前進行用戶操做權限攔截 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //從session獲取當前選擇的店鋪 Shop currentShop = (Shop) request.getSession().getAttribute( "currentShop"); @SuppressWarnings("unchecked") //從session中獲取當前用戶可操做的d店鋪列表 List<Shop> shopList = (List<Shop>) request.getSession().getAttribute( "shopList"); //非空判斷 if (currentShop != null && shopList != null) { //遍歷可操做的店鋪列表 for (Shop shop : shopList) { //若是當前店鋪在可操做的列表則返回true,進行接下來操做 if (shop.getShopId() == currentShop.getShopId()) { return true; } } } //不知足驗證,返回false return false; } }
<!-- 5.權限攔截器 --> <mvc:interceptors> <!-- 校驗是否登陸了該管理系統的攔截器 --> <mvc:interceptor> <!-- 定義攔截的路由,shopadmin包下的全部Controller --> <mvc:mapping path="/shopadmin/**" /> <!-- 攔截方法 --> <bean class="com.swpu.o2o.interceptor.shopadmin.ShopLoginInterceptor" id="ShopInterceptor" /> </mvc:interceptor> <!-- 校驗是否對該店鋪有操做權限的攔截器 --> <mvc:interceptor> <!-- 須要攔截的接口 --> <mvc:mapping path="/shopadmin/**" /> <!-- shoplist page --> <!-- 排除該包下的某些接口不攔截 --> <mvc:exclude-mapping path="/shopadmin/shoplist" /> <mvc:exclude-mapping path="/shopadmin/getshoplist" /> <!-- shopmanage page --> <mvc:exclude-mapping path="/shopadmin/shopmanagement" /> <mvc:exclude-mapping path="/shopadmin/getshopmanagementinfo" /> <!-- shopregister page --> <mvc:exclude-mapping path="/shopadmin/getshopinitinfo" /> <mvc:exclude-mapping path="/shopadmin/shopoperation" /> <mvc:exclude-mapping path="/shop/registershop" /> <bean class="com.swpu.o2o.interceptor.shopadmin.ShopPermissionInterceptor" id="ShopPermissionInterceptor" /> </mvc:interceptor> </mvc:interceptors>