模型數據 1.數據放入request 說明:開發中,控制器/處理器中獲取的數據如何放入request域,然後在前端(vue/jsp/...)取出顯示? 先來看一個例子 應用實例需求:表單提交信息,後端獲取信息,並通過request轉發到另一個頁面,顯示信息。 需要知道的是:前端提交的數據,sprin ...
模型數據
1.數據放入request
- 說明:開發中,控制器/處理器中獲取的數據如何放入request域,然後在前端(vue/jsp/...)取出顯示?
先來看一個例子
應用實例需求:表單提交信息,後端獲取信息,並通過request轉發到另一個頁面,顯示信息。
需要知道的是:前端提交的數據,springmvc會自動地封裝到java對象中,同時 springmvc 會自動地將其放入request 域中,這樣我們就可以在跳轉的下一個頁面取出數據。
-
mode_date.jsp提交數據:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>model_data</title> </head> <body> <form action="vote/vote05" method="post"> 主人id:<input type="text" name="id"/><br/> 主人名:<input type="text" name="name"/><br/> 寵物id:<input type="text" name="pet.id"/><br/> 寵物名:<input type="text" name="pet.name"/><br/> <input type="submit" value="添加主人和寵物"/><br/> </form> </body> </html>
-
VoteHandler.java:
springmvc會自動將數據封裝到Javabean中,並將獲取的model模型放入到request域中。
package com.li.web.requestparam; import com.li.entity.Master; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author 李 * @version 1.0 */ @RequestMapping(value = "/vote") @Controller public class VoteHandler { /** * 1.提交的數據->springmvc會自動地封裝到 java對象 * ->同時 springmvc 會自動地將其放入request域中 * 2.這樣就可以在跳轉的下一個頁面取出數據 */ @RequestMapping(value = "/vote05") public String test05(Master master) { //springmvc會自動的把獲取的model模型放入request域中,名字就是 master return "vote_ok"; } }
-
轉發的頁面 vote_ok.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>vote_ok</title> </head> <body> <h1>取出request域中的信息</h1> 主人的id=${requestScope.master.id} 主人的名字=${requestScope.master.name} 寵物的id=${requestScope.master.pet.id} 寵物的名字=${requestScope.master.pet.name} </body> </html>
訪問mode_date.jsp,提交數據:
轉發頁面vote_ok.jsp成功地拿到了request域中的信息:
從上述代碼中可以看出springmvc會自動將獲取的model數據添加到request域中。同時我們也可以手動添加修改數據,並放入到request域中,有如下三種方式:
1.1方式1-通過HttpServletRequest放入request域
-
這種方式就是原生的javaweb方式,可以在request域中以k-v形式,直接放入普通字元串,也可以放入對象
-
同時springmvc 自動放入request域的model也可以被修改
-
註意:springmvc放入request域中的對象的key值,是按照對象的類型(首字母小寫)存放的,和方法的形參名無關
修改VoteHandler.java:
@RequestMapping(value = "/vote05")
public String test05(Master master100, HttpServletRequest request) {
//1.springmvc會自動的把獲取的model模型放入request域中,名字就是 master
//2.也可以手動添加數據到request域中
request.setAttribute("address", "beijing");
//3.同時可以修改 master的屬性值
master100.setName("hahahah");
//4.分析一下springmvc預設存放對象到request域中,屬性名是如何確定的?
// 是按對象的類型(首字母小寫)放入的,和方法的形參名無關
// 因此我們在轉發的頁面按照該名稱是可以拿出來的
return "vote_ok";
}
mode_date.jsp不變,vote_ok.jsp添加address獲取。
提交數據:
轉發頁面獲取的數據:
1.2方式2-通過請求的方法參數Map<String,Object>放入request域
springmvc會遍歷map,將map中的k-v存放到request域中。因此你會發現在轉發頁面中,直接通過${requestScope.key}也可以獲取屬性的數據。
修改VoteHandler.java:
/**
* 演示通過Map<String,Object>設置數據到request域
*/
@RequestMapping(value = "/vote06")
public String test06(Master master, Map<String, Object> map) {
//需求是通過map對象,添加屬性到request域中
map.put("address", "tianjin");
//原理分析:springmvc會遍歷map,將map中的k-v存放到request域中
//因此你會發現在轉發頁面中,直接通過${requestScope.address}也可以獲取address的數據
return "vote_ok";
}
model_data.jsp不變
vote_ok.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>vote_ok</title>
</head>
<body>
<h1>取出request域中的信息</h1>
主人的address=${requestScope.address}
主人的id=${requestScope.master.id}
主人的名字=${requestScope.master.name}
寵物的id=${requestScope.master.pet.id}
寵物的名字=${requestScope.master.pet.name}
</body>
</html>
model_data.jsp:
vote_ok.jsp:
註意事項:
-
我們知道,表單提交的數據會被springmvc自動封裝成對象,並放入request域中。而且springmvc會掃描map,將裡面的k-v也放到request域中。
-
這意味著,如果map的中某個key和之前自動封裝的對象同名,那麼在springmvc掃描map的時候,原先的request的對象的屬性值會被map中同名key的value值覆蓋。
1.3方式3-通過返回ModelAndView對象實現request域數據
- 表單數據被springmvc封裝到master對象
- master對象被springmvc封裝到request域中
- ModelAndView的屬性也會被springmvc放入到request域中
- 因此轉發的頁面中可以通過request域獲取到所有數據
修改 VoteHandler.java:
//演示通過返回ModelAndView對象,將數據放入到request域中
@RequestMapping(value = "/vote07")
public ModelAndView test07(Master master) {
ModelAndView modelAndView = new ModelAndView();
//放入屬性到 ModelAndView對象
modelAndView.addObject("address", "shanghai~~");
//指定要跳轉的視圖名稱
modelAndView.setViewName("vote_ok");
return modelAndView;
}
model_data.jsp不變
vote_ok.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>vote_ok</title>
</head>
<body>
<h1>取出request域中的信息</h1>
主人的address=${requestScope.address}
主人的id=${requestScope.master.id}
主人的名字=${requestScope.master.name}
寵物的id=${requestScope.master.pet.id}
寵物的名字=${requestScope.master.pet.name}
</body>
</html>
model_data.jsp:
vote_ok.jsp:可以看到在ModelAndView中的數據已經被放入到了request對象中,因此可以直接獲取
註意事項:
-
從本質上看,請求響應的方return "xxx",只是返回了一個字元串,其實本質上底層是返回了一個ModelAndView 對象,只是預設被封裝起來了。
-
ModelAndView 既可以包含 model 數據,也可以包含視圖信息。
-
ModelAndView 對象的 addObject 方法可以添加key-val數據,添加的數據預設被 springmvc 掃描放在request域中。
-
ModelAndView 對象的 setView 方法可以指定視圖名稱。
-
這裡ModelAndView 被 springmvc 掃描,將屬性放入request域中的操作,和之前map被springmvc掃描非常相似。同樣的,ModelAndView中的屬性被放入request域中時,如果request域中已經有同名屬性了,那麼將會進行覆蓋操作。
2.數據放入session
- 說明:開發中,控制器/處理器中獲取的數據如何放入session域,然後在前端(vue/jsp/...)取出顯示?
應用實例
仍然以之前的例子說明:
-
model_date.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>model_data</title> </head> <body> <h1>添加信息[測試session]</h1> <form action="vote/vote08" method="post"> 主人id:<input type="text" name="id"/><br/> 主人名:<input type="text" name="name"/><br/> 寵物id:<input type="text" name="pet.id"/><br/> 寵物名:<input type="text" name="pet.name"/><br/> <input type="submit" value="添加主人和寵物"/><br/> </form> </body> </html>
-
修改VoteHandler.java
//演示如何將數據設置到session域中 @RequestMapping(value = "/vote08") public String test08(Master master,HttpSession session) { //master對象預設放在request域中 //因此要手動將數據放入session中 session.setAttribute("master",master); session.setAttribute("address","guangzhou"); return "vote_ok"; }
-
vote_ok.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>vote_ok</title> </head> <body> <h1>取出session域中的信息</h1> 主人的address=${sessionScope.address}<br/> 主人的id=${sessionScope.master.id}<br/> 主人的名字=${sessionScope.master.name}<br/> 寵物的id=${sessionScope.master.pet.id}<br/> 寵物的名字=${sessionScope.master.pet.name} </body> </html>
model_data.jsp:
vote_ok.jsp:
3.@ModelAttribute實現prepare方法
3.1基本說明
開發中,有時需要使用某個前置方法(如prepareXXX,名稱隨意)給目標方法準備一個模型對象
- @ModelAttribute 註解可以實現這樣的需求
- 在某個方法上添加了@ModelAttribute註解後,這個方法就是前置方法。在調用該Handler的任何一個方法時,都會先調用這個前置方法。
應用實例
-
修改VoteHandler.java,增加方法,並測試。
@RequestMapping(value = "/vote09") public String test09() { System.out.println("test09被調用..."); return "vote_ok"; } @RequestMapping(value = "/vote10") public String test10() { System.out.println("test10被調用..."); return "vote_ok"; } /** * 1.當 Handler的一個方法被 @ModelAttribute 修飾時,這個方法就是前置方法 * 2.該 Handler中的其他方法被調用時,都會先調用這個前置方法 * 3.類似spring的aop的前置通知 * 4.前置方法會切入到其他方法前執行[底層還是aop機制] */ @ModelAttribute public void prepareModel() { System.out.println("prepareModel()---完成準備工作"); }
-
分別在瀏覽器中方法test09,test10方法
-
後臺輸出:可以看到每次目標方法被訪問前,都會調用前置方法prepareModel()
3.2@ModelAttribute的最佳實踐
- 修改用戶信息(就是這種機制的經典應用),流程如下:
- 在修改前,在前置方法中從資料庫查出這個用戶的數據
- 在修改方法(目標方法)中,可以使用前置方法的(從資料庫查出的)用戶數據
- 如果表單中對用戶的某個屬性修改了,則以新的數據為準。如果沒有修改或不能修改,就以前置方法查出的用戶數據為準,就保持原來的值。