1?模型數據處理-數據放入 request
說明:開發中, 控制器/處理器中獲取的數據如何放入 request 域,然后在前端(VUE/JSP/...)取出顯 示
1.1?方式 1: 通過 HttpServletRequest 放入 request 域
(1)前端發送請求
<h1>添加主人信息</h1>
<form action="vote/vote05" method="post">主人號:<input type="text" name="id"><br>主人名:<input type="text" name="name"><br>寵物號:<input type="text" name="pet.id"><br>寵物名:<input type="text" name="pet.name"><br><input type="submit" value="添加主人和寵物">
</form>
(2)后端接收請求
springmvc會自動把獲取的model模型,放入到request域中
/*** 1. 將提交的數據封裝到java對象->springmvc 會自動的將其放入到request域* 2. 這樣我們就可以在跳轉到的頁面取出數據.*/
@RequestMapping(value = "/vote05")
public String test05(Master master, HttpServletRequest request) {//1. springmvc會自動把獲取的model模型,放入到request域中,名字就是master//2. 也可以手動將master放入到requestrequest.setAttribute("address", "beijing");//3. 如果我們希望修改master的屬性值master.setName("nono");//4. 分析一下springmvc默認存放對象到request域中,屬性名是// request域 ("master", master) 屬性名是類名/類型名 首字母小寫//返回到一個結果return "vote_ok";
}
(3)跳轉頁面
<h1>獲取的的數據顯示頁面</h1>
<hr>
取出 request域的數據-通過 el表達式來獲取
<br>
address: ${requestScope.address}<br>
主人名字= ${requestScope.master.name}
主人id= ${requestScope.master.id}
寵物名字= ${requestScope.master.pet.name}
(4)頁面顯示結果
1.2?方式 2: 通過請求的方法參數 Map<String,Object> 放入 request 域
(1)前端發送請求
<h1>添加主人信息[測試 Map ]</h1>
<form action="vote/vote06" method="post">主人號:<input type="text" name="id"><br>主人名:<input type="text" name="name"><br>寵物號:<input type="text" name="pet.id"><br>寵物名:<input type="text" name="pet.name"><br><input type="submit" value="添加主人和寵物">
</form>
(2)后端接收請求
/*** 通過Map<String,Object> 設置數據到request域*/
@RequestMapping(value = "/vote06")
public String test06(Master master, Map<String, Object> map) {//1. 需求是通過map對象,添加屬性到request中//2. 原理分析:springmvc會遍歷map,然后將map的k-v, 存放到request域map.put("address", "beijing...");//返回到一個結果return "vote_ok";
}
(3)跳轉頁面同方式1
(4)頁面顯示結果
1.3?方式 3: 通過返回 ModelAndView 對象 實現 request 域數據
(1)前端發送請求
<h1>添加主人信息[測試ModelAndView]</h1>
<form action="vote/vote07" method="post">主人號:<input type="text" name="id"><br>主人名:<input type="text" name="name"><br>寵物號:<input type="text" name="pet.id"><br>寵物名:<input type="text" name="pet.name"><br><input type="submit" value="添加主人和寵物">
</form>
(2)后端接收請求
說明:
- 從本質看,請求響應的方法 return "xx", 是返回了一個字符串,其實本質是返回了一個 ModelAndView 對象,只是默認被封裝起來的.
- ModelAndView 即可以包含 model 數據,也可以包含視圖信息
- ModelAndView 對象的 addObject 方法可以添加 key-val 數據,默認在 request 域中
- ModelAndView 對象 setView 方法可以指定視圖名稱
/*** 通過返回ModelAndView對象,將數據放入到request域*/
@RequestMapping(value = "/vote07")
public ModelAndView test07(Master master) {System.out.println("----test07----");ModelAndView modelAndView = new ModelAndView();//放入屬性到modelAndView對象modelAndView.addObject("address", "shanghai");//可以把從數據庫得到的數據->對象,放入modelAndView//這里指定跳轉的視圖名稱modelAndView.setViewName("vote_ok");//返回結果return modelAndView;
}
(3)跳轉頁面同方式1
(4)頁面顯示結果
2?模型數據處理-數據放入 session
說明:開發中, 控制器/處理器中獲取的數據如何放入 session 域,然后在前端(VUE/JSP/...)取出顯 示
應用實例:
(1)前端發送請求
<h1>添加主人信息[測試session]</h1>
<form action="vote/vote08" method="post">主人號:<input type="text" name="id"><br>主人名:<input type="text" name="name"><br>寵物號:<input type="text" name="pet.id"><br>寵物名:<input type="text" name="pet.name"><br><input type="submit" value="添加主人和寵物">
</form>
(2)后端接收請求
/*** 將數據設置到session域中*/
@RequestMapping(value = "/vote08")
public String test08(Master master, HttpSession httpSession) {System.out.println("----test08----");//master對象是默認放在request域//這里將master對象放入到session域httpSession.setAttribute("master", master);httpSession.setAttribute("address", "guangzhou");return "vote_ok";//請求轉發
}
(3)跳轉頁面
取出 session域的數據 <br>
address: ${sessionScope.address}<br>
主人名字= ${sessionScope.master.name}
主人信息= ${sessionScope.master}
(4)頁面顯示結果
3 @ModelAttribute 實現 prepare 方法
說明:開發中,有時需要使用某個前置方法(比如 prepareXxx(), 方法名由程序員定)給目標方法準 備一個模型對象
@ModelAttribute 注解可以實現 這樣的需求,在某個方法上,增加了@ModelAttribute 注解后 那么在調用該 Handler 的任何一個方法時,都會先調用這個方法
案例:
/*** 1. 當Handler的方法被標識 @ModelAttribute,就視為一個前置方法* 2. 當調用該Handler的其它的方法時,都會先執行該前置方法* 3. 類似Spring中AOP的前置通知[底層是AOP機制]* 4. prepareModel前置方法,會切入到其它方法前執行*/
@ModelAttribute
public void prepareModel(){System.out.println("prepareModel()-----完成準備工作-----");
}
使用場景舉例:
修改用戶信息(就是經典的使用這種機制的應用),流程如下:
1. 在修改前,在前置方法中從數據庫查出這個用戶
2. 在修改方法(目標方法)中,可以使用前置方法從數據庫查詢的用戶
3. 如果表單中對用戶的某個屬性修改了,則以新的數據為準,如果沒有修改,則以數據庫 的信息為準,比如,用戶的某個屬性不能修改,就保持原來的值?
4?視圖和視圖解析器
4.1?基本介紹
(1)在 springMVC 中的目標方法最終返回都是一個視圖(有各種視圖).
(2)返回的視圖都會由一個視圖解析器來處理 (視圖解析器有很多種)
4.2 自定義視圖
4.2.1?為什么需要自定義視圖
(1)在默認情況下,我們都是返回默認的視圖, 然后這個返回的視圖交由 SpringMVC 的 InternalResourceViewResolver 視圖處理器來處理的
<!--下面配置springMVC的視圖解析器,如果我們的controller return 的是 login_ok
那么要跳轉的頁面頁面就是 /WEB-INF/pages/login_ok-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><!--配置屬性suffix(后綴) 和 prefix(前綴)--><property name="prefix" value="/WEB-INF/pages/"/><property name="suffix" value=".jsp"/>
</bean>
(2)在實際開發中,我們有時需要自定義視圖,這樣可以滿足更多更復雜的需求.
4.2.2 自定義視圖實例-代碼實現
(1)配置 applicationContext-mvc, 增加自定義視圖解析器
<!--
1. 配置自定義視圖解析器BeanNameViewResolver
2. BeanNameViewResolver可以去解析我們自定義的視圖
3. 配置 屬性 order, 表示視圖解析器執行的順序, 值越小, 優先級越高
4. 屬性 order 的默認值是最低優先級 ,值為 Integer.MAX_VALUEint LOWEST_PRECEDENCE = 2147483647
-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"><property name="order" value="99"/>
</bean>
(2)創建 MyView.java - 自定義視圖類
package com.web.viewresolver;import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.AbstractView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;/*** 1. MyView繼承了AbstractView, 就可以作為一個視圖使用* 2. @Component(value = "myView"),該視圖會注入到容器中, 名字/id是 myView*/
@Component(value = "myView")
public class MyView extends AbstractView {@Overrideprotected void renderMergedOutputModel(Map<String, Object> model,HttpServletRequest request,HttpServletResponse response) throws Exception {//完成視圖渲染//并且可以確定我們要跳轉的頁面 [請求轉發]System.out.println("進入到自己的視圖..");//1. 下面就是進行請求轉發到 /WEB-INF/pages/my_view.jsp//2. /WEB-INF/pages/my_view.jsp 會被springmvc解析成 /springmvc/WEB-INF/pages/my_view.jsprequest.getRequestDispatcher("/WEB-INF/pages/my_view.jsp").forward(request, response);}
}
(3)創建 GoodsHandler.java
@RequestMapping("/goods")
@Controller
public class GoodsHandler {@RequestMapping(value = "/buy")public String buy() {System.out.println("------buy()-----");// 這里返回自定義視圖類在容器中的名字/idreturn "myView";}
}
(4)創建 web\view.jsp 和 /WEB-INF/pages/my_view.jsp?
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>自定義視圖測試</title>
</head>
<body>
<h1>自定義視圖測試</h1>
<a href="goods/buy">點擊到自定義視圖-</a><br/>
<a href="goods/order">測試在目標方法中指定請求轉發或者重定向的頁面-</a><br/>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>my_view頁面</title>
</head>
<h1>進入到my_view頁面</h1>
<p>是從自定義視圖來的..</p>
<body></body>
</html>
?(5)效果如下
初始頁面:
跳轉頁面:
4.2.3?自定義視圖工作流程小結
自定義視圖-小結
- 自定義視圖: 創建一個 View 的 bean, 該 bean 需要繼承自 AbstractView, 并實現 renderMergedOutputModel 方法.
- 需要把自定義 View 加入到 IOC 容器中
- 自定義視圖的視圖處理器,使用 BeanNameViewResolver, 這個視圖處理器也需要配置 到 ioc 容器
- BeanNameViewResolver 的調用優先級需要設置一下,設置 order 比 Integer.MAX_VAL 小的值. 以確保其在 InternalResourceViewResolver 之前被調用
自定義視圖-工作流程
- SpringMVC 調用目標方法, 返回自定義 View 在 IOC 容器中的 id
- SpringMVC 調用 BeanNameViewResolver 解析視圖: 從 IOC 容器中獲取 返回 id 值對 應的 bean, 即自定義的 View 的對象
- SpringMVC 調用自定義視圖的 renderMergedOutputModel 方法渲染視圖
- 說明: 如果在 SpringMVC 調用目標方法, 返回自定義 View 在 IOC 容器中的 id, 不存在, 則仍然按照默認的視圖處理器機制處理。但是如果先按照默認視圖解析器進行解析,就是解析出來的頁面不存在,也不會進入到自定義解析器,而會直接報錯
4.3?目標方法直接指定轉發或重定向
4.3.1 說明
(1)默認返回的方式是請求轉發,然后用視圖處理器進行處理,比如在目標方法中這樣寫:
@RequestMapping(value = "/login")
public String login(){System.out.println("login ok....");return "login_ok";
}
(2)也可以在目標方法直接指定重定向或轉發的 url 地址
(3)如果指定重定向,不能定向到 /WEB-INF 目錄中,因為這個目錄是tomcat的一個類路徑
4.3.2 應用實例
(1)修改 GoodsHandler.java, 增加方法 order()?
/*** 演示直接指定要請求轉發的或者是重定向的頁面*/
@RequestMapping(value = "/order")
public String order() {System.out.println("=======order()=====");//請求轉發到 /WEB-INF/pages/my_view.jsp//forward 關鍵字表示請求轉發//請求轉發可以到/WEB-INF/ 目錄下,也可以轉發到這個目錄外面的頁面//下面的 /WEB-INF/pages/my_view.jsp 會被解析成 /springmvc/WEB-INF/pages/my_view.jsp//return "forward:/WEB-INF/pages/my_view.jsp"; // 等價于 return "my_view.jsp"//請求轉發到/WEB-INF/目錄外面的頁面//return "forward:/aaa/bbb/ok.jsp";//直接指定要重定向的頁面//1. 對于重定向來說,可以重定向到web目錄,不能重定向到 /WEB-INF/ 目錄下//2. redirect 關鍵字,表示進行重定向//3. /login.jsp 在服務器解析 /springmvc/login.jspreturn "redirect:/login.jsp";// /WEB-INF/pages/my_view.jsp 被解析 /springmvc/WEB-INF/pages/my_view.jsp 該路徑是訪問不到的//return "redirect:/WEB-INF/pages/my_view.jsp";//這樣寫會報錯
}
?(2)前端發出請求
<a href="goods/order">測試在目標方法中指定請求轉發或者重定向的頁面-</a><br/>
?(3)跳轉頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>登錄成功</title>
</head>
<body>
<h1>恭喜 登錄成功</h1>
</body>
</html>
(4)跳轉成功