在spring MVC 中,controllers不會負責具體的頁面渲染,它僅僅是調用業務邏輯並返回model數據給view層,至於view層具體怎麼用HTML展示,由專門的view層具體負責,這就是MVC模式,業務層與展現層是鬆耦合的。那麼,Spring MVC是如何解耦合請求處理邏輯和頁面渲染的呢?java
咱們在Spring MVC配置介紹文章中已經知道,controller在處理外業務邏輯以後會返回一個邏輯view的字符串,那麼Spring MVC是怎麼根據這個邏輯view名找到真正的物理view頁面呢?這個工做就由Spring的ViewResolvers負責。web
對於普通的JSP頁面,最經常使用到的就是view resolver就是InternalResourceViewResolver
,它有兩個屬性,一個是匹配物理view的前綴,一個是後綴。前綴通常就是view頁面的路徑位置,後綴就是文件的格式,而前綴後綴之間的就是邏輯view名稱。spring
<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"; } }
ViewResolver接口:後端
public interface ViewResolver { View resolveViewName(String var1, Locale var2) throws Exception; }
這個接口很簡單,當咱們傳入一個邏輯view名和Locale對象,就會返回一個View實例。mvc
View接口:app
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對象中去就能夠了。jsp
固然,咱們基本上不須要本身去寫ViewResolver,spring mvc爲咱們提供了各類各樣的ViewResolver:
ui
上面雖然列了不少個ViewResolver,但咱們具體用哪一個好呢?其實上面的每一個ViewResolver都對應着一種view頁面的實現技術,好比InternalResourceViewResolver
就是用來處理JSP頁面,TilesViewResolver
主要處理Apache Tiles Views
,FreeMarkerViewResolver
和VelocityViewResolver
分別對應着FreeMarker
和Velocity Template
頁面渲染技術。spa
無能否認,在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頁面,它用起來最簡單也最方便。
其實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頁面:
上面例子中還能夠看到,當咱們的邏輯名稱中含有反斜線/時,解析器會將其解析成資源文件的路徑,這樣咱們就能夠對頁面資源文件進行目錄管理了。
若是要想在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>
上面已經講過,Spring JSP提供了兩種類庫,一種是表單數據綁定標籤庫,另外一種提供了更多樣話的通用標籤庫。
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對象的屬性
除了表單數據綁定標籤庫以外,Spring還提供了一個更加通用的標籤庫,要想使用這個更通用的標籤庫,只須要在JSP頁面中添加:
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
標籤庫中的標籤:
關於這些標籤的詳細使用說明能夠查看spring的官方文檔,這裏很少作介紹了。