spring mvc: view resolvers

調(diào)用過程

org.springframework.web.servler.ViewResolver 用來決定應(yīng)該用哪個(gè)org.springframework.web.servlet.View的實(shí)例來創(chuàng)建并發(fā)送給客戶端的response。

Dispatcherservlet 收到一個(gè)由request handler (通常為Controller中處理用戶請求的方法)處理完用戶請求而返回的值之后,在DispatcherServlet#doDispatch中調(diào)用了processDispatchResult


/**

* Handle the result of handler selection and handler invocation, which is

* either a ModelAndView or an Exception to be resolved to a ModelAndView.

*/

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
    HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception

之后的call hierarchy如下:

DispatcherServlet call hierarchy.png

DispatcherServlet#resolveViewName中锌历,遍歷當(dāng)前的所有ViewResolver,調(diào)用其resolveViewName方法:

protected View resolveViewName(String viewName, Map<String, Object> model, Locale locale,
            HttpServletRequest request) throws Exception {

        for (ViewResolver viewResolver : this.viewResolvers) {
            View view = viewResolver.resolveViewName(viewName, locale);
            if (view != null) {
                return view;
            }
        }
        return null;
    }

因此试幽,ViewResolver#resolveViewName的語義就是:對(duì)于給定的viewName(由Controller返回),若是能夠處理卦碾,則返回對(duì)應(yīng)的View的實(shí)例铺坞,否則返回null,由下一個(gè)ViewResolver 處理蔗坯。

找到合適的view之后康震,即調(diào)用其render方法燎含,將從request handler 返回的數(shù)據(jù)(在spring mvc中稱為model)宾濒,進(jìn)行數(shù)據(jù)綁定并對(duì)客戶端進(jìn)行相應(yīng):

//DispatcherServlet#render(...):
    view.render(mv.getModelInternal(), request, response);

詳情可參考:SpringMVC#mvc-viewresolver

注冊ViewResolver

從上面的代碼可以看到,所有的ViewResolver保存在DispatcherServlet#viewResolvers中屏箍,而viewResolvers這個(gè)列表的值從context里面绘梦、與獲取其他bean一樣、來獲雀翱:

private void initViewResolvers(ApplicationContext context) {
        this.viewResolvers = null;

        if (this.detectAllViewResolvers) {
            // Find all ViewResolvers in the ApplicationContext, including ancestor contexts.
            Map<String, ViewResolver> matchingBeans =
                                        //從context中獲取類型為ViewResolver的bean
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.viewResolvers = new ArrayList<ViewResolver>(matchingBeans.values());
                // We keep ViewResolvers in sorted order.
                OrderComparator.sort(this.viewResolvers);
            }
        }
        else {
            try {
                                //從context中獲取類型為ViewResolver的bean
                ViewResolver vr = context.getBean(VIEW_RESOLVER_BEAN_NAME, ViewResolver.class);
                this.viewResolvers = Collections.singletonList(vr);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default ViewResolver later.
            }
        }

        // Ensure we have at least one ViewResolver, by registering
        // a default ViewResolver if no other resolvers are found.
        if (this.viewResolvers == null) {
            this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
            if (logger.isDebugEnabled()) {
                logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
            }
        }
    }

這里可以看到卸奉,ViewResolver是有順序的(可以通過@order 來控制bean的順序),若是多個(gè)ViewResolver可以處理同樣的viewName颖御,那么排在后面的ViewResolver將不起作用榄棵。

View#render

View#render 方法負(fù)責(zé)輸出最終的HTTP response.
其接收三個(gè)參數(shù):

  • Map<String, ?> model: 從Controller那邊獲得的跟業(yè)務(wù)相關(guān)的數(shù)據(jù)
  • HttpServletRequest request: ?當(dāng)前的HTTP request
  • HttpServletResponse response:當(dāng)前正在構(gòu)建的HTTP response,可將內(nèi)容寫入并發(fā)送給客戶端

SpringMVC 提供了許多默認(rèn)的View的實(shí)現(xiàn)類,可以滿足大部分開發(fā)的需求——?如果完全使用spring框架的話疹鳄。如果你打算自己控制render過程拧略,有自己的一套模板機(jī)制,那么就可以創(chuàng)建自定義View的實(shí)現(xiàn)類了瘪弓。

總結(jié)

這里簡單講述了當(dāng)一個(gè)request被處理完成之后垫蛆,將處理結(jié)果轉(zhuǎn)化為response的過程中涉及到的類。大致流程如下:

  1. 接收到客戶端的request腺怯,根據(jù)request查找對(duì)應(yīng)的request handler(一般為Controller中的方法)
  2. request handler處理完之后返回袱饭,spring將處理結(jié)果包裝為ModelAndView(將在其他文章中介紹這個(gè)過程)
  3. DispatcherServlet 根據(jù)ModelAndView的view name來選擇對(duì)應(yīng)的View:遍歷ViewResolver,ViewResolver根據(jù)view name來返回對(duì)應(yīng)的View的實(shí)現(xiàn)類(或返回null并交給下一個(gè)ViewResolver)
  4. 調(diào)用View#render來生成最終的response呛占,在View的實(shí)現(xiàn)類中實(shí)現(xiàn)最終渲染并輸出到response的過程虑乖。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市晾虑,隨后出現(xiàn)的幾起案子决左,更是在濱河造成了極大的恐慌,老刑警劉巖走贪,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件佛猛,死亡現(xiàn)場離奇詭異,居然都是意外死亡坠狡,警方通過查閱死者的電腦和手機(jī)继找,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逃沿,“玉大人婴渡,你說我怎么就攤上這事】粒” “怎么了边臼?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長假消。 經(jīng)常有香客問我柠并,道長,這世上最難降的妖魔是什么富拗? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任臼予,我火速辦了婚禮,結(jié)果婚禮上啃沪,老公的妹妹穿的比我還像新娘粘拾。我一直安慰自己,他們只是感情好创千,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布缰雇。 她就那樣靜靜地躺著入偷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪械哟。 梳的紋絲不亂的頭發(fā)上盯串,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音戒良,去河邊找鬼体捏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糯崎,可吹牛的內(nèi)容都是我干的几缭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼沃呢,長吁一口氣:“原來是場噩夢啊……” “哼年栓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起薄霜,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤某抓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后惰瓜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體否副,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年崎坊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了备禀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡奈揍,死狀恐怖曲尸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情男翰,我是刑警寧澤另患,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站蛾绎,受9級(jí)特大地震影響昆箕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜秘通,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一为严、第九天 我趴在偏房一處隱蔽的房頂上張望敛熬。 院中可真熱鬧肺稀,春花似錦、人聲如沸应民。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至繁仁,卻和暖如春涉馅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背黄虱。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工稚矿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捻浦。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓晤揣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親朱灿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昧识,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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