SpringMVC源码系列:HandlerMapping

3,370 阅读4分钟

HandlerMapping接口是用来查找Handler的。在SpringMvc中,DispatcherServlet处理分发很多请求,而每个请求都需要一个Handler来处理,具体接受到一个请求后使用哪个Handler来处理呢?这就是Handler要做的事情。因此,HandlerMapping的作用就是根据request找到相应的处理器Handler和Interceptors。

下面是Spring中对HandlerMapping接口的说明:

This class can be implemented by application developers, although this is not necessary, as BeanNameUrlHandlerMapping and DefaultAnnotationHandlerMapping are included in the framework. The former is the default if no HandlerMapping bean is registered in the application context.
这个类可以由应用程序开发人员实现,尽管这不是必须的,因为BeanNameUrlHandlerMapping和DefaultAnnotationHandlerMapping已经包含在框架中,作为HandlerMapping的默认实现。 如果在应用程序上下文中没有注册HandlerMapping bean,BeanNameUrlHandlerMapping是默认值。

HandlerMapping implementations can support mapped interceptors but do not have to. A handler will always be wrapped in a HandlerExecutionChain instance, optionally accompanied by some HandlerInterceptor instances.The DispatcherServlet will first call each HandlerInterceptor's preHandle method in the given order, finally invoking the handler itself if all preHandle methods have returned true
HandlerMapping实现可以支持映射的拦截器,但不必如此;handler将始终被封装在HandlerExecutionChain实例中,并可由一些HandlerInterceptor实例执行。在给定的顺序中,DispatcherServlet将首先调用每个HandlerInterceptor的preHandle方法,如果所有的preHandle方法都返回true,那么最后调用handler本身。

The ability to parameterize this mapping is a powerful and unusual capability of this MVC framework. For example, it is possible to write a custom mapping based on session state, cookie state or many other variables. No other MVC framework seems to be equally flexible.
参数化这个映射的能力是这个MVC框架的一个强大且不同寻常的能力。 例如,可以根据会话状态,cookie状态或许多其他变量编写自定义映射。 没有其他MVC框架似乎同样灵活。

Note: Implementations can implement the Ordered interface to be able to specify a sorting order and thus a priority for getting applied by DispatcherServlet. Non-Ordered instances get treated as lowest priority.
注:实现可以实现Ordered接口,以便能够指定排序顺序,从而指定由DispatcherServlet应用的优先级。 无序实例被视为最低优先级。

1.接口常量

1.1、PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE

HttpServletRequest属性的名称,它包含处理程序映射中的路径,比如模式匹配,或者完全相关的URI(通常在DispatcherServlet的映射中)。此属性不需要所有HandlerMapping实现支持。基于url的HandlerMappings通常会支持它,但是处理程序不应该期望这个请求属性在所有场景中都存在。

/**
 * Name of the {@link HttpServletRequest} attribute that contains the path
 * within the handler mapping, in case of a pattern match, or the full
 * relevant URI (typically within the DispatcherServlet's mapping) else.
 * <p>Note: This attribute is not required to be supported by all
 * HandlerMapping implementations. URL-based HandlerMappings will
 * typically support it, but handlers should not necessarily expect
 * this request attribute to be present in all scenarios.
 */
String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";

1.2、BEST_MATCHING_PATTERN_ATTRIBUTE

HttpServletRequest属性的名称,包括处理程序映射中的最佳匹配模式

/**
 * Name of the {@link HttpServletRequest} attribute that contains the
 * best matching pattern within the handler mapping.
 * <p>Note: This attribute is not required to be supported by all
 * HandlerMapping implementations. URL-based HandlerMappings will
 * typically support it, but handlers should not necessarily expect
 * this request attribute to be present in all scenarios.
 */
String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";

1.3、INTROSPECT_TYPE_LEVEL_MAPPING

HttpServletRequest属性的名称,指示是否应该检查类型级别的映射。

/**
 * Name of the boolean {@link HttpServletRequest} attribute that indicates
 * whether type-level mappings should be inspected.
 * <p>Note: This attribute is not required to be supported by all
 * HandlerMapping implementations.
 */
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";

1.4、URI_TEMPLATE_VARIABLES_ATTRIBUTE

包含URI模板映射的HttpServletRequest属性的名称,将变量名称映射到值。

/**
 * Name of the {@link HttpServletRequest} attribute that contains the URI
 * templates map, mapping variable names to values.
 * <p>Note: This attribute is not required to be supported by all
 * HandlerMapping implementations. URL-based HandlerMappings will
 * typically support it, but handlers should not necessarily expect
 * this request attribute to be present in all scenarios.
 */
String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";

1.5、MATRIX_VARIABLES_ATTRIBUTE

包含带有URI矩阵变量的映射的HttpServletRequest属性的名称。此属性不需要所有HandlerMapping实现支持,也可能不存在,这取决于HandlerMapping是否被配置为在请求URI中保留矩阵变量内容。

/**
 * Name of the {@link HttpServletRequest} attribute that contains a map with
 * URI matrix variables.
 * <p>Note: This attribute is not required to be supported by all
 * HandlerMapping implementations and may also not be present depending on
 * whether the HandlerMapping is configured to keep matrix variable content
 * in the request URI.
 */
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";

1.6、PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE

HttpServletRequest属性的名称,该属性包含可用于映射处理程序的可生成的MediaTypes集合。

/**
 * Name of the {@link HttpServletRequest} attribute that contains the set of
 * producible MediaTypes applicable to the mapped handler.
 * <p>Note: This attribute is not required to be supported by all
 * HandlerMapping implementations. Handlers should not necessarily expect
 * this request attribute to be present in all scenarios.
 */
String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

2.核心方法

HandlerMapping接口中只有一个方法,如下:

HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

从方法定义可以看出,getHandler方法就是通过request来获取一个HandlerExecutionChain;该方法在不同的子类中都有实现,具体的实现后面说子类的时候在详细分析。

3.HandlerMapping的子类

图中黄色部分表示已经过时的类,时间开发中不建议再使用。

在HandlerMapping的体系中可以看出,HandlerMapping下属子类可分为两个分支;

  • AbstractHandlerMethodMapping
  • AbstractUrlHandlerMapping

上述两个抽象类又均是AbstractHandlerMapping的子类。关于AbstractHandlerMapping我们下篇文章来学习。

大家如果有什么意见或者建议可以在下方评论区留言,也可以给我们发邮件(glmapper_2018@163.com)!欢迎小伙伴与我们一起交流,一起成长。