概述
Spring MVC
接口HandlerMapping
用于抽象建模概念:请求(request
)和处理器(handler
)之间的映射关系。
该接口可以由开发者实现,不过这不是必须的。框架自己带了一些实现,比如BeanNameUrlHandlerMapping
和RequestMappingHandlerMapping
。如果容器中没有注册HandlerMapping
bean
组件,那么缺省使用的会是BeanNameUrlHandlerMapping
。
HandlerMapping
仅仅定义了一个方法HandlerExecutionChain getHandler(HttpServletRequest request)
,用于根据请求(request
)获取处理器(handle
)。注意所获取的处理器(handler
)总是以一个HandlerExecutionChain
的形式存在。
一个HandlerExecutionChain
表示一组HandlerInterceptor
对象(0个或者多个)和一个真正的处理器(handler
)对象。DispatcherServlet
使用该HandlerExecutionChain
处理请求时 :
- 总是按指定的顺序调用所有
HandlerInterceptor
的preHandle
方法,最后在所有preHandle
都返回true
时才最终调用处理器(handler
)。 - 执行完
handler
之后,再按照调用preHandle
相反的顺序调用每个HandlerInterceptor
的方法postHandle
。 - 然后在
handler
执行结果处理完之后,再按照执行preHandler
相同的属性调用每个HandlerInterceptor
的方法afterCompletion
。
源代码实现
package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import org.springframework.lang.Nullable;
public interface HandlerMapping {
/**
* Name of the HttpServletRequest attribute that contains the mapped
* handler for the best matching pattern.
* @since 4.3.21
*/
String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
/**
* Name of the 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.
* 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";
/**
* Name of the HttpServletRequest attribute that contains the
* best matching pattern within the handler mapping.
* 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";
/**
* Name of the boolean HttpServletRequest attribute that indicates
* whether type-level mappings should be inspected.
* Note: This attribute is not required to be supported by all
* HandlerMapping implementations.
*/
String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName()
+ ".introspectTypeLevelMapping";
/**
* Name of the HttpServletRequest attribute that contains the URI
* templates map, mapping variable names to values.
* 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";
/**
* Name of the HttpServletRequest attribute that contains a map with
* URI variable names and a corresponding MultiValueMap of URI matrix
* variables for each.
* 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
*/
String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";
/**
* Name of the HttpServletRequest attribute that contains the set of
* producible MediaTypes applicable to the mapped handler.
* 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";
/**
* Return a handler and any interceptors for this request. The choice may be made
* on request URL, session state, or any factor the implementing class chooses.
* The returned HandlerExecutionChain contains a handler Object, rather than
* even a tag interface, so that handlers are not constrained in any way.
* For example, a HandlerAdapter could be written to allow another framework's
* handler objects to be used.
* Returns null if no match was found. This is not an error.
* The DispatcherServlet will query all registered HandlerMapping beans to find
* a match, and only decide there is an error if none can find a handler.
* @param request current HTTP request
* @return a HandlerExecutionChain instance containing handler object and
* any interceptors, or null if no mapping found
* @throws Exception if there is an internal error
*/
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
该接口主要是定义了一个方法HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception
,另外定义了一些常量,这些常量用于请求/处理器映射处理过程中往请求HttpServletRequest
中记录一些属性时作为属性名称使用。