springMvc請(qǐng)求如何獲取相關(guān)HandlerMapping(四)


github原文鏈接 https://github.com/DespairYoke/java-advance。創(chuàng)作不易,請(qǐng)給個(gè)免費(fèi)的star,已表支持。

在Servlet如何關(guān)聯(lián)spring中,說(shuō)過(guò)當(dāng)請(qǐng)求來(lái)后會(huì)被轉(zhuǎn)發(fā)到springDispatcherServlet類中的doService方法。

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

轉(zhuǎn)發(fā)到doDispatch中

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

getHandler獲取相關(guān)

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;
}

可以看出,循環(huán)遍歷初始化時(shí)加載的handlerMappings。在初始化時(shí)加載是BeanNameUrlHandlerMappingRequestMappingHandlerMapping(不知道的,可以參考上篇文章spingMvc初始HandlerMapping)。
BeanNameUrlHandlerMapping不滿條件返回null,而RequestMappingHandlerMapping滿足條件,通過(guò)getHandler返回我們想要的HandlerExecutionChain

public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    Object handler = getHandlerInternal(request);

    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    return executionChain;
}

getHandlerExecutionChain可見(jiàn)是對(duì)handler和request的封裝,真正的處理還是如何獲取到這個(gè)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在初始化的時(shí)候放在了,mappingRegistry中,由上述代碼,可以看出是從mappingRegistry中,匹配請(qǐng)求,并返回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);
    }
}

果不其然是對(duì)我們的請(qǐng)求路徑進(jìn)行最佳匹配。
這樣我們就回去到初始化handlerMapping時(shí)生成的handlerMethod,為后續(xù)handlerAdapter做好參數(shù)準(zhǔn)備。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容