一、理解view解析過程
1.1 從邏輯view到物理view
在Spring MVC 中,controllers不會負責具體的頁面渲染,它僅僅是調用業務邏輯並返回model數據給view層,至於view層具體怎麼用HTML展現,由專門的view層具體負責,這就是MVC模式,業務層與展示層是松耦合的。那麼,Spring MVC是如何解耦合請求處理邏輯和頁面渲染的呢?
我們在Spring MVC配置介紹文章中已經知道,controller在處理外業務邏輯之後會返回一個邏輯view的字符串,那麼Spring MVC是怎麼根據這個邏輯view名找到真正的物理view頁面呢?這個工作就由Spring的ViewResolvers負責。
對於普通的JSP頁面,最常用到的就是view resolver就是InternalResourceViewResolver
,它有兩個屬性,一個是匹配物理view的前綴,一個是後綴。前綴一般就是view頁面的路徑位置,後綴就是文件的格式,而前綴後綴之間的就是邏輯view名稱。
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
比如按照上面的配置,如果controller返回的邏輯view名稱是home的話,InternalResourceViewResolver
會根據這個邏輯view名home找到其對應的實際物理view:/WEB-INF/views/home.jsp
。
@Controller
@RequestMapping(value = "/")
public class HomeController {
@RequestMapping(method= RequestMethod.GET)
public String home() {
return "home";
}
}
1.2 ViewResolver相關接口
ViewResolver接口:
public interface ViewResolver {
View resolveViewName(String var1, Locale var2) throws Exception;
}
這個接口很簡單,當我們傳入一個邏輯view名和Locale對象,就會返回一個View實例。
View接口:
public interface View {
String getContentType();
void render(Map<String, ?> var1, HttpServletRequest var2, HttpServletResponse var3) throws Exception;
}
View接口的職責就是接收model對象、Request對象、Response對象,並渲染輸出結果給Response對象。如果我們要自己寫一個ViewResolver也很簡單,我們只需要實現ViewResolver和View兩個接口,在View接口中把需要渲染的內容輸出到Response對象中去就可以了。
1.3 各種現成的ViewResolver
當然,我們基本上不需要自己去寫ViewResolver,spring mvc爲我們提供了各種各樣的ViewResolver:
上面雖然列了很多個ViewResolver,但我們具體用哪個好呢?其實上面的每個ViewResolver都對應着一種view頁面的實現技術,比如InternalResourceViewResolver
就是用來處理JSP頁面,TilesViewResolver
主要處理Apache Tiles Views
,FreeMarkerViewResolver
和VelocityViewResolver
分別對應着FreeMarker
和Velocity Template
頁面渲染技術。
二、創建一個JSP View
無可否認,在Java web編程領域,歷史最悠久的頁面處理技術便是JSP。所以,這裏我們就拿JSP技術來展示spring是如何渲染頁面的。
Spring有兩種方式來支持JSP頁面:
1. InternalResourceViewResolver可以用來解析JSP文件,當然,它也支持JSP頁面使用JavaServer Standard Library(JSTL)
2. Spring自己也提供了兩種JSP 標籤類庫,一種是表單數據綁定標籤庫,另一種是提供了一些通用特性的標籤庫
無論我們使用JSTL還是Spring JSP標籤類庫,我們都需要配置一個ViewResolver來解析JSP頁面。當然一些其他的ViewResolver也可以解析JSP頁面,但InternalResourceViewResolver是專門針對JSP技術設計的解析器,所以對於JSP頁面,它用起來最簡單也最方便。
2.1 InternalResourceViewResolver的配置
其實InternalResourceViewResolver
的配置在1.1節已經介紹了,它可以直接把一個邏輯view名映射到轉實際渲染數據的物理view頁面。如果按照我們這樣的配置:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
那麼對於下面這些邏輯view名,InternalResourceViewResolver
則會將其映射成相應的JSP頁面:
- home 解析成 /WEB-INF/views/home.jsp
- productList 解析成 /WEB-INF/views/productList.jsp
- books/detail 解析成 /WEB-INF/views/books/detail.jsp
上面例子中還可以看到,當我們的邏輯名稱中含有反斜線/時,解析器會將其解析成資源文件的路徑,這樣我們就可以對頁面資源文件進行目錄管理了。
2.2 解析標準的JSTL文件
如果要想在JSP中使用JSTL標籤很簡單,我們只需在InternalResourceViewResolver中指定一個viewClass屬性即可:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView />
</bean>
2.3 使用Spring JSP類庫
上面已經講過,Spring JSP提供了兩種類庫,一種是表單數據綁定標籤庫,另一種提供了更多樣話的通用標籤庫。
2.3.1 使用表單數據綁定標籤庫
Spring的表單數據綁定標籤庫提供了14個標籤,它和普通標籤的區別就是能夠將表單屬性和model對象屬性綁定在一起。要想使用表單數據綁定標籤庫,只需要在JSP頁面中聲明:
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
標籤庫中的14個標籤:
下面舉個例子,我們使用這個標籤庫來重寫一個註冊頁面:
<sf:form method="POST" commandName="user">
First Name: <sf:input path="firstName" /><br/>
Last Name: <sf:input path="lastName" /><br/>
Email: <sf:input path="email" /><br/>
Username: <sf:input path="username" /><br/>
Password: <sf:password path="password" /><br/>
<input type="submit" value="Register" />
</sf:form>
commandName:對應後端model數據對象名稱,也就是Model中的對應的key值
@RequestMapping(value="/register", method= RequestMethod.GET)
public String showRegistrationForm(Model model) {
model.addAttribute("user",new User());
return "register";
}
path:我們可以看到form表單內部每個標籤都有個path屬性,這個屬性對應的就是Model對象的屬性
2.3.2 使用通用標籤庫
除了表單數據綁定標籤庫之外,Spring還提供了一個更加通用的標籤庫,要想使用這個更通用的標籤庫,只需要在JSP頁面中添加:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
標籤庫中的標籤:
關於這些標籤的詳細使用說明可以查看spring的官方文檔,這裏不多做介紹了。