2010-10-22

了解什麼是 Spring Web MVC

 

循前例,我還是自NetBeans的官網,取用如下之教學指引,以為自修研習用教材,開始了我對 Spring 的初步探究--「Spring是什麼東東啊?」

Introduction to Spring Web MVC

 

文件導讀

 

上述教材研讀及實作完畢後,摘錄心得如下,當成是自己的讀書筆記,也希望對需要了解Spring的朋友,能提供那麼一點助益。

根據教材內容的說明,可知此處所探討的只是Spring Web MVC的運作原理,可能這教材裡的說明,只是讓我們了解在 Spring Framework 下,Controller、View、Model 三種類別是如何協同運作,還不能算是給了 Spring Framework 的總體概述。

此教材主要的章節架構如下:

  • Setting up a New Project with Spring Web MVC Support
  • Overview of the Application
  • Implementing a Service
  • Implementing the Controller and Model
  • Implementing the Views
  •  

    對於以上之章節,可將「Setting up a New Project with Spring Web MVC Support」章節視為本文章的第一篇。

    至於「Overview of the Application」到「Implementing the Views」的章節,則屬於本文章的第二篇。

     

    第一篇內容摘要

     

    認識DispatcherServlet

    指導NetBeans的使用者,如何透過專案建置精靈,建立一個支援Spring Framework 3.0的NetBeans專案資料夾。

    完成了上述專案建置工作後,即可依據教材中的指示,體驗一下,Spring有什麼樣的特性。

    第一件要了解的事,偉大的DispatcherServle從web.xml檔案內容的描述,可以發覺在Spring Framework有著一個神奇的Servlet,它的名字叫DispatcherServlet。從以下自web.xml節錄的內容,可以看出,只要有使用者對伺服器發出讀取.htm檔案的Request時,往後的處理工作,皆由偉大的DispatcherServlet來負責操盤。

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

     

    第二件要了解的事,網站的首頁是如何被找到的:別懷疑,同時,我也沒有侮辱您的專業。本來網站的首頁用腳指想也知,不是index.hm;就是index.jsp檔案。

    可是,從下列web.xml的設定,可知以上皆非,預設為redirect.jsp。

    <welcome-file-list>
        <welcome-file>redirect.jsp</welcome-file>
    </welcome-file-list>

     

    當redirect.jsp檔案打開後,可以看到如下的內容:

    <% response.sendRedirect(“index.htm”); %>

     

    結果.....,才知,這網站的首頁仍由index.htm擔綱。但是.....,在Web Pages之下,根本沒有index.htm這個檔案啊!

    image

     

    可是......,這個網站在執行時候,明明可以看到如下的網頁內容,同時,在Web瀏覽器中的URL網址,也出現了index.htm啊!

    image

     

    如果你不死心到處找,可以在路徑「Web Pages\WEB-INF\jsp\」處,找到一個最最最標準的首頁檔案index.jsp。

    image

     

    把這個網頁檔案打開後,可以查覺其內容,跟前述網站首頁內容是相同的。

    image

     

    啊......!現在是怎麼回事?怎麼會這樣?

    謎題的解答dispatcher-servlet.xml

    其實在網站所見的首頁內容,其來源正是出自index.jsp。但是,從要進入index.htm網頁,卻是顯示index.jsp的「無中生有」過程,是怎麼回事?以下我們來一一分解詳述:

    由於redirect.jsp檔案,說要將網頁轉到index.htm。所以,根據web.xml的設定,只要是*.htm檔案,通通交由DispatcherServlet負責。

    當DispatcherServlet這個血統純正的Java Servlet,聽說有人要求瀏覽index.htm網頁的內容時,便會查閱dispatcher-servlet.xml檔案中的設定,並嚴格遵循當中的規矩,照章行事。

    當DispatcherServlet讀到 id 為 urlMappingbean 設定,它知道若有人要看 "/index.htm" 的檔案時,它要以 indexController 頂替 。

    於是DispatcherServlet,再到dispatcher-servlet.xml檔案尋找 name 為 indexController 的 bean 。結果,自 p:viewName 的屬性查出,indexController 要找主要檔名叫 index 的檔案。

    最後,DispatcherServlet藉由 id 為 viewResolver 的 bean ,其中的 p:prefixp:suffix,查出主檔名為 index 的檔案,要到路徑為「/WEB-INF/jsp/」處尋找;找到這個檔案後,再配以 jsp 的副檔名。

    image

    經過上述無中生有的過程,DispatcherServlet終於完成解讀,知道有人要看 index.htm 時,就給它 /WEB-INF/jsp/index.jsp 的檔案。

    瞭了嗎?!

    只是.....,不過是要喝杯牛奶,幹啥要自行蓋個牧場來養牛,生產年奶。為什麼要把事情搞得這麼大,如此複雜?別問我,我那知!

     

    第二篇內容摘要

     

    Spring Web MVC運作架構

    這篇教材真正的重點,從此處開始。它用了如下的應用例子,說明在 Spring Framework 下MVC是怎樣運作的。

    假設您的網站要提供一個功能,這功能會透過一個網頁向使用者詢問其姓名。當使用者輸入了姓名之後,則會用另一個網頁向使用者說聲嗨!

    有了上述初步的功能需求後,在設計上我們需使用 2 個 View,以 nameView.jsp 網頁來向使用者詢問,要求輸入姓名。使用者輸入的姓名,經過系統的處理後,再透過名為helloView.jsp 的網頁,向使用者 Say Hello。且此功能的啟動執行點,設計成「當使用者瀏覽 /hello.htm 網頁便執行」。

    在 Spring Web MVC 的設計模式下,View (可以直接想成網頁) 之間的切換係由 Controller 的類別 (亦即 MVC 中的 Control) 來控制。所以,依據上述的設計規格,我們需要有個名為 helloController ,屬 Controller 的類別,以便有人想瀏覽 /hello.htm 網頁時,便提供 nameView.jsp 給他;待取得使用者輸入的姓名後,則再顯示 helloView.jsp 網頁給使用者。

    關於使用者在 nameView.jsp 輸入的資料,可以使用一名為 Name ,屬 Model 的類別,用以接收輸入的結果。

    至於從使用者接收到的資料,該做什麼處理,完成什麼樣的輸出,這活就由屬 Service (亦即一般所謂之 Business Logic) 的類別來幹。因此,根據設計,需要一名為 helloService 的類別,以便能將使用者輸入的姓名進行加工處理。

    綜合上述,整個功能的運作過程,所需使用的網頁及類別,其設計可以用以下,UML 的穩建圖來表示:

    image

    上圖的 dispatcher-servlet.xml ,用於表示 helloController 類別須在這個檔案內做登記。同樣,helloService 類別的存在,亦須記錄相關設定在 applicationContext.xml 檔案之中。 如此,helloController 類別才能正常運作。甚至說得更白點,非得這樣做,Web Container 才有辦法,遇到有人要瀏覽 /hello.htm 時, 知道該怎麼做。

    根據上述設計,需要撰寫製作的網頁及各個類別(class),在專案資料夾的放置處,則如下圖所示:

    image

     

    研習須細讀重點

    有了上述 Spring Web MVC 在架構上的認知後,請再加強下列事項的研習。

    HelloController.java 的建構子:細讀其程式碼,了解 Controller 啟動後,怎麼知道該先顯示那個網頁,然後又該顯示那個網頁。網頁輸入的資料,要用那個類別去接收;當靜態的類別(class)變成可執行的物件(object)時,要用什麼作為變數名稱

    HelloController.java 的 onSubmit 方法:當第一個網頁完成輸入 (nameView.jsp),onSubmit 事件發生後,Controller 要如何接收第一個網頁所傳來的輸入;然後又如何透過 Service ,對輸入的資料進行加工,完成輸出;最後又如何將加工後輸出,餵給第二個網頁 (helloView.jsp)。

    nameView.jsp網頁:研究網頁中,屬 Spring 專用的 Tag 如何自 Controller 接收由 Name 類別所產生的 name 物件。而使用者的輸入,如何以 Spring Tag ,將之存入 name 物件中的 value 屬性。

    helloView.jsp網頁:研究網頁中欲輸出的內容,如何能透過 EL 表示式  ${helloMessage}  顯示出來。EL 表示中的變數 helloMessage , 與 HelloController 類別中的 onSubmit 方法,有什麼互為因果的關係。

     

    總結

     

    哇!好棒!終於寫完了。這篇文章花了我 5 小時,才搞定。可是這篇文章的內容,我花了一天讀完,又再花了三天反覆思考 Spring Web MVC 運作的架構;網頁、Controller類別、Service類別、Model類別各個之間的互動關係;三個設定檔 web.xml 、 dispatcher-servlet.xml 、applicationContext.xml 各個的作用。

    這個研習過程,對我而言有些吃力。因此,希望我這研究心得報告,可以幫大家減少一些學習過程的障礙。

    9 則留言:

    匿名 提到...

    謝謝分享~

    Taken 提到...

    你寫的太棒了~非常清楚易了解,對初學者來說,茫茫網海文章,大家都先從"使用者應該原本就知道某些東西"開始,而你卻把gap變小了!

    莊佳宏 提到...
    作者已經移除這則留言。
    莊佳宏 提到...

    好文一篇
    感謝大大的用心^^
    給你個大拇指@

    ChengWei 提到...

    感謝你的用心
    等我學出心得了也要分享文章給大家

    匿名 提到...

    剛好也在學習這個
    感謝作者的用心

    Danielkimo 提到...

    請問有M V C的java source code嗎

    nfsnfs 提到...

    好文,減少我不少時間!!多謝 :)

    kenny 提到...

    你寫得比原文還好呢!

    張貼留言