Spring 詳解(三)------- SpringMVC攔截器使用


不攔截靜態資源

  • 若是配置攔截相似於*.do格式的攔截規則,則對靜態資源的訪問是沒有問題的,可是若是配置攔截了全部的請求(如咱們上面配置的「/」),就會形成js文件、css文件、圖片文件等靜態資源沒法訪問。css

  • 攔截器的主要做用是是用於權限管理,攔截不合理的URL,因此不對靜態資源進行攔截。html

  • 使用<mvc:resources/> (mapping:請求,location:映射地址,注意必須是webapp根目錄下的路徑。) java

spring配置文件:applicationContext-mvc.xml
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/images/**" location="/img/"/>
<mvc:resources mapping="/js/**" location="/js/"/>


使用攔截器

在實際應用中,我們通常都是經過實現 HandlerInterceptor 接口或者繼承 HandlerInterceptorAdapter 抽象類,複寫 preHandle()postHandle()afterCompletion()這 3 個方法來對用戶的請求進行攔截處理的。web

  1. 實現 HandlerInterceptor 接口(須要實現三個方法)

在 HandlerInterceptor 接口中,定義了 3 個方法,分別爲 preHandle()postHandle()afterCompletion(),我們就是經過複寫這 3 個方法來對用戶的請求進行攔截處理的。所以,我們能夠經過直接實現 HandlerInterceptor 接口來實現攔截器的功能。spring

public interface HandlerInterceptor {
    //該方法在請求處理以前進行調用。
    boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
    void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
    void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) 方法,該方法在請求處理以前進行調用。SpringMVC 中的 Interceptor 是鏈式調用的,在一個應用中或者說是在一個請求中能夠同時存在多個 Interceptor 。每一個 Interceptor 的調用會依據它的聲明順序依次執行,並且最早執行的都是 Interceptor 中的 preHandle 方法,因此能夠在這個方法中進行一些前置初始化操做或者是對當前請求作一個預處理,也能夠在這個方法中進行一些判斷來決定請求是否要繼續進行下去。該方法的返回值是布爾值 Boolean 類型的,當它返回爲 false 時,表示請求結束,後續的 Interceptor 和 Controller 都不會再執行;當返回值爲 true 時,就會繼續調用下一個 Interceptor 的 preHandle 方法,若是已是最後一個 Interceptor 的時候,就會是調用當前請求的 Controller 中的方法。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法,經過 preHandle 方法的解釋我們知道這個方法包括後面要說到的 afterCompletion 方法都只能在當前所屬的 Interceptor 的 preHandle 方法的返回值爲 true 的時候,才能被調用。postHandle 方法在當前請求進行處理以後,也就是在 Controller 中的方法調用以後執行,可是它會在 DispatcherServlet 進行視圖返回渲染以前被調用,因此我們能夠在這個方法中對 Controller 處理以後的 ModelAndView 對象進行操做。postHandle 方法被調用的方向跟 preHandle 是相反的,也就是說,先聲明的 Interceptor 的 postHandle 方法反而會後執行。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,也是須要當前對應的 Interceptor 的 preHandle 方法的返回值爲 true 時纔會執行。所以,該方法將在整個請求結束以後,也就是在 DispatcherServlet 渲染了對應的視圖以後執行,這個方法的主要做用是用於進行資源清理的工做。


  1. 繼承 HandlerInterceptorAdapter(通常使用此種方式)

須要哪一個方法重寫便可,不須要實現全部方法spring-mvc

afterConcurrentHandlingStarted()方法用於處理異步請求,當 Controller 中有異步請求方法的時候會觸發該方法時,異步請求先支持 preHandle、而後執行 afterConcurrentHandlingStarted。異步線程完成以後執行preHandlepostHandleafterCompletionmvc

public class TestHandlerInterceptorAdapter extends HandlerInterceptorAdapter {
    public TestHandlerInterceptorAdapter() {
        super();
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        super.afterConcurrentHandlingStarted(request, response, handler);
    }
}


攔截器使用測試

建立攔截器app

public class LoginHandlerInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle ------- Intercepter1" );
        return true;
    }
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ------- Intercepter1");
    }
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion ------- Intercepter1");
    }
public class LoginHandlerIntercepter2 implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle ------- Intercepter2" );
        return true;
    }

    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ------- Intercepter2" );
    }

    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion ------- Intercepter2" );
    }
}

在 spring-mvc.xml 聲明攔截器webapp

<mvc:interceptors>
     <!--使用 bean 定義一個 Interceptor,直接定義在 mvc:interceptors 下面的 Interceptor 將攔截全部的請求 -->
    <bean class="com.anqi.testHandlerInterceptor.LoginHandlerInterceptor"></bean>
    <mvc:interceptor>
        <mvc:mapping path="/testip"/>
        <!-- 定義在 mvc:interceptor 下面的 Interceptor,表示對特定的請求進行攔截 -->
        <bean class="com.anqi.testHandlerInterceptor.LoginHandlerIntercepter2"></bean>
    </mvc:interceptor>
</mvc:interceptors>

測試結果1(第一個攔截器的 preHandle 返回 true)

preHandle ------- Intercepter1
preHandle ------- Intercepter2
postHandle ------- Intercepter2
postHandle ------- Intercepter1
afterCompletion ------- Intercepter2
afterCompletion ------- Intercepter1
頁面上正常返回

測試結果2(第一個攔截器的 preHandle 返回 false)

preHandle ------- Intercepter1

頁面沒有返回 controller 返回的頁面


SimpleMappingExceptionResolver 攔截異常

官方文檔描述:

A mapping between exception class names and error view names. Useful for rendering error pages in a browser application.

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
   <property name="exceptionMappings">
      <props>
         <prop key="java.lang.Exception">/errors/404</prop>
      </props>
   </property>
</bean>
<html>
<head>
   <title>404</title>
   <link href="${basePath}/css/system/404.css" type="text/css" rel="stylesheet">
   <script type="text/javascript">
   </script>
</head>
<body>
   <div class="errorPage">
      <div class="errorImg"></div>
      <a href="${basePath}/index" class="ui-button ui-button-positive ui-button-large">返回首頁</a>
   </div>
</body>
</html>
相關文章
相關標籤/搜索