• springMVC(五): 通过 HandlerMapping 获取 HandlerExecutionChain


     请求具体过程

     

    一、HandlerMapping 

     Interface to be implemented by objects that define a mapping between requests and handler objects.

        HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

    HandlerExecutionChain(包含一个处理器 handler 如HandlerMethod 对象、多个 HandlerInterceptor 拦截器对象)

    • RequestMappingHandlerMapping 的映射关系由 MappingRegistry 维护,通过多个map联结,即可找到请求对应的处理器
    • RequestMappingHandlerMapping 的映射关系初始化入口是 afterProperties 方法,因为其实现了接口 InitializingBean

    SpringMVC的请求处理过程中的路径匹配过程(AbstractHandlerMethodMapping#lookupHandlerMethod)

        protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
            List<Match> matches = new ArrayList<Match>();
            List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
            if (directPathMatches != null) {
                addMatchingMappings(directPathMatches, matches, request);
            }
            if (matches.isEmpty()) {
                // 如正则匹配、RESTFUL路径/list/{cityId}等,这里可以改进,No choice but to go through all mappings...
                addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);
            }
    
            if (!matches.isEmpty()) {
                Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
                Collections.sort(matches, comparator);
                if (logger.isTraceEnabled()) {
                    logger.trace("Found " + matches.size() + " matching mapping(s) for [" +
                            lookupPath + "] : " + matches);
                }
                Match bestMatch = matches.get(0);
                if (matches.size() > 1) {
                    if (CorsUtils.isPreFlightRequest(request)) {
                        return PREFLIGHT_AMBIGUOUS_MATCH;
                    }
                    Match secondBestMatch = matches.get(1);
                    if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                        Method m1 = bestMatch.handlerMethod.getMethod();
                        Method m2 = secondBestMatch.handlerMethod.getMethod();
                        throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" +
                                request.getRequestURL() + "': {" + m1 + ", " + m2 + "}");
                    }
                }
                handleMatch(bestMatch.mapping, lookupPath, request);
                return bestMatch.handlerMethod;
            }
            else {
                return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);
            }
        }

    RequestMappingHandlerMapping根据,细化匹配条件,整体的查找过程如下:

    1.1 从urlMap中直接等值匹配查找匹配条件RequestMappingInfo

    1.2 如果等值查找到匹配条件,将其添加到match条件中

    1.3 如果没有找到匹配条件,使用所有的handlerMethod的RequestMappingInfo进行匹配

    1.4 对匹配到的Match进行排序,取出最高优先级的Match,并核对是否是唯一的最高优先级

    二、获取HandlerExecutionChain(AbstractHandlerMapping#getHandler)

        @Override
        public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
         //模板方法 Object handler
    = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = getApplicationContext().getBean(handlerName); }      //把Handler和HandlerInterceptor包裹成HandlerExecutionChain HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }

    3.getHandlerExecutionChain调用

        protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
         //为啥这里要做判断,因为DispatchServlet里面的doDispatch调用getHandler返回的是HandlerExecutionChain HandlerExecutionChain chain
    = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); String lookupPath = this.urlPathHelper.getLookupPathForRequest(request); for (HandlerInterceptor interceptor : this.adaptedInterceptors) { if (interceptor instanceof MappedInterceptor) { MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) { chain.addInterceptor(mappedInterceptor.getInterceptor()); } } else { chain.addInterceptor(interceptor); } } return chain; }

    三、选择使用HandlerMapping

    如何选择合适的HandlerMapping

        protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
            for (HandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
           //如何选择不同的HandlerMapping HandlerExecutionChain handler
    = hm.getHandler(request); if (handler != null) { return handler; } } return null; }
  • 相关阅读:
    Control Group(CGroup)资源限制组
    系统安全之用户认证
    如何在Linux中禁用和挂起休眠
    ubuntu18 virtualbox启动失败Kernel driver not installed (rc=-1908)
    C# Winform 多线程更新界面UI控件,解决界面卡顿问题(转)
    【573】LaTeX相关技巧
    程序计时函数
    王炸!!Spring 终于对 JVM 动手了…
    ThreadLocalRandom 是线程安全的吗?
    Spring Boot 应用可视化监控,一目了然!
  • 原文地址:https://www.cnblogs.com/yuyutianxia/p/8630559.html
Copyright © 2020-2023  润新知