springMVC4(7)模型視圖方法源代碼綜合分析
在完整web開發中。springMVC主要充當了控制層的角色。它接受視圖層的請求。獲取視圖層請求數據,再對數據進行業務邏輯處理。然後封裝成視圖層須要的模型數據,再將數據導向到jsp等視圖界面。
在前面,[email protected],完畢了視圖層->控制層的數據交接,然後業務邏輯處理主要由Service層進行。那麽接下來非常關鍵的就是,怎樣將視圖數據導向到特定的視圖中。
廣泛意義上,視圖,並不是是單指前端界面如jsp\html等。我們可能須要給安卓、IOS等寫後臺接口、因前後端分離而放棄視圖界面導向如對前端ajax請求的純數據流輸出等。
這時,我們的視圖能夠為json視圖、xml視圖、乃至PDF視圖、Excel視圖等
springMVC為我們提供了多種途徑輸出模型數據:
輸出途徑 | 功能說明 |
---|---|
ModelAndView | 將處理方法返回類型設為ModelAndView。裏面封裝了我們的模型數據,同一時候指明了視圖導向。 |
@modelAttribute | 方法入參標註改註解後,入參的對象就會放到數據模型中。 |
Map及Model | 入參為org.springframework.ui.Model或org.springframework.ui.ModelMap或java.util.Map時,方法返回時會將Map中的數據自己主動加入到模型中 |
@SessionAttributes | 將模型中的某個屬性暫存到HttpSession中,以便多個請求之間完畢屬性共享 |
以下我們主要介紹ModelAndView
ModelAndView(以下簡稱MAV)就像它的名字一樣。既包括了模型數據又包括視圖信息。我們返回一個MAV。springMVC就會將模型數據轉發給相應的視圖界面。
在學習ModelAndView的用法前。我們先用肢解的方法學習其兩個重要組成部分
1. model
model是一個接口,我們能夠簡單地將model的實現類理解成一個Map,將模型數據以鍵值對的形式返回給視圖層使用。在springMVC中,每一個方法被前端請求觸發調用前,都會創建一個隱含的模型對象,作為模型數據的存儲容器。
這是一個Request級別的模型數據。我們能夠在前端頁面如jsp中通過HttpServletRequest等相關API讀取到這些模型數據。
在model中。定義有例如以下經常使用接口方法:
/**
* 加入鍵值屬性對
*/
Model addAttribute(String attributeName, Object attributeValue);
/**
* 以屬性的類型為鍵加入屬
*/
Model addAttribute(Object attributeValue);
/**
* 以屬性和集合的類型構造鍵名加入集合屬性,假設有同類型會存在覆蓋現象
*/
Model addAllAttributes(Collection<?> attributeValues);
/**
* 將attributes中的內容拷貝到當前的model中
* 假設當前model存在同樣內容。會被覆蓋
*/
Model addAllAttributes(Map<String, ?> attributes);
/**
* 將attributes中的內容拷貝到當前的model中
* 假設當前model存在同樣內容,不會被覆蓋
*/
Model mergeAttributes(Map<String, ?> attributes);
/**
* 推斷是否有相應的屬性值
*/
boolean containsAttribute(String attributeName);
/**
* 將當前的model轉換成Map
*/
Map<String, Object> asMap();
假設我們加入的屬性沒有指定鍵名。我們稱之為匿名數據綁定,它們遵循例如以下規則:
1. 對於普通數據類型,我們直接以類型(第一字母小寫)作為鍵值
2. 對於集合類型(Collection接口的實現者們,包括數組),生成的模型對象屬性名為“簡單類名(首字母小寫)”+“List”,如List生成的模型對象屬性名為“stringList”,List生成的模型對象屬性名為“userModelList”。
在ModelAndView中,我們很多其它的是直接操作modelMap和Map來完畢我們的模型參數準備就可以。modelMap繼承自java.util.LinkedHashMap。
它在LinkedHashMap的基礎上,新增了非常多便利的構造方法如:
public ModelMap(String attributeName, Object attributeValue) {
addAttribute(attributeName, attributeValue);
}
public ModelMap addAllAttributes(Map<String, ?> attributes) {
if (attributes != null) {
putAll(attributes);
}
return this;
}
使用這些構造方法能進一步簡化我們的模型數據封裝。
2. view
view也是一個接口,它表示一個響應給用戶的視圖如jsp文件,pdf文件,html文件。
它有兩個接口方法:
1. String getContentType():返回視圖的內容類型
2. void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception
:依據給定模型和web資源定義視圖的渲染形式。
view接口有眾多的實現類,例如以下圖所看到的:
在spring中。通過ViewResolver來解析相應View實例的行為。 它的定義相當簡單:
public interface ViewResolver {
//通過view name 解析View
View resolveViewName(String viewName, Locale locale) throws Exception;
}
spring為我們提供ViewResolver實現類用來解析不同的view:
在我們最開始配置springMVC核心文件時,就用到了InternalResourceViewResolver,它是一個內部資源視圖解析器。
會把返回的視圖名稱都解析為 InternalResourceView 對象。 InternalResourceView 會把 Controller 處理器方法返回的模型屬性都存放到相應的 request 屬性中。然後通過 RequestDispatcher 在server端把請求 forword 重定向到目標 URL。
以下我們來看配置實例:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property><!-- 前綴,在springMVC控制層處理好的請求後,轉發配置文件夾下的視圖文件 -->
<property name="suffix" value=".jsp"></property><!-- 文件後綴,表示轉發到的視圖文件後綴為.jsp -->
</bean>
解析完Model and(和) View後,再來看我們的ModelAndView:
public class ModelAndView {
//視圖成員
private Object view;
//模型成員
private ModelMap model;
//是否調用clear()方法清空視圖和模型
private boolean cleared = false;
/**
* 空構造方法
*/
public ModelAndView() {
}
/**
* 簡便地使用視圖名生成視圖,詳細解析由DispatcherServlet的視圖解析器進行
*/
public ModelAndView(String viewName) {
this.view = viewName;
}
/**
* 指定一個視圖對象生成視圖
*/
public ModelAndView(View view) {
this.view = view;
}
/**
* 指定視圖名同一時候綁定模型數據。這裏模型數據以追加的形式加入在原來的視圖數據中
*/
public ModelAndView(String viewName, Map<String, ?> model) {
this.view = viewName;
if (model != null) {
getModelMap().addAllAttributes(model);
}
}
/**
* 指定一個視圖對象同一時候綁定模型數據。這裏模型數據以追加的形式加入在原來的視圖數據中
*/
public ModelAndView(View view, Map<String, ?> model) {
this.view = view;
if (model != null) {
getModelMap().addAllAttributes(model);
}
}
/**
* 簡便配置:指定視圖名,同一時候加入單個屬性
*/
public ModelAndView(String viewName, String modelName, Object modelObject) {
this.view = viewName;
addObject(modelName, modelObject);
}
/**
* 簡便配置:指定一個視圖對象,同一時候加入單個屬性
*/
public ModelAndView(View view, String modelName, Object modelObject) {
this.view = view;
addObject(modelName, modelObject);
}
/**
* 設置當前視圖名
*/
public void setViewName(String viewName) {
this.view = viewName;
}
/**
* 獲取視圖名。假設當前視圖屬性為view而非名字(String)則返回null
*/
public String getViewName() {
return (this.view instanceof String ? (String) this.view : null);
}
/**
* 設置當前視圖對象
*/
public void setView(View view) {
this.view = view;
}
/**
* 獲取視圖,假設非view實例,則返回null
*/
public View getView() {
return (this.view instanceof View ? (View) this.view : null);
}
/**
* 推斷當前視圖是否存在
*/
public boolean hasView() {
return (this.view != null);
}
/**
* 獲取模型Map。假設為空,則新建一個
*/
public ModelMap getModelMap() {
if (this.model == null) {
this.model = new ModelMap();
}
return this.model;
}
/**
* 同getModelMap
*/
public Map<String, Object> getModel() {
return getModelMap();
}
/**
* 加入單個鍵值對屬性
*/
public ModelAndView addObject(String attributeName, Object attributeValue) {
getModelMap().addAttribute(attributeName, attributeValue);
return this;
}
/**
* 以屬性類型為鍵加入屬性
*/
public ModelAndView addObject(Object attributeValue) {
getModelMap().addAttribute(attributeValue);
return this;
}
/**
* 將Map中的全部屬性加入到成員屬性ModelMap中
*/
public ModelAndView addAllObjects(Map<String, ?> modelMap) {
getModelMap().addAllAttributes(modelMap);
return this;
}
/**
* 清空視圖模型。並設為清空狀態
*/
public void clear() {
this.view = null;
this.model = null;
this.cleared = true;
}
/**
* 推斷是否為不含視圖和模型
*/
public boolean isEmpty() {
return (this.view == null && CollectionUtils.isEmpty(this.model));
}
}
springMVC4(7)模型視圖方法源代碼綜合分析