美文网首页
springMvc请求如何获取相关HandlerMapping(

springMvc请求如何获取相关HandlerMapping(

作者: 昨日已逝去 | 来源:发表于2019-05-24 10:28 被阅读0次

    github原文链接 https://github.com/DespairYoke/java-advance。创作不易,请给个免费的star,已表支持。

    在Servlet如何关联spring中,说过当请求来后会被转发到springDispatcherServlet类中的doService方法。

    @Override
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
       doDispatch(request, response);
    }
    

    转发到doDispatch中

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        mappedHandler = getHandler(processedRequest);
    }
    

    getHandler获取相关

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (MyHandlerMapping hm : this.handlerMappings) {
                if (logger.isTraceEnabled()) {
                    logger.trace(
                            "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
                }
                HandlerExecutionChain handler = hm.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }
    

    可以看出,循环遍历初始化时加载的handlerMappings。在初始化时加载是BeanNameUrlHandlerMappingRequestMappingHandlerMapping(不知道的,可以参考上篇文章spingMvc初始HandlerMapping)。
    BeanNameUrlHandlerMapping不满条件返回null,而RequestMappingHandlerMapping满足条件,通过getHandler返回我们想要的HandlerExecutionChain

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Object handler = getHandlerInternal(request);
    
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        return executionChain;
    }
    

    getHandlerExecutionChain可见是对handler和request的封装,真正的处理还是如何获取到这个handler
    具体代码写在了AbstractHandlerMethodMapping

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    
        this.mappingRegistry.acquireReadLock();
        try {
            HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
            }
            return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
        }
        finally {
            this.mappingRegistry.releaseReadLock();
        }
    }
    

    在前文分析中,handlerMethod在初始化的时候放在了,mappingRegistry中,由上述代码,可以看出是从mappingRegistry中,匹配请求,并返回handlerMethod。
    那我们看下lookupHandlerMethod方法吧。

    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<>();
        List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        if (matches.isEmpty()) {
            // 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));
            matches.sort(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);
        }
    }
    

    果不其然是对我们的请求路径进行最佳匹配
    这样我们就回去到初始化handlerMapping时生成的handlerMethod,为后续handlerAdapter做好参数准备。

    相关文章

      网友评论

          本文标题:springMvc请求如何获取相关HandlerMapping(

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