18.4.1用HandlerInterceptor拦截请求

Spring的处理程序映射机制包括处理程序拦截器,当您想要将特定的功能应用于某些请求时(例如,检查主体),这是非常有用的。

位于处理程序映射中的拦截器必须从org.springframework.web.servlet包中实现HandlerInterceptor。 这个接口定义了三个方法:preHandle(..)在实际的处理器被执行之前被调用; postHandle(..)被调用后,处理程序被执行; 并且在完成请求完成之后调用afterCompletion(..)。 这三种方法应该提供足够的灵活性来进行各种预处理和后处理。

preHandle(..)方法返回一个布尔值。 您可以使用此方法来中断或继续处理执行链。 当此方法返回true时,处理程序执行链将继续; 当它返回false时,DispatcherServlet假定拦截器本身已经处理了请求(并且例如呈现了适当的视图)并且不继续执行执行链中的其他拦截器和实际处理器。

拦截器可以使用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拦截。 如果当前时间在办公时间之外,用户被重定向到一个静态的HTML文件,例如说你只能在办公时间访问网站。

当使用RequestMappingHandlerMapping时,实际的处理程序是HandlerMethod的一个实例,它标识了将被调用的特定控制器方法。

正如你所看到的,Spring适配器类HandlerInterceptorAdapter使扩展HandlerInterceptorinter面更容易。

在上面的示例中,配置的拦截器将应用于使用带注解的控制器方法处理的所有请求。 如果要缩小拦截器所应用的URL路径,可以使用MVC名称空间或MVC Java配置,或者声明MappedInterceptor类型的bean实例来执行此操作。 请参见Section18.16.1, “Enabling the MVC Java Config or the MVC XML Namespace”

请注意,HandlerInterceptorpostHandle方法并不总是非常适合与@ResponseBodyResponseEntity方法一起使用。 在这种情况下HttpMessageConverter会在调用postHandle之前写入并提交响应,从而无法更改响应,例如添加标题。 相反,应用程序可以实现ResponseBodyAdvice,并将其声明为@ControllerAdvice bean,或直接在RequestMappingHandlerAdapter上进行配置。

results matching ""

    No results matching ""