本節書摘來自異步社群《spring 3.0就這麼簡單》一書中的第1章,第1.6節,作者: 陳雄華 , 林開雄著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視
業務層和持久層的開發任務已經完成,該是為程式提供界面的時候了。struts mvc架構由于搶盡天時地利,成為當下最流行的展現層架構。但也有很多人認為spring mvc相比較于struts更簡單、更強大、更優雅。此外,由于spring mvc出自于spring之手,是以和spring容器沒有任何不相容性,顯得天衣無縫。
spring 1.5新增了基于注解的mvc,而且spring 3.1還提供了rest風格的mvc,spring mvc已經變得輕便、強大、易用。我們将會在本書的第8章中學習spring mvc的詳細内容。
1.6.1 配置spring mvc架構
首先需要對web.xml檔案進行配置,以便web容器啟動時能夠自動啟動spring容器,如代碼清單1-13所示。
代碼清單1-13 自動啟動spring容器的配置
首先,通過web容器上下文參數指定spring配置檔案的位址,如①所示。多個配置檔案可用逗号或空格分隔,建議采用逗号分隔的方式。在②處指定spring所提供的contextloaderlistener的web容器監聽器,該監聽器在web容器啟動時自動運作,它會根據contextconfiglocation web容器參數擷取spring配置檔案,并啟動spring容器。注意需要将log4j.propertis日志配置檔案放置在類路徑下,以便日志引擎自動生效。
接下來,需要配置spring mvc相關的資訊,spring mvc像struts一樣,也通過一個servlet截獲url請求,然後再進行相關的處理,如代碼清單1-14所示。
代碼清單1-14 spring mvc位址映射
在①處聲明了一個servlet,spring mvc也擁有一個spring配置檔案(稍後會涉及),該配置檔案的檔案名和此處定義的servlet名有一個契約:即采用-servlet.xml的形式。在這裡,因為servlet名為viewspace,是以在/web-inf目錄下必須提供一個viewspace- servlet.xml的spring mvc配置檔案,但這個配置檔案無須通過web.xml的contextconfiglocation上下文參數進行聲明,因為spring mvc的servlet會自動将viewspace -servlet.xml和spring其他的配置檔案進行拼裝。
在②處對這個servlet的url路徑映射進行定義,在這裡讓所有以.html為字尾的url都能被viewspace servlet截獲,進而轉由spring mvc架構進行處理。我們知道,在struts架構中,一般将url字尾配置為.do,在webwork中一般配置為.action,其實,架構本身和url模式沒有任何關系,使用者大可使用喜歡的任何字尾。使用.html字尾,一方面,使用者不能通過url直接知道開發者采用了何種服務端技術;另一方面,.html是靜态網頁的字尾,可以騙過搜尋引擎,增加被收錄的機率,是以推薦采用這種字尾。對于那些真正的無須任何動态處理的靜态網頁,則可以使用.htm字尾加以區分,以避免被架構截獲。
請求被spring mvc截獲後,首先根據請求的url查找到目标的處理控制器,并将請求參數封裝成一個“指令”對象一起傳給控制器處理,控制器調用spring容器中的業務bean完成業務處理工作并傳回結果視圖。
1.6.2 處理登入請求
pojo控制器類
首先要編寫的是logincontroller,它負責處理登入請求,完成登入業務,并根據登入成功與否轉向歡迎頁面或失敗頁面,如代碼清單1-15所示。
代碼清單1-15 logincontroller.java
在①處通過spring mvc的@controller注解可以将任何一個pojo的類标注為spring mvc的控制器,處理http的請求。當然标注了@controller的類首先會是一個bean,是以可以使用@autowired進行bean的注入。
一個控制器可以擁有多個對應不同http請求路徑的處理方法,通過@requestmapping指定方法如何映射請求路徑,如②和③所示。
請求的參數會根據參數名稱預設契約自動綁定到響應方法的入參中,在③處的logincheck(httpservletrequest request,logincommand logincommand)方法中,請求參數會按名稱比對綁定到logincommand的入參中。
請求響應方法可以傳回一個modelandview,或直接傳回一個字元串,spring mvc會解析之并轉向目标響應頁面。
modelandview對象既包括了視圖資訊又包括了視圖渲染所需的模型資料資訊,在這裡使用者僅需要了解它代表一個視圖就可以了,在後面的内容中,讀者将了解到spring mvc如何根據這個對象轉向真正的頁面。
前面使用到的logincommand對象是一個pojo,它沒有繼承于特定的父類或實作特定的接口。logincommand類僅包括使用者/密碼這兩個屬性(和請求的使用者/密碼參數名稱一樣),如代碼清單1-16所示。
代碼清單1-16 logincommand
spring mvc配置檔案
編寫好logincommand後,需要在viewspace-servlet.xml中聲明該控制器,掃描web路徑,指定spring mvc的視圖解析器,如代碼清單1-17所示。
代碼清單1-17 viewspace-servlet.xml
modelandview的解析配置
在代碼清單1-15 的③處,控制器根據登入處理結果分别傳回 modelandview ("login", "error", "使用者名或密碼錯誤。")和modelandview("main")。modelandview的第一個參數代表視圖的邏輯名,第二個和第三個參數分别為資料模型名稱和資料模型對象,資料模型對象将以資料模型名稱為參數名放置到request的屬性中。
spring mvc如何将視圖邏輯名解析為具體的視圖頁面呢?解決的思路也和上面的方法類似,需要在viewspace-servlet.xml中提供一個定義解析規則的bean,如代碼清單1-18所示。
代碼清單1-18 viewspace-servlet.xml視圖解析規則
spring mvc為視圖名到具體視圖的映射提供了許多可供選擇的方法。在這裡,使用了internalresourceviewresolver,它通過為視圖邏輯名添加前字尾的方式進行解析。如視圖邏輯名“login”将解析為/web-inf/jsp/login.jsp;視圖邏輯名“main”将解析為/web-inf/jsp/main.jsp。
1.6.3 jsp視圖頁面
景區網站登入子產品共包括兩個jsp頁面,分别是登入頁面login.jsp和管理首頁面main.jsp,下面将完成這兩個頁面的開發工作。
登入頁面login.jsp
登入頁面login.jsp的代碼如代碼清單1-19所示。
代碼清單1-19 login.jsp
login.jsp頁面既作為登入頁面又作為登入失敗後的響應頁面。是以在 ①處使用jstl标簽對登入錯誤傳回的資訊進行處理。jstl标簽中引用了error變量,這個變量正是logincontroller中傳回的modelandview("login", "error", "使用者名或密碼錯誤。") 對象所聲明的error參數。
login.jsp的登入表單送出到/logincontroller.html,如②所示。的jstl标簽會在url前自動加上應用程式部署根目錄,假設應用部署在網站的viewspace目錄下,标簽将輸出/viewspace/logincontroller.html。通過标簽很好地解決了開發和應用部署目錄不一緻的問題。
由于 login.jsp 放置在 web-inf/jsp 目錄下,無法直接通過 url 進行調用,它由logincontroller 控制類中标注了@requestmapping(value = "/login.html")的loginpage()進行轉發,見代碼清單1-15。
景區管理首頁面main.jsp
登入成功的歡迎頁面很簡單,僅使用jstl标簽顯示一條歡迎資訊即可,如代碼清單1-20所示。
代碼清單1-20 main.jsp
①處通路session域中的user對象,顯示使用者名和積分資訊。這樣,就完成了執行個體所有的開發任務。