1. 程式人生 > >Spring MVC+mybatis 專案入門:旅遊網(二) dispatcher與controller與Spring MVC

Spring MVC+mybatis 專案入門:旅遊網(二) dispatcher與controller與Spring MVC

MVC模式

        既然在使用Spring MVC,那麼當然要了解什麼是MVC模式。

MVC全名是Model View Controller,是模型(model)-檢視(view)-控制器(controller)的縮寫,一種軟體設計典範,用一種業務邏輯、資料、介面顯示分離的方法組織程式碼,將業務邏輯聚集到一個部件裡面,在改進和個性化定製介面及使用者互動的同時,不需要重新編寫業務邏輯。                                                                                                                         ——來自百度百科

MVC模式的各種圖網上也有很多了,這裡就不說了,說明一下我理解的Spring MVC。

假設這個是祖國手辦拼裝場。肥宅對前臺小姐姐說:給我一個蕾姆!前臺小姐姐說ok,回頭跟手辦安裝員說,給我一個蕾姆!手辦安裝員說ok,然後就需要從倉庫中拿到蕾姆的各個元件。倉庫管理員直接在倉庫裡面找,找到以後全部給手辦安裝員。手辦安裝員開始拼,拼好以後給前臺小姐姐,前臺小姐姐在給肥宅。

        這就是簡單的一個邏輯,而也使用了MVC的思想。肥宅只用掏錢就行了,而前臺小姐姐只負責傳話,跟遞手辦。手辦安裝員哪裡都不用去,只用安裝手辦就可以了,而倉庫管理員負責在倉庫裡面手機零件,然後再給手辦安裝員。

        我們可以去理解,前臺小姐姐就是V,或者說是瀏覽器,負責接收肥宅的需求並且反饋給手辦安裝員。手辦安裝員就是C,只負責吧手辦拼出來。而M就是手辦。剛開始就是一堆零件,在被C拼好以後運送到V,然後肥宅就能看見了。

        如果需要擴充套件一下,例如,不同的手辦安裝員精通某種型別的手辦,因為肥宅的要求很高的,需要高達類的,就必須由高達安裝員安裝,而其他安裝員不能安裝。那麼就需要多個C,同樣,產品多了,就代表M多了。而前臺小姐姐數量是不變的,增加前臺實際上是多執行緒。

        這樣,我們的MVC工廠就略顯混亂,1個V,多個C,多個M。而不同的零件可能換放在不同的倉庫裡面。此時,我們可以升級為Spring MVC了。Spring MVC提供了dispatcher,中文是排程員。當然就是負責中間排程的人員。dispatcher放在前臺小姐姐和手辦安裝員中間。而對於倉庫的管理我們交給mybatis。獲得了這樣:

前臺小姐姐還是很輕鬆的,傳話就行了,具體這些話傳給誰,全部由dispatcher來管理,dispatcher可以將需求傳遞給正確的安裝員。安裝員只用告訴mybatis需要什麼就行了,mybatis就會自動找到具體的位置來把零件給安裝員。

        這也是博主理解的Spring MVC。而這次專案也會基於此。

dispatcher的配置

        dispatcher是一個servlet。在沒有框架的時候,利用jsp+servlet+javabean來完成MVC模式,我們就需要自己編寫dispatcher。而現在Spring MVC已經封裝好了dispatcher,我們直接使用就可以了。不過其本質還是servlet,所以我們應該在web.xml裡面對其進行配置,宣告我們要使用這個servlet。

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

學過servlet,這裡就很能看懂了。正因為如此,在標籤<servlet-mapping>裡面的<url-pattern>反而有些疑惑。為什麼是“/”。其實就是字面意思,所有的請求全部對映到dispatcher。

        因為dispatcher也是前置控制器,就是所有的請求全部經過dispatcher,而且統一由dispatcher進行排程。所以,Spring MVC的核心就是dispatcher。而dispatcher的具體功能,包括IoC等全部被封裝好了,我們根本不用考慮這些具體的實現,用就完事了。當然,關於IoC等內容太多了,文章就不多寫,這個還是需要自己下去查,因為這些比較核心,也有點不太入門。

        現在,我們有了dispatcher,在web.xml裡面的宣告,Spring MVC就能知道:我們使用了dispatcher,並且對於所有的對映統統交給dispatcher來管理。那麼我們當然也需要對dispatcher進行一些設定,配置dispatcher。

        dispatcher的配置檔案也是xml檔案,但是命名要求是固定的。web.xml中,<servlet-name>是什麼,我們的xml檔案命名就必須一致,例如有:<servlet-name>abcde</servlet-name>,那麼我們dispatcher配置檔案命名應該為:abcde-servlet.xml。這個一定要一致。idea在建立專案的時候已經預設給建好了,很爽啊。

        因為dispatcher是Spring MVC相當核心的部分,所以網上很多人也稱其為Spring MVC配置檔案。所以理解這個名詞指的是什麼就行,就是指dispatcher配置檔案。

        裡面具體配置什麼,現在先不說,但是檔案一定要建立好。

宣告controller

        controller也是非常重要的,算是整個專案的核心部分。在Spring MVC2.0之前,我們都需要繼承Controller類,通過重寫一部分方法來完成controller的建立。這樣其實非常麻煩,並且一個類只能實現一個請求。專案稍微大一點就非常冗雜。而現在,我們可以使用註解方式,來很簡單地完成操作。此時,我們可以開始專案了。

        首先先來完成首頁吧。我們想要進入首頁,在邏輯上應該如何完成?假設我們有一個請求:getIndex.action。這表示我們想要獲得一個首頁。此時,我們需要寫controller類:

package me.iwts.controller;

import me.iwts.tools.ViewTool;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ViewController {
    // 首頁
    @RequestMapping("getIndex.action")
    public ModelAndView getIndex(){
        return new ModelAndView("/WEB-INF/view/index-test.jsp");
    }
}

我們對整個類的上面宣告@Controller。這說明,這個類就是我們需要的controller,而其中的方法是針對具體的請求而進行具體的操作,用註解@RequestMapping()來表示,裡面就是具體的操作。

        可以看到,@ReuqestMapping()註解是註釋了具體的方法,說明這個方法處理了對應的請求。而其返回值ModelAndView就是指模型和檢視。這個ModelAndView類可以自動封裝檢視和模型,並且返回到前端。這裡我們new了一個ModelAndView類,而其內容,則是一個檢視在伺服器上的位置。這樣我們就能返回這個檢視了。

dispatcher如何找到controller

        上面,配置好了dispatcher,完成了controller。問題是我們應該如何讓dispatcher找到controller。僅僅是一個@Controller註解就可以了麼?當然是不對的,這裡簡單介紹一下掃描器。

        dispatcher掃描器,聲明瞭一個域,dispatcher在尋找一些資源的時候,就去利用掃描器掃描。例如dispatcher獲取了一個請求,就需要利用掃描器先掃描一下,如果發現這個類有@Controller註解,ok,就再去裡面搜尋其方法,如果碰見@RequestMapping宣告跟請求一樣,就執行方法體。

        當然,這裡就理所當然需要在dispatcher裡面配置,程式碼如下:

<context:component-scan base-package="me.iwts.controller" />

這樣,就說明了去這個包下面掃描。

發起請求

        現在,小姐姐跟dispatcher就都就位了,就差肥宅了。這個問題有點蛋疼,獲取首頁這個請求由誰來發出。如果是一個真實的網站,我們需要訪問其IP地址,然後就出來了首頁。而tomcat的話,我們訪問localhost:8080,就會預設跳轉到規定的首頁(這個需要自己配置tomcat的xml)預設就是WEB-INF下的index.jsp。那麼我們在這裡面呼叫就好了啊:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>$Title$</title>
    </head>
    <body>
        <jsp:forward page="/getIndex.action" />
    </body>
</html>

利用forward轉發,傳送一個請求,然後dispatcher捕獲這個請求。然後依靠掃描器去controller包下面搜尋,找到了具體的方法,然後就開始執行,同時返回了jsp頁面。

利用view resolver來簡化對檢視的操作

        如果按照上面的寫法,在返回view的時候,寫的是一大串字串,很麻煩其實。而我們可以通過配置view resolver來簡化這個操作。這個是一個類,在Spring MVC規範中,稱這些類為bean,我們現在需要這個bean,來完成對檢視的處理。我們將所有的檢視全部放在/WEB-INF/view/資料夾下,而我們的檢視全部是jsp程式碼。

        而view resolver其實就是宣告一次拼接,字首是什麼字尾是什麼,處理以後,我們在程式碼裡面就可以只寫view的名字就好了。而view resolver在dispatcher裡面的配置如下:

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
    </bean>

prefix就是指字首,suffix就是指字尾,這樣,controller裡面我們就可化簡程式碼:

return new ModelAndView("index-test");

其實這樣還是不好。我們需要檢視的地方非常多,如果改一個檔案的名字,就要改非常多。那麼我們就可以寫一個工具類,專門來控制這些檢視的名字。例如ViewTool類:

package me.iwts.tools;

public class ViewTool {
    public static final String INDEX = "index-test";
    public static final String LOGIN = "login-test";
    public static final String PROFILE = "profile-test";
    public static final String REGISTER = "register-test";
    public static final String REGISTER_SUCCESS = "register_success-test";
    public static final String ADMIN_CONSOLE = "admin_console-test";
    public static final String DETAILS = "details-test";
    public static final String ADD_SUCCESS = "add_success-test";
    public static final String TOURISM_CONSOLE = "tourism_console-test";
    public static final String MY_ORDER = "my_order-test";
}

這些靜態變數,聲明瞭具體的檢視名字,這樣controller也能化簡為:

package me.iwts.controller;

import me.iwts.tools.ViewTool;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class ViewController {
    // 首頁
    @RequestMapping("getIndex.action")
    public ModelAndView getIndex(){
        return new ModelAndView(ViewTool.INDEX);
    }
}

很爽,這樣jsp的名字隨便改,我們只用在ViewTool類裡面改一次就好了。

下一章連結

未完待續——缺哥哥里什麼時候出22啊?