美文网首页
Spring MVC 02 - HandlerMapping

Spring MVC 02 - HandlerMapping

作者: lxian2shell | 来源:发表于2018-08-10 19:41 被阅读0次

    HandlerMapping

    // HandlerMapping
    +HandlerExecutionChain getHandler(HttpServletRequest request)
    

    根据 Request 匹配handler 返回 HandlerExecutionChain

    // HandlerExecutionChain
    private final Object handler;
    private HandlerInterceptor[] interceptors;
    

    HandlerExecutionChain 包含一个实际的handler 和一串interceptors

    实际常用的实现是 RequestMappingHandlerMapping。讲Controller 的 @RequestMapping 修饰的方法作为 handler

    image.png

    AbstractHandlerMapping
    HandlerMapping 的入口,管理 handler interceptors. 和一些列工具类 UrlPathHelper, AntPathMatcher 等。
    AbstractHandlerMethodMapping<T>
    注册handler 和匹配规则,实现根据 request 搜索匹配 handler 的逻辑。T 代表匹配规则。
    RequestMappingInfoHandlerMapping
    extends AbstractHandlerMethodMapping<RequestMappingInfo> 将匹配规则实现具体到 RequestMappingInfo 类。
    同时向请求中添加一些关于解析结果的属性
    RequestMappingHandlerMapping

    初始化

    AbstractHandlerMapping

    1. initApplicationContext()
      detectMappedInterceptors 找到所有mapped interceptor, 添加入adaptedInterceptors list中

    AbstractHandlerMethodMapping<T>

    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<T, HandlerMethod> mappingLookup = new LinkedHashMap<T, HandlerMethod>();
    // 不带匹配规则的简单url - handler methods 的 mapping。方便在查找简单url时快速找到对应的 handler methods
    -final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<String, T>();
    

    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<T> getMappingComparator(HttpServletRequest request) 提供
      2.4 调用模板方法 handleMatch

    RequestMappingInfoHandlerMapping

    实现模板方法
    getMappingComparator()

    protected Comparator<RequestMappingInfo> getMappingComparator(final HttpServletRequest request) {
        return (info1, info2) -> info1.compareTo(info2, request);
    }
    

    handleMatch()
    添加匹配结果相关属性到 request

    handleNoMatch()
    针对没匹配上的情况抛出相应异常

    RequestMappingInfo

    image.png
    • RequestCondition<T> 中的T 是这个匹配条件可以combine/compare 的对象,实际的实现里面都是自己。比如RequestMappingInfo implements RequestCondition<RequestMappingInfo>
    • 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 进行比较

    总结大致流程

    image.png

    相关文章

      网友评论

          本文标题:Spring MVC 02 - HandlerMapping

          本文链接:https://www.haomeiwen.com/subject/rhgkbftx.html