您的位置:首页 > 编程语言 > Java开发

Spring 4.x官方参考文档中文版——第21章 Web MVC框架(14)

2016-06-22 15:45 281 查看
21.4 handler mappings(处理器映射)
在Spring前面的版本中,用户被要求在web应用的context中定义一个或多个HandlerMapping的bean,来把请求映射到合适的handler处理器上。在你认识了注解式controller以后,你一般就不需要这样做了,因为RequestMappingHanderMapping能够自动在所有@Controller的bean中寻找@RequestMapping注解。但是,请牢牢记住,所有HandlerMapping类是继承自AbstractHandlerMapping,并且拥有着以下的属性,以用来自定义它们的行为:

Interceptors(拦截器):列出所使用的拦截器。HandlerInterceptors在”21.4.1 使用HandlerInterceptor拦截请求”一章中讲过。
defaultHandler:默认使用的handler处理器,当handler处理器映射没有匹配到对应handler时使用。
order:基于order的属性值(详见org.springframework.core.Ordered接口),Spring把所有在context中可用的handler处理器映射进行排序,并使用第一个匹配的handler处理器。
alwaysUseFullPath:如果是true,Spring会在现有Servlet context中使用完整路径来寻找合适的handler处理器。如果是false(默认值),路径是基于现有Servlet映射的。例如:如果有一个Servlet,映射路径是”/testing/*”,并且alwaysUserFullpath属性被设置为true,那么他将使用”/testing/viewPage.html”,如果为false,将使用“/viewPage.html“。
urlDecode:默认为true,就如Spring2.5那样,如果你偏爱比较编码了的路径,把这个标识设置为false。然而,HttpServletRequest总是以解码形式暴露Servlet的路径。请注意,当在编码了的路径间比较时,Servlet路径是无法匹配的。

下面的例子展示了如何配置一个interceptor(拦截器):

<beans>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<bean class="example.MyInterceptor"/>
</property>
</bean>
<beans>


21.4.1 使用HandlerInterceptor拦截请求
Spring的处理器映射机制就包括了handler处理器的拦截器,当你想要在特定请求中使用特定功能时,这个机制就会很有用。例如:checking for a principal(暂译:检查本金)。
位于handler处理器映射中的拦截器必须实现org.springframework.web.servlet包中的HandlerInterceptor。这个借口定义了三个方法:preHandle(..)会在指定handler处理器被执行前调用;postHandle(..)会在handler执行后调用;afterCompletion(..)会在请求被完整地完成后被调用。这3个方法应该可以满足所有前置处理和后置处理的各种类型的需求。
preHandle(..)方法返回一个布尔值,你能够使用这个方法来break(中断)或者continue(继续)这个执行链的处理过程。当这个方法返回true,handler处理器的执行链将继续;当返回false,DispatcherServlet就假定了拦截器已经处理过了这个请求(并且包括了比如:渲染了一个合适的视图之类的事),同时不继续执行其他拦截器,也不执行在执行链中的其他handler处理器。
拦截器能够使用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拦截。如果现在的时间在office hours(工作时间)之外,用户将被重定向到一个静态的HTML文件,这就表示,你只能在工作时间访问这个网站。

请注意:
当使用RequestMappingHandlerMapping时,这个handler处理器就是HandlerMethod的一个实例,以识别将要被调用的指定controller方法。

如你所见,Spring的适配器类:handlerInterceptorAdapter使继承HandlerInterceptor接口变得更加容易。

小提示:
在上面的例子中,这个被配置了的拦截器会在所有使用了注解式controller方法的请求处理过程中使用。如果你想要限制URL路径使用哪一个拦截器,你能够使用MVC 命名空间或者MVC Java配置,亦或声明一个MappedInterceptor类型的实例bean来指定之。详见”21.16.1 启用MVC Java配置或MVC XML命名空间”这一章节。

请注意,HandlerInterceptor的postHandle方法并不适合在使用了@ResponseBody和ResponseEntity的方法中使用。在这种情况下,HttpMessageConverter会在postHandler被调用前就写入并提交了这个响应,这样的话,postHandle就不能修改这个响应了,例如:你需要使用postHandle添加一个报头。更好的方法是:去实现ResponseBodyAdvice或者把它声明为一个@ControllerAdvice的bean,又或是直接在RequestMappingHandlerAdapter中配置来解决这个问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息