SpringMVC(8) - 处理器映射

我会带着你远行 2022-04-16 05:06 253阅读 0赞

参考:https://docs.spring.io/spring/docs/4.3.20.RELEASE/spring-framework-reference/htmlsingle/#mvc-handlermapping

在以前的Spring版本中,用户需要在Web应用程序上下文中定义一个或多个HandlerMapping bean,以将传入的Web请求映射到适当的处理器。通过引入带注解的控制器,就不需要像之前那样定义了,因为RequestMappingHandlerMapping会自动在所有@Controller bean上查找@RequestMapping注解。但是,请记住,从AbstractHandlerMapping扩展的所有HandlerMapping类都具有以下可用于自定义其行为的属性:

  • 拦截器:使用的拦截器列表
  • defaultHandler:当此处理器映射未找到匹配的处理器时使用的默认处理器。
  • order:基于order属性的值(参考org.springframework.core.Ordered接口),Spring对上下文中可用的所有处理程序映射进行排序,并应用第一个匹配的处理器。
  • alwaysUseFullPath:如果为true,则Spring使用当前Servlet上下文中的完整路径来查找适当的处理器序。如果为false(默认值),则使用当前Servlet映射中的路径。例如,如果使用 /testing/* 映射Servlet并且将alwaysUseFullPath属性设置为true,则使用 /testing/viewPage.html,而如果该属性设置为false,则使用/viewPage.html。
  • urlDecode:从Spring 2.5开始,默认为true。如果希望比较编码路径,将此标志设置为false。但是,HttpServletRequest始终以解码形式暴露Servlet路径。请注意,Servlet路径与编码路径相比是不匹配的。

以下示例显示如何配置拦截器:

  1. <beans>
  2. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
  3. <property name="interceptors">
  4. <bean class="example.MyInterceptor"/>
  5. </property>
  6. </bean>
  7. <beans>
  1. 使用HandlerInterceptor拦截请求

Spring的处理器映射机制包括处理器拦截器,当想要将特定功能应用于某些请求(例如,检查认证信息)时,它们很有用。

位于处理器映射中的拦截器必须从org.springframework.web.servlet.HandlerInterceptor。该接口定义了三种方法,这三种方法应该提供足够的灵活性来进行各种预处理和后处理,方法如下:

  • 在执行实际处理程序之前调用preHandle(..)
  • 执行处理程序后调用postHandle(..)
  • 完成请求完成后调用afterCompletion(..)

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

可以使用interceptors属性配置拦截器,该属性存在于从AbstractHandlerMapping扩展的所有HandlerMapping类中。示例:

  1. <beans>
  2. <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
  3. <property name="interceptors">
  4. <list>
  5. <ref bean="officeHoursInterceptor"/>
  6. </list>
  7. </property>
  8. </bean>
  9. <bean id="officeHoursInterceptor" class="samples.TimeBasedAccessInterceptor">
  10. <property name="openingTime" value="9"/>
  11. <property name="closingTime" value="18"/>
  12. </bean>
  13. </beans>

TimeBasedAccessInterceptor拦截此映射处理的任何请求。如果当前时间不在办公时间,则会将用户重定向到静态HTML文件,例如,只能在办公时间访问该网站。

  1. package samples;
  2. public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {
  3. private int openingTime;
  4. private int closingTime;
  5. public void setOpeningTime(int openingTime) {
  6. this.openingTime = openingTime;
  7. }
  8. public void setClosingTime(int closingTime) {
  9. this.closingTime = closingTime;
  10. }
  11. public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
  12. Object handler) throws Exception {
  13. Calendar cal = Calendar.getInstance();
  14. int hour = cal.get(HOUR_OF_DAY);
  15. if (openingTime <= hour && hour < closingTime) {
  16. return true;
  17. }
  18. response.sendRedirect("http://host.com/outsideOfficeHours.html");
  19. return false;
  20. }
  21. }

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

如上例,Spring适配器类HandlerInterceptorAdapter使扩展HandlerInterceptor接口变得更容易。

提示:在上面的示例中,配置的拦截器将应用于使用带注解的控制器方法处理的所有请求。如果要缩小拦截器应用的URL路径,可以使用MVC命名空间或MVC Java配置,或者声明类型为MappedInterceptor的bean实例来执行此操作。

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

发表评论

表情:
评论列表 (有 0 条评论,253人围观)

还没有评论,来说两句吧...

相关阅读