Spring|Spring MVC 02 - HandlerMapping

HandlerMapping

// HandlerMapping +HandlerExecutionChain getHandler(HttpServletRequest request)

根据 Request 匹配handler 返回 HandlerExecutionChain
// HandlerExecutionChain private final Object handler; private HandlerInterceptor[] interceptors;

HandlerExecutionChain 包含一个实际的handler 和一串interceptors
实际常用的实现是 RequestMappingHandlerMapping。讲Controller 的 @RequestMapping 修饰的方法作为 handler

Spring|Spring MVC 02 - HandlerMapping
文章图片
image.png
【Spring|Spring MVC 02 - HandlerMapping】AbstractHandlerMapping
HandlerMapping 的入口,管理 handler interceptors. 和一些列工具类 UrlPathHelper, AntPathMatcher 等。
AbstractHandlerMethodMapping
注册handler 和匹配规则,实现根据 request 搜索匹配 handler 的逻辑。T 代表匹配规则。
RequestMappingInfoHandlerMapping
extends AbstractHandlerMethodMapping 将匹配规则实现具体到 RequestMappingInfo 类。
同时向请求中添加一些关于解析结果的属性
RequestMappingHandlerMapping
初始化 AbstractHandlerMapping
  1. initApplicationContext()
    detectMappedInterceptors 找到所有mapped interceptor, 添加入adaptedInterceptors list中
AbstractHandlerMethodMapping afterPropertiesSet() 中调用 initHandlerMethods()
  1. 遍历所有bean, 使用模版方法 isHandler 判断一个bean 是否为handler。对于handler 调用 detectHandlerMethods
  2. detectHandlerMethods() 遍历handler bean 下所有的方法,使用模版方法 T getMappingForMethod(Method method, Class handlerType) 判断并返回当前method 对应的匹配条件。使用registerHandler 注册下来。
  3. registerHandlerMethod(Object handler, Method method, T mapping) 调用 MappingRegistry.register() 注册handler 及其mapping.
RequestMappingHandlerMapping isHandler
实现模板方法,检查bean 是否为 Controller 或者 RequestMapping
getMappingForMethod
实现模板方法
  1. 依次对 handler 和 method 调用 createRequestMappingInfo
    2 createRequestMappingInfo 获取 RequestMapping 的 annotation, 调用 createRequestMappingInfo 生成 RequestMappingInfo
    3 createRequestMappingInfo 从 RequestMapping 从取出 path, method, header... 加上 config,生成RequestMappingInfo
MappingRegistry
// 存储匹配条件 - handlerMethod 的 mapping -Map mappingLookup = new LinkedHashMap(); // 不带匹配规则的简单url - handler methods 的 mapping。方便在查找简单url时快速找到对应的 handler methods -final MultiValueMap urlLookup = new LinkedMultiValueMap();

register(T mapping, Object handler, Method method)
  1. 调用 createHandlerMethod(handler, method) 创建 handlerMethod
  2. 检查该mapping 是否已经注册过
  3. 加入 mappingLookup
  4. getDirectUrls 尝试从该mapping 中获取简单url,如有简单url,则加入 urlLookup
匹配Handler
//HandlerMapping HandlerExecutionChain getHandler(HttpServletRequest request)

AbstractHandlerMapping getHandler()
  1. 调用模版方法 ·Object getHandlerInternal(HttpServletRequest)` 获取 handler
  2. 调用 getHandlerExecutionChain. 将handler和所有adaptedInterceptors 添加入 HandlerExectionChain
AbstractHandlerMethodMapping
  1. getUrlPathHelper().getLookupPathForRequest(request) 提取请求路径
  2. 调用 HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) 匹配handler
    2.1 从urlMap 中尝试直接取出所有满足条件的匹配
    2.2 否则则取出所有注册的匹配条件
    2.3 模版方法getMatchingMapping 获取准确的mapping 并过滤掉完全不匹配的条件
    2.4 用MatchComparator 对所有匹配条件进行排序,找到最佳的。排序算法由模版方法 Comparator getMappingComparator(HttpServletRequest request) 提供
    2.4 调用模板方法 handleMatch
RequestMappingInfoHandlerMapping 实现模板方法
getMappingComparator()
protected Comparator getMappingComparator(final HttpServletRequest request) { return (info1, info2) -> info1.compareTo(info2, request); }

handleMatch()
添加匹配结果相关属性到 request
handleNoMatch()
针对没匹配上的情况抛出相应异常
RequestMappingInfo
Spring|Spring MVC 02 - HandlerMapping
文章图片
image.png
  • RequestCondition 中的T 是这个匹配条件可以combine/compare 的对象,实际的实现里面都是自己。比如RequestMappingInfo implements RequestCondition
  • getMatchingCondition 返回null (不匹配)或者一个新的 Condition (可以去掉无关的信息)
  • compareTo 在执行了 getMatchingCondition 的前提下比较(保证去除了无关信息)
RequestMappingInfo
整合了所有请求相关的 Condition
private final PatternsRequestCondition patternsCondition; private final RequestMethodsRequestCondition methodsCondition; private final ParamsRequestCondition paramsCondition; private final HeadersRequestCondition headersCondition; private final ConsumesRequestCondition consumesCondition; private final ProducesRequestCondition producesCondition; private final RequestConditionHolder customConditionHolder;

匹配request 的时候会逐个Condition 检查,都匹配上则通过。
compare 的时候也会逐个Condition 进行比较
总结大致流程 Spring|Spring MVC 02 - HandlerMapping
文章图片
image.png

    推荐阅读