SpringMVC中的攔截器的樣本及應用,springmvc樣本
一、自訂攔截器實作類別
在Springmvc中想要定義攔截器,則自訂一個類要實現HandlerInterceptor介面,HandlerInterceptor介面中有三個抽象方法,若不想使用全部,則可以或者是這個類繼承HandlerInterceptor介面的實作類別,比如Spring已經提供的實現了HandlerInterceptor 介面的抽象類別HandlerInterceptorAdapter ;
在此之前,先回顧下springmvc整個訪問的流程:
HandlerInterceptor介面的定義如下:
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;}
HandlerInterceptor介面中定義了三個抽象方法:
**preHandle方法:**Springmvc中可以存在多個自訂攔截器。每個攔截器的調用會依據他的聲明順序依次執行,preHandle()為最先執行的方法,傳回值為boolean類型。當返回true時,會繼續調用下一個攔截器的preHandle方法,直至最後一個攔截器的preHandle運行結束並返回true時,才調用Controller中的方法。當某個攔截器的preHandle()傳回值為false時,後續的攔截器和Controller都不會再執行;這個方法作用在中2的位置。
postHandle方法:執行完Controller後調用的方法。也就意味著在此之前全部攔截器的preHandle()傳回值均為true,否則無法執行Controller。進而總結出此方法的一個特點:postHandle()方法是只有在preHandle()方法的傳回值為true 時才能被調用的方法。它的執行時間是在處理器適配器進行處理之後,在中10的位置執行,也就是說在這個方法中你可以對ModelAndView進行操作。這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會後調用。
afterCompletion方法:次方法同樣為當前對應的攔截器 的preHandle方法的傳回值為true 時才能被調用的方法。該方法將在整個請求完成之後,也就是在13位置執行,這個方法的主要作用是用於清理資源的。
二、攔截器應用簡單樣本
1.建立自訂Class實現HandlerInterceptor介面:
public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("preHandle...."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle...."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion...."); }}
2.在springmvc.xml中配置自訂的Interceptor
<!-- 配置攔截器 --> <mvc:interceptors> <!-- 多個攔截器,順序執行 --> <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 --> <!-- <bean class="com.asjy.util.MyInterceptor"></bean> --> <mvc:interceptor> <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 --> <mvc:mapping path="/user/**" /> <bean class="com.asjy.util.MyInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
3.測試,訪問登入頁login.jsp,點擊登入後會向Controller發送一個請求(jsp頁和Controller頁不為本次重點,略)
三、多個攔截器應用樣本
1.新增兩個測試攔截器MyInterceptor2, MyInterceptor3,增加一個登入驗證攔截器LoginInterceptor,對於未進行登入的使用者禁止訪問login.jsp以外的頁面
public class MyInterceptor2 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("preHandle....2"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle....2"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion....2"); }}
public class MyInterceptor3 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("preHandle....3"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("postHandle....3"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("afterCompletion....3"); }}
public class LoginInterceptor implements HandlerInterceptor {
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub System.out.println("Login....preHandle.... 4"); //擷取請求的URL String url = request.getRequestURI(); //URL:login.jsp是公開的;這個demo是除了login.jsp是可以公開訪問的,其它的URL都進行攔截控制 if(url.indexOf("doLogin.do")>=0){ return true; } //擷取Session HttpSession session = request.getSession(); String username = (String)session.getAttribute("username"); if(username != null){ return true; } //不合格,跳轉到登入介面 request.getRequestDispatcher("../login.jsp").forward(request, response); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("login...postHandle....4"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("login...afterCompletion....4"); }}
2.在springmvc.xml中配置自訂的Interceptor
<!-- 配置攔截器 --> <mvc:interceptors> <!-- 多個攔截器,順序執行 --> <!-- 使用bean定義一個Interceptor,直接定義在mvc:interceptors根下面的Interceptor將攔截所有的請求 --> <bean class="com.asjy.util.MyInterceptor"></bean> <bean class="com.asjy.util.MyInterceptor2"></bean> <bean class="com.asjy.util.MyInterceptor3"></bean> <mvc:interceptor> <!-- 定義在mvc:interceptor下面的表示是對特定的請求才進行攔截的 --> <mvc:mapping path="/user/**" /> <bean class="com.asjy.util.LoginInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
點擊登入後,攔截器允許存取,跳轉至doLogin.do,儲存資訊至session中。代碼為:
@RequestMapping("doLogin") public String doLogin(String username,HttpServletRequest request){ HttpSession session = request.getSession(); session.setAttribute("username", username); return "redirect:/user/list.do"; //重至使用者列表首頁面 }
@RequestMapping("list") public String doAdd(UserExt userExt,Model model){ List<User> list = new ArrayList<User>(); User u1 = new User(); u1.setId(1); u1.setUsername("tom"); User u2 = new User(); u2.setId(2); u2.setUsername("jerry"); User u3 = new User(); u3.setId(3); u3.setUsername("lucy"); list.add(u1); list.add(u2); list.add(u3); model.addAttribute("list",list); return "list"; }
3.測試
(1)未進行登入狀態下直接存取list.do
可見程式執行至LoginInterceptor時,未檢測到session中username的值,則返回false,並跳轉至登入頁,程式無法進入Controller
(2).先登入
登入成功:
開啟新視窗,再次直接存取list.do
訪問成功!看看控制台列印的什麼: