轉載請注明出處:http://www.cnblogs.com/Joanna-Yan/p/7098753.html
前面講到:Spring+SpringMVC+MyBatis深入學習及搭建(十六)——SpringMVC注解開發(高級篇)
1.攔截器定義
Spring Web MVC的處理器攔截器類似於Servlet開發中的過濾器Filter,用於對處理器進行預處理和后處理。
定義攔截器,實現HandlerInterceptor接口。接口中提供三個方法。
package joanna.yan.ssm.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 void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("HandlerInterceptor1......afterCompletion"); } //進入Handler方法之后,返回modelAndView之前執行 //應用場景從modelAndView出發:將公用的模型數據(比如菜單導航)在這里傳到視圖,也可以在這里同意指定視圖 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("HandlerInterceptor1......postHandle"); } //進入Handler方法之前執行 //用於身份認證、身份授權 //比如身份認證,如果認證不通過表示當前用戶沒有登錄,需要此方法攔截不再向下執行。 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("HandlerInterceptor1......preHandle"); //return false表示攔截,不向下執行 //return true表示放行 return true; } }
2.攔截器配置
struts中是有一個大的攔截器鏈,它是一個共用的東西,可以把它添加到任何的action鏈接,都讓它攔截。但是spring的攔截器不是全局的。
2.1針對某種mapping配置攔截器
springmvc攔截器針對HandlerMapping進行攔截設置,如果在某個HandlerMapping中設置攔截,經過該HandlerMapping映射成功的handler最終使用該攔截器。
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="handlerInterceptor1"/> <ref bean="handlerInterceptor2"/> </list> </property> </bean> <bean id="handlerInterceptor1" class="joanna.yan.ssm.interceptor.HandlerInterceptor1"/> <bean id="handlerInterceptor2" class="joanna.yan.ssm.interceptor.HandlerInterceptor2"/>
一般不推薦使用。
2.2針對所有mapping配置全局攔截器
springmvc可以配置類似全局的攔截器,springmvc框架將配置的類似全局的攔截器注入到每個HandlerMapping中。
<!--攔截器 --> <mvc:interceptors> <!--多個攔截器,順序執行 --> <mvc:interceptor> <!-- /**表示所有url包括子url路徑 --> <mvc:mapping path="/**"/> <bean class="joanna.yan.ssm.interceptor.HandlerInterceptor1"></bean> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="joanna.yan.ssm.interceptor.HandlerInterceptor2"></bean> </mvc:interceptor> </mvc:interceptors>
3.攔截測試
3.1測試需求
測試多個攔截器各個方法的執行時機。
3.2編寫兩個攔截器
3.3兩個攔截器都放行
運行日志信息:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor2...postHandle
HandlerInterceptor1...postHandle
HandlerInterceptor2...afterCompletion
HandlerInterceptor1...afterCompletion
總結:
preHandle方法按順序執行,postHandle和afterCompletion按攔截器配置的逆向順序執行。
3.4攔截器1放行,攔截器2不放行
運行日志信息:
HandlerInterceptor1...preHandle
HandlerInterceptor2...preHandle
HandlerInterceptor1...afterCompletion
總結:
攔截器1放行,攔截器2的preHandle才會執行。
攔截器2的preHandle不放行,攔截器2的postHandle和afterCompletion不會執行。
只要有一個攔截器不放行,postHandle就不會執行。
3.5攔截器1不放行,攔截器2不放行
運行日志信息:
HandlerInterceptor1...preHandle
攔截器1的preHandle不放行,postHandle和afterCompletion不會執行。
攔截器1的preHandle不放行,攔截器2不執行。
4.小結
根據測試結果,對攔截器應用。
比如:統一日志處理攔截器,需要改攔截器preHandle一定要放行,且將它放在攔截器鏈中的第一位置。
比如:登錄認證攔截器,放在攔截器鏈中第一個位置。權限校驗攔截器,放在登錄攔截器之后。(因為登錄通過后才校驗權限)
5.攔截器應用(實現登錄認證)
5.1需求
(1)用戶請求url
(2)攔截器進行攔截校驗
如果請求的url是公開地址(無需登錄即可訪問的url),讓放行
如果用戶session不存在,跳轉到登錄頁面。
如果用戶session存在,放行,繼續操作。
5.2登錄、退出controller方法
package joanna.yan.ssm.controller; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class LoginController { //登錄 @RequestMapping("/login") public String login(HttpSession session, String username, String password) throws Exception{ //調用service進行用戶身份認證 //... //在session中保存用戶身份信息 session.setAttribute("username", username); return "redirect:items/queryItems.action"; } //退出 @RequestMapping("/logout") public String logout(HttpSession session) throws Exception{ //清除session session.invalidate(); return "redirect:items/queryItems.action"; } }
5.3登錄認證攔截實現
5.3.1LoginInterceptor
public class LoginInterceptor implements HandlerInterceptor{ //執行Handler完成執行此方法 //應用場景:統一異常處理,統一日志處理 @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("HandlerInterceptor1......afterCompletion"); } //進入Handler方法之后,返回modelAndView之前執行 //應用場景從modelAndView出發:將公用的模型數據(比如菜單導航)在這里傳到視圖,也可以在這里同意指定視圖 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("HandlerInterceptor1......postHandle"); } //進入Handler方法之前執行 //用於身份認證、身份授權 //比如身份認證,如果認證不通過表示當前用戶沒有登錄,需要此方法攔截不再向下執行。 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("HandlerInterceptor1......preHandle"); //獲取請求的url String url=request.getRequestURI(); //判斷url是否是公開地址(實際使用時要將公開地址配置到文件中) //這里公開地址是登錄提交的地址 if(url.indexOf("login.action")>=0){ //如果進行登錄提交,放行 return true; } //判斷session HttpSession session=request.getSession(); String username=(String) session.getAttribute("username"); if(username!=null){ //身份存在,放行 return true; } //執行到這里,表示用戶身份需要認證,跳轉登錄頁面 request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); //return false表示攔截,不向下執行 //return true表示放行 return false; } }
5.3.2攔截器配置
classpath下springmvc.xml中配置:
如果此文對您有幫助,微信打賞我一下吧~