javascript
《Spring 3.0就这么简单》——1.6 展现层
本節書摘來自異步社區《Spring 3.0就這么簡單》一書中的第1章,第1.6節,作者: 陳雄華 , 林開雄著,更多章節內容可以訪問云棲社區“異步社區”公眾號查看
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容器的配置
<?xml version="1.0" encoding="UTF-8"?> <web-app version="1.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"><!--①從類路徑下加載Spring配置文件,classpath關鍵字特指在類路徑下加載_--> <context-param><param-name>contextConfigLocation</param-name><param-value>classpath:applicationContext.xml</param-value></context-param> _<!--②負責啟動Spring容器的監聽器,它將引用①處的上下文參數獲得Spring配置文件地址-->_<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>… </web-app>首先,通過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地址映射
… <!-- Spring MVC的主控Servlet --> <servlet> ①<servlet-name>viewspace</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><load-on-startup>2</load-on-startup></servlet> <!-- Spring MVC處理的URL --><servlet-mapping>② <servlet-name>viewspace</servlet-name><url-pattern>*.html</url-pattern> </servlet-mapping>在①處聲明了一個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
package com.smart.web; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.smart.domain.User; import com.smart.service.UserService; @Controller① @RequestMapping(value = "/admin" public class LoginController{@Autowiredprivate UserService userService;@RequestMapping(value = "/login.html")②public String loginPage(){return "login";}@RequestMapping(value = "/loginCheck.html")③public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(),loginCommand.getPassword());if (!isValidUser) {return new ModelAndView("login", "error", "用戶名或密碼錯誤。");} else {User user = userService.findUserByUserName(loginCommand.getUserName());user.setLastIp(request.getRemoteAddr());user.setLastVisit(new Date());userService.loginSuccess(user);request.getSession().setAttribute("user", user);return new ModelAndView("main");}} }在①處通過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
package com.smart.web; public class LoginCommand {private String userName;private String password;//省略get/setter方法 }Spring MVC配置文件
編寫好LoginCommand后,需要在viewspace-servlet.xml中聲明該控制器,掃描Web路徑,指定Spring MVC的視圖解析器,如代碼清單1-17所示。
代碼清單1-17 viewspace-servlet.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework. org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.1.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"><!--①掃描web包,應用Spring的注解 --><context:component-scan base-package="com.smart.web"/><!--②配置視圖解析器,將ModelAndView及字符串解析為具體的頁面 --><beanclass="org.springframework.web.servlet.view.InternalResourceViewResolver"p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/"p:suffix=".jsp" /> </beans>ModelAndView的解析配置
在代碼清單1-15 的③處,控制器根據登錄處理結果分別返回 ModelAndView ("login", "error", "用戶名或密碼錯誤。")和ModelAndView("main")。ModelAndView的第一個參數代表視圖的邏輯名,第二個和第三個參數分別為數據模型名稱和數據模型對象,數據模型對象將以數據模型名稱為參數名放置到request的屬性中。
Spring MVC如何將視圖邏輯名解析為具體的視圖頁面呢?解決的思路也和上面的方法類似,需要在viewspace-servlet.xml中提供一個定義解析規則的Bean,如代碼清單1-18所示。
代碼清單1-18 viewspace-servlet.xml視圖解析規則
… <!--通過prefix指定在視圖名前所添加的前綴,通過suffix指定在視圖名后添加的后綴--> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/jsp/"p:suffix=".jsp" />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
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <html><head><title>景區網站登錄</title></head><body><c:if test="${!empty error}"> ①<font color="red"><c:out value="${error}" /></font></c:if> <form action="<c:url value="/ loginCheck.html "/>" method= "post">②用戶名:<input type="text" name="userName"><br>密 碼:<input type="password" name="password"><br><input type="submit" value="登錄" /><input type="reset" value="重置" /></form></body> </html>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
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>景區后臺管理主頁面</title></head><body>${user.userName},歡迎您進入景區后臺管理! ①</body> </html>①處訪問Session域中的user對象,顯示用戶名和積分信息。這樣,就完成了實例所有的開發任務。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的《Spring 3.0就这么简单》——1.6 展现层的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows解决anaconda下双p
- 下一篇: yum安装nginx的负载均衡详解