Spring MVC 使用HandlerInterceptor攔截請求

2018-07-26 14:07 更新

Spring的處理器映射機制包含了處理器攔截器。攔截器在你需要為特定類型的請求應(yīng)用一些功能時可能很有用,比如,檢查用戶身份等。

處理器映射處理過程配置的攔截器,必須實現(xiàn) org.springframework.web.servlet包下的 HandlerInterceptor接口。這個接口定義了三個方法: preHandle(..),它在處理器實際執(zhí)行 之前 會被執(zhí)行; postHandle(..),它在處理器執(zhí)行 完畢 以后被執(zhí)行; afterCompletion(..),它在 整個請求處理完成 之后被執(zhí)行。這三個方法為各種類型的前處理和后處理需求提供了足夠的靈活性。

preHandle(..)方法返回一個boolean值。你可以通過這個方法來決定是否繼續(xù)執(zhí)行處理鏈中的部件。當(dāng)方法返回 true時,處理器鏈會繼續(xù)執(zhí)行;若方法返回 false, DispatcherServlet即認(rèn)為攔截器自身已經(jīng)完成了對請求的處理(比如說,已經(jīng)渲染了一個合適的視圖),那么其余的攔截器以及執(zhí)行鏈中的其他處理器就不會再被執(zhí)行了。

攔截器可以通過interceptors屬性來配置,該選項在所有繼承了AbstractHandlerMapping的處理器映射類HandlerMapping都提供了配置的接口。如下面代碼樣例所示:

<beans>
    <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        <property name="interceptors">
            <list>
                <ref bean="officeHoursInterceptor"/>
            </list>
        </property>
    </bean>

    <bean id="officeHoursInterceptor" class="samples.TimeBasedAccessInterceptor">
        <property name="openingTime" value="9"/>
        <property name="closingTime" value="18"/>
    </bean>
<beans>
package samples;

public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {

    private int openingTime;
    private int closingTime;

    public void setOpeningTime(int openingTime) {
        this.openingTime = openingTime;
    }

    public void setClosingTime(int closingTime) {
        this.closingTime = closingTime;
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object handler) throws Exception {
        Calendar cal = Calendar.getInstance();
        int hour = cal.get(HOUR_OF_DAY);
        if (openingTime <= hour && hour < closingTime) {
            return true;
        }
        response.sendRedirect("http://host.com/outsideOfficeHours.html");
        return false;
    }
}

在上面的例子中,所有被此處理器處理的請求都會被TimeBasedAccessInterceptor攔截器攔截。如果當(dāng)前時間在工作時間以外,那么用戶就會被重定向到一個HTML文件提示用戶,比如顯示“你只有在工作時間才可以訪問本網(wǎng)站”之類的信息。

使用RequestMappingHandlerMapping時,實際的處理器是一個處理器方法HandlerMethod的實例,它標(biāo)識了一個將被用于處理該請求的控制器方法。

如你所見,Spring的攔截器適配器HandlerInterceptorAdapter讓繼承HandlerInterceptor接口變得更簡單了。

上面的例子中,所有控制器方法處理的請求都會被配置的攔截器先攔截到。如果你想進一步縮小攔截的URL范圍,你可以通過MVC命名空間或MVC Java編程的方式來配置,或者,聲明一個MappedInterceptor類型的bean實例來處理。具體請見 21.16.1 啟用MVC Java編程配置或MVC命名空間配置一小節(jié)。

需要注意的是,HandlerInterceptor的后攔截postHandle方法不一定總是適用于注解了@ResponseBodyResponseEntity的方法。這些場景中,HttpMessageConverter會在攔截器的postHandle方法被調(diào)之前就把信息寫回響應(yīng)中。這樣攔截器就無法再改變響應(yīng)了,比如要增加一個響應(yīng)頭之類的。如果有這種需求,請讓你的應(yīng)用實現(xiàn)ResponseBodyAdvice接口,并將其定義為一個@ControllerAdvicebean或直接在RequestMappingHandlerMapping中配置。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號