day03-模型数据

打印 上一主题 下一主题

主题 525|帖子 525|积分 1575

模型数据

1.数据放入request


  • 说明:开发中,控制器/处理器中获取的数据如何放入request域,然后在前端(vue/jsp/...)取出显示?
先来看一个例子
应用实例需求:表单提交信息,后端获取信息,并通过request转发到另一个页面,显示信息。

需要知道的是:前端提交的数据,springmvc会自动地封装到java对象中,同时 springmvc 会自动地将其放入request 域中,这样我们就可以在跳转的下一个页面取出数据。

  • mode_date.jsp提交数据:
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4.     <title>model_data</title>
    5. </head>
    6. <body>
    7. <form action="vote/vote05" method="post">
    8.   主人id:<input type="text" name="id"/><br/>
    9.   主人名:<input type="text" name="name"/><br/>
    10.   宠物id:<input type="text" name="pet.id"/><br/>
    11.   宠物名:<input type="text" name="pet.name"/><br/>
    12.   <input type="submit" value="添加主人和宠物"/><br/>
    13. </form>
    14. </body>
    15. </html>
    复制代码
  • VoteHandler.java:
    springmvc会自动将数据封装到Javabean中,并将获取的model模型放入到request域中。
    1. package com.li.web.requestparam;
    2. import com.li.entity.Master;
    3. import org.springframework.stereotype.Controller;
    4. import org.springframework.web.bind.annotation.RequestMapping;
    5. /**
    6. * @author 李
    7. * @version 1.0
    8. */
    9. @RequestMapping(value = "/vote")
    10. @Controller
    11. public class VoteHandler {
    12.     /**
    13.      * 1.提交的数据->springmvc会自动地封装到 java对象
    14.      * ->同时 springmvc 会自动地将其放入request域中
    15.      * 2.这样就可以在跳转的下一个页面取出数据
    16.      */
    17.     @RequestMapping(value = "/vote05")
    18.     public String test05(Master master) {
    19.         //springmvc会自动的把获取的model模型放入request域中,名字就是 master
    20.         return "vote_ok";
    21.     }
    22. }
    复制代码
  • 转发的页面 vote_ok.jsp:
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4.     <title>vote_ok</title>
    5. </head>
    6. <body>
    7. <h1>取出request域中的信息</h1>
    8. 主人的id=${requestScope.master.id}
    9. 主人的名字=${requestScope.master.name}
    10. 宠物的id=${requestScope.master.pet.id}
    11. 宠物的名字=${requestScope.master.pet.name}
    12. </body>
    13. </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:
  1. @RequestMapping(value = "/vote05")
  2. public String test05(Master master100, HttpServletRequest request) {
  3.     //1.springmvc会自动的把获取的model模型放入request域中,名字就是 master
  4.     //2.也可以手动添加数据到request域中
  5.     request.setAttribute("address", "beijing");
  6.     //3.同时可以修改 master的属性值
  7.     master100.setName("hahahah");
  8.     //4.分析一下springmvc默认存放对象到request域中,属性名是如何确定的?
  9.     //  是按对象的类型(首字母小写)放入的,和方法的形参名无关
  10.     //  因此我们在转发的页面按照该名称是可以拿出来的
  11.     return "vote_ok";
  12. }
复制代码
mode_date.jsp不变,vote_ok.jsp添加address获取。
提交数据:
转发页面获取的数据:
1.2方式2-通过请求的方法参数Map放入request域

springmvc会遍历map,将map中的k-v存放到request域中。因此你会发现在转发页面中,直接通过${requestScope.key}也可以获取属性的数据。
修改VoteHandler.java:
  1. /**
  2. * 演示通过Map<String,Object>设置数据到request域
  3. */
  4. @RequestMapping(value = "/vote06")
  5. public String test06(Master master, Map<String, Object> map) {
  6.     //需求是通过map对象,添加属性到request域中
  7.     map.put("address", "tianjin");
  8.     //原理分析:springmvc会遍历map,将map中的k-v存放到request域中
  9.     //因此你会发现在转发页面中,直接通过${requestScope.address}也可以获取address的数据
  10.     return "vote_ok";
  11. }
复制代码
model_data.jsp不变
vote_ok.jsp:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4.     <title>vote_ok</title>
  5. </head>
  6. <body>
  7. <h1>取出request域中的信息</h1>
  8. 主人的address=${requestScope.address}
  9. 主人的id=${requestScope.master.id}
  10. 主人的名字=${requestScope.master.name}
  11. 宠物的id=${requestScope.master.pet.id}
  12. 宠物的名字=${requestScope.master.pet.name}
  13. </body>
  14. </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:
  1. //演示通过返回ModelAndView对象,将数据放入到request域中
  2. @RequestMapping(value = "/vote07")
  3. public ModelAndView test07(Master master) {
  4.     ModelAndView modelAndView = new ModelAndView();
  5.     //放入属性到 ModelAndView对象
  6.     modelAndView.addObject("address", "shanghai~~");
  7.     //指定要跳转的视图名称
  8.     modelAndView.setViewName("vote_ok");
  9.     return modelAndView;
  10. }
复制代码
model_data.jsp不变
vote_ok.jsp:
  1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  2. <html>
  3. <head>
  4.     <title>vote_ok</title>
  5. </head>
  6. <body>
  7. <h1>取出request域中的信息</h1>
  8. 主人的address=${requestScope.address}
  9. 主人的id=${requestScope.master.id}
  10. 主人的名字=${requestScope.master.name}
  11. 宠物的id=${requestScope.master.pet.id}
  12. 宠物的名字=${requestScope.master.pet.name}
  13. </body>
  14. </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
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4.     <title>model_data</title>
    5. </head>
    6. <body>
    7. <h1>添加信息[测试session]</h1>
    8. <form action="vote/vote08" method="post">
    9.   主人id:<input type="text" name="id"/><br/>
    10.   主人名:<input type="text" name="name"/><br/>
    11.   宠物id:<input type="text" name="pet.id"/><br/>
    12.   宠物名:<input type="text" name="pet.name"/><br/>
    13.   <input type="submit" value="添加主人和宠物"/><br/>
    14. </form>
    15. </body>
    16. </html>
    复制代码
  • 修改VoteHandler.java
    1. //演示如何将数据设置到session域中
    2. @RequestMapping(value = "/vote08")
    3. public String test08(Master master,HttpSession session) {
    4.     //master对象默认放在request域中
    5.     //因此要手动将数据放入session中
    6.     session.setAttribute("master",master);
    7.     session.setAttribute("address","guangzhou");
    8.     return "vote_ok";
    9. }
    复制代码
  • vote_ok.jsp:
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4.     <title>vote_ok</title>
    5. </head>
    6. <body>
    7. <h1>取出session域中的信息</h1>
    8. 主人的address=${sessionScope.address}<br/>
    9. 主人的id=${sessionScope.master.id}<br/>
    10. 主人的名字=${sessionScope.master.name}<br/>
    11. 宠物的id=${sessionScope.master.pet.id}<br/>
    12. 宠物的名字=${sessionScope.master.pet.name}
    13. </body>
    14. </html>
    复制代码
model_data.jsp:
vote_ok.jsp:
3.@ModelAttribute实现prepare方法

3.1基本说明

开发中,有时需要使用某个前置方法(如prepareXXX,名称随意)给目标方法准备一个模型对象

  • @ModelAttribute 注解可以实现这样的需求
  • 在某个方法上添加了@ModelAttribute注解后,这个方法就是前置方法。在调用该Handler的任何一个方法时,都会先调用这个前置方法。
应用实例

  • 修改VoteHandler.java,增加方法,并测试。
    1. @RequestMapping(value = "/vote09")
    2. public String test09() {
    3.     System.out.println("test09被调用...");
    4.     return "vote_ok";
    5. }
    6. @RequestMapping(value = "/vote10")
    7. public String test10() {
    8.     System.out.println("test10被调用...");
    9.     return "vote_ok";
    10. }
    11. /**
    12. * 1.当 Handler的一个方法被 @ModelAttribute 修饰时,这个方法就是前置方法
    13. * 2.该 Handler中的其他方法被调用时,都会先调用这个前置方法
    14. * 3.类似spring的aop的前置通知
    15. * 4.前置方法会切入到其他方法前执行[底层还是aop机制]
    16. */
    17. @ModelAttribute
    18. public void prepareModel() {
    19.     System.out.println("prepareModel()---完成准备工作");
    20. }
    复制代码
  • 分别在浏览器中方法test09,test10方法

  • 后台输出:可以看到每次目标方法被访问前,都会调用前置方法prepareModel()

3.2@ModelAttribute的最佳实践


  • 修改用户信息(就是这种机制的经典应用),流程如下:

    • 在修改前,在前置方法中从数据库查出这个用户的数据
    • 在修改方法(目标方法)中,可以使用前置方法的(从数据库查出的)用户数据
    • 如果表单中对用户的某个属性修改了,则以新的数据为准。如果没有修改或不能修改,就以前置方法查出的用户数据为准,就保持原来的值。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表