SpringMVC之HandlerMapping

HandlerMapping的作用

HandlerMapping的主要作用是注冊(cè)Handler和獲取Handler延曙。

注冊(cè)Handler

HandleMapping注冊(cè)Handler發(fā)生在SpringMVC容器啟動(dòng)的過程中,在注冊(cè)Handler的同時(shí)也初始化攔截器田度。

BeanNameUrlHandlerMapping類圖

注冊(cè)Handle源碼走讀

//AbstractDetectingUrlHandlerMapping類中initApplicationContext()方法

public void initApplicationContext() throws ApplicationContextException { 
//初始化攔截器
super.initApplicationContext(); 
//注冊(cè)處理器
detectHandlers();
}

//AbstractHandlerMapping類中initApplicationContext()實(shí)現(xiàn)
protected void initApplicationContext() throws BeansException {  
extendInterceptors(this.interceptors);
detectMappedInterceptors(this.mappedInterceptors);  
initInterceptors();
}

//AbstractDetectingUrlHandlerMapping類中detectHandlers()實(shí)現(xiàn)
protected void detectHandlers() throws BeansException {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
        }
        String[] beanNames = (this.detectHandlersInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                getApplicationContext().getBeanNamesForType(Object.class));

        // Take any bean name that we can determine URLs for.
        for (String beanName : beanNames) {
            String[] urls = determineUrlsForHandler(beanName);
            if (!ObjectUtils.isEmpty(urls)) {
                // URL paths found: Let's consider it a handler.
                registerHandler(urls, beanName);
            }
            else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
                }
            }
        }
    }


//BeanNameUrlHandlerMapping類中determineUrlsForHandler()實(shí)現(xiàn)
//獲取以"/"開頭的beanName
protected String[] determineUrlsForHandler(String beanName) {
        List<String> urls = new ArrayList<String>();
        if (beanName.startsWith("/")) {
            urls.add(beanName);
        }
        String[] aliases = getApplicationContext().getAliases(beanName);
        for (String alias : aliases) {
            if (alias.startsWith("/")) {
                urls.add(alias);
            }
        }
        return StringUtils.toStringArray(urls);
    }
//AbstractUrlHandlerMapping類中實(shí)現(xiàn)
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {
        Assert.notNull(urlPaths, "URL path array must not be null");
        for (String urlPath : urlPaths) {
            //注冊(cè)處理器
            registerHandler(urlPath, beanName);
        }
    }
//AbstractUrlHandlerMapping類中registerHandler()實(shí)現(xiàn)

protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
        Assert.notNull(urlPath, "URL path must not be null");
        Assert.notNull(handler, "Handler object must not be null");
        Object resolvedHandler = handler;

        // Eagerly resolve handler if referencing singleton via name.
        if (!this.lazyInitHandlers && handler instanceof String) {
            String handlerName = (String) handler;
            if (getApplicationContext().isSingleton(handlerName)) {
                resolvedHandler = getApplicationContext().getBean(handlerName);
            }
        }
        //mappedHandler為保存處理器的map,key值為請(qǐng)求地址(/hello)
        Object mappedHandler = this.handlerMap.get(urlPath);
        if (mappedHandler != null) {
            if (mappedHandler != resolvedHandler) {
                throw new IllegalStateException(
                        "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +
                        "]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");
            }
        }
        else {
            if (urlPath.equals("/")) {
                if (logger.isInfoEnabled()) {
                    logger.info("Root mapping to " + getHandlerDescription(handler));
                }
                setRootHandler(resolvedHandler);
            }
            else if (urlPath.equals("/*")) {
                if (logger.isInfoEnabled()) {
                    logger.info("Default mapping to " + getHandlerDescription(handler));
                }
                setDefaultHandler(resolvedHandler);
            }
            else {
                this.handlerMap.put(urlPath, resolvedHandler);
                if (logger.isInfoEnabled()) {
                    logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
                }
            }
        }
    }

獲取Handler

獲取Handler其實(shí)獲取的是HandlerExecutionChain湾宙,HandlerExecutionChain包括一個(gè)Handler和一組攔截器樟氢。

獲取Handler的時(shí)序圖

獲取Handle源碼走讀

//AbstractHandlerMapping類中g(shù)etHandler()實(shí)現(xiàn)
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);
        }
        //獲取HandlerExecutionChain
        return getHandlerExecutionChain(handler, request);
    }

//AbstractHandlerMapping類中g(shù)etHandlerExecutionChain()實(shí)現(xiàn)
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
        //將<bean <property>>配置的攔截器添加到對(duì)應(yīng)的攔截器List中
        chain.addInterceptors(getAdaptedInterceptors());

        String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
        for (MappedInterceptor mappedInterceptor : this.mappedInterceptors) {
            if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                //<mvc:interceptors>都會(huì)被解析成MappedInterceptor
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }
        return chain;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市侠鳄,隨后出現(xiàn)的幾起案子埠啃,更是在濱河造成了極大的恐慌,老刑警劉巖伟恶,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件碴开,死亡現(xiàn)場離奇詭異,居然都是意外死亡博秫,警方通過查閱死者的電腦和手機(jī)潦牛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挡育,“玉大人巴碗,你說我怎么就攤上這事〖春” “怎么了橡淆?”我有些...
    開封第一講書人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蒿叠。 經(jīng)常有香客問我明垢,道長,這世上最難降的妖魔是什么市咽? 我笑而不...
    開封第一講書人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任痊银,我火速辦了婚禮,結(jié)果婚禮上施绎,老公的妹妹穿的比我還像新娘溯革。我一直安慰自己贞绳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開白布致稀。 她就那樣靜靜地躺著冈闭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪抖单。 梳的紋絲不亂的頭發(fā)上萎攒,一...
    開封第一講書人閱讀 49,784評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音矛绘,去河邊找鬼耍休。 笑死,一個(gè)胖子當(dāng)著我的面吹牛货矮,可吹牛的內(nèi)容都是我干的羊精。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼囚玫,長吁一口氣:“原來是場噩夢啊……” “哼喧锦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抓督,我...
    開封第一講書人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤燃少,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后本昏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體供汛,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年涌穆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雀久。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宿稀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赖捌,到底是詐尸還是另有隱情祝沸,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布越庇,位于F島的核電站罩锐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卤唉。R本人自食惡果不足惜涩惑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望桑驱。 院中可真熱鬧竭恬,春花似錦蹦掐、人聲如沸庵楷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽标沪。三九已至,卻和暖如春蔽莱,著一層夾襖步出監(jiān)牢的瞬間端仰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工盒揉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挡鞍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓预烙,卻偏偏與公主長得像墨微,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子扁掸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容