處理器攔截器相似於servlet開發中的filter,用於對處理器進行預處理和後處理。前端
定義攔截器,實現HandlerInterceptor這個接口java
接口的實現須要導入包import org.springframework.web.servlet.HandlerInterceptor;web
這個包不能導錯,否則不能自動添加方法。spring
代碼:瀏覽器
package com.jch.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class HandlerInterceptor1 implements HandlerInterceptor{ /** * 進入handler方法以前執行 * 用於身份認證,身份校驗 * 好比身份認證,若是認證不經過表示當前用戶沒有登陸,須要此方法攔截不在向下執行 */ @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { // TODO Auto-generated method stub return false; } /** * 進入handler以後,返回modelandview以前執行 * 應用場景從modelandview出發,將共用的模型數據(好比菜單導航)在這裏傳到視圖,也能夠在這裏統一制定視圖 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub } /** * 執行handler完成執行此方法 * 應用場景:統一異常處理,統一日誌處理 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub } }
SpringMVC攔截器針對HandlerMapping進行攔截器設置session
若是在某個HandlerMapping中配置攔截,通過該HandlerMapping映射成功的handler最終使用該攔截器。mvc
通常不推薦使用,配置過於麻煩app
SpringMVC配置相似全局的攔截器,SpringMVC框架將配置的相似全局的攔截器注入到每個HandlerMapping中框架
測試多個攔截器各個方法的執行時機jsp
代碼;
package com.jch.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class HandlerInterceptor1 implements HandlerInterceptor{ /** * 進入handler方法以前執行 * 用於身份認證,身份校驗 * 好比身份認證,若是認證不經過表示當前用戶沒有登陸,須要此方法攔截不在向下執行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("這是第1個攔截器,preHandle方法"); return false; } /** * 進入handler以後,返回modelandview以前執行 * 應用場景從modelandview出發,將共用的模型數據(好比菜單導航)在這裏傳到視圖,也能夠在這裏統一制定視圖 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub System.out.println("這是第1個攔截器,postHandle方法"); } /** * 執行handler完成執行此方法 * 應用場景:統一異常處理,統一日誌處理 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub System.out.println("這是第1個攔截器, afterCompletion方法"); } }
將兩個return都改成true
在瀏覽器中隨意訪問一個路由看效果:
這是第1個攔截器,preHandle方法
這是第2個攔截器,preHandle方法
這是第2個攔截器,postHandle方法
這是第1個攔截器,postHandle方法
這是第2個攔截器,afterCompletion方法
這是第1個攔截器, afterCompletion方法
總結:
preHandle方法按順序執行
postHandle方法和afterCompletion方法按攔截器配置的逆向順序執行
結果:
這是第1個攔截器,preHandle方法
這是第2個攔截器,preHandle方法
這是第1個攔截器, afterCompletion方法
總結:
攔截器1放行,攔截器的preHandle方法纔會執行
攔截器2的preHandle方法不放行,攔截器2的postHandle方法和afterCompletion方法不會執行。
只要有一個攔截器攔截不放行postHandle方法都不會執行
結果:
這是第1個攔截器,preHandle方法
總結:
攔截器1 preHandle方法不放行,postHandle方法和afterCompletion方法都不會執行
攔截器1 preHandle方法不放行,攔截器2不執行。
根據測試結果,對攔截器應用。
好比:
統一日誌處理攔截器,須要該攔截器preHandler必定要放行,且將它放在攔截器連接中的第一個位置。
登陸認證的攔截器,放在攔截器連接中的第一個位置
權限校驗攔截器,放在登陸校驗攔截器以後。(由於登陸經過後才校驗權限)
一、 用戶請求URL
二、 攔截器進行校驗
若是請求的URL是公開地址(無需登陸就能訪問的URL),讓放行。、
若是用戶session不存在跳轉到登陸界面
若是用戶session存在,繼續操做
package com.jch.controller; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { // 登陸 @RequestMapping("login.jch") public String login(HttpSession session , String username , String password) { // 調用service進行用戶身份驗證 // ...這裏假設驗證經過 // 在session中保存用戶身份信息 session.setAttribute("username", username); return "redirect:/register.jch"; // /爲項目根目錄 } // 退出登陸 @RequestMapping("logout.jch") public String login(HttpSession session) { // 清楚session數據 session.invalidate(); return "redirect:/login.jch"; } }
package com.jch.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class LoginInterceptor implements HandlerInterceptor{ /** * 進入handler方法以前執行 * 用於身份認證,身份校驗 * 好比身份認證,若是認證不經過表示當前用戶沒有登陸,須要此方法攔截不在向下執行 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub // 獲取請求的URL String url = request.getRequestURI(); // 判斷是不是公開地址(實際使用將公開地址配置在配置文件中)這裏公開地址就是登陸提交的地址 if(url.indexOf("login.jch")>=0) { // 若是要登陸提交,那麼放行 return true; } // 判斷session HttpSession session = request.getSession(); String username = (String)session.getAttribute("username"); if(username != null) { // 有身份信息,放行 return true; } // 身份驗證不經過跳轉到登陸界面 request.getRequestDispatcher("/views/home/login.jsp").forward(request, response); System.out.println("這是第1個攔截器,preHandle方法"); return false; } /** * 進入handler以後,返回modelandview以前執行 * 應用場景從modelandview出發,將共用的模型數據(好比菜單導航)在這裏傳到視圖,也能夠在這裏統一制定視圖 */ @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { // TODO Auto-generated method stub System.out.println("這是第1個攔截器,postHandle方法"); } /** * 執行handler完成執行此方法 * 應用場景:統一異常處理,統一日誌處理 */ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub System.out.println("這是第1個攔截器, afterCompletion方法"); } }
在springmvc的前端控制器配置文件中配置interceptor攔截器
<!-- 配置攔截器 --> <mvc:interceptors> <!-- 多個攔截器,順序執行 --> <!-- 登陸認證攔截器 --> <mvc:interceptor> <mvc:mapping path="/**"/><!-- 標識攔截全部的URL包括全部的子URL --> <bean class="com.jch.interceptor.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
啓動Tomcat查看測試結果。