• SpringMVC框架学习笔记(四):模型数据 以及 视图和视图解析器


    模型数据处理-数据放入 request

    说明:开发中, 控制器/处理器中获取的数据如何放入 request 域,然后在前端(VUE/JSP/...)取出显 示

    1.1 方式 1: 通过 HttpServletRequest 放入 request

    (1)前端发送请求

    1. <h1>添加主人信息</h1>
    2. <form action="vote/vote05" method="post">
    3. 主人号:<input type="text" name="id"><br>
    4. 主人名:<input type="text" name="name"><br>
    5. 宠物号:<input type="text" name="pet.id"><br>
    6. 宠物名:<input type="text" name="pet.name"><br>
    7. <input type="submit" value="添加主人和宠物">
    8. </form>

    (2)后端接收请求

    springmvc会自动把获取的model模型,放入到request域中

    1. /**
    2. * 1. 将提交的数据封装到java对象->springmvc 会自动的将其放入到request域
    3. * 2. 这样我们就可以在跳转到的页面取出数据.
    4. */
    5. @RequestMapping(value = "/vote05")
    6. public String test05(Master master, HttpServletRequest request) {
    7. //1. springmvc会自动把获取的model模型,放入到request域中,名字就是master
    8. //2. 也可以手动将master放入到request
    9. request.setAttribute("address", "beijing");
    10. //3. 如果我们希望修改master的属性值
    11. master.setName("nono");
    12. //4. 分析一下springmvc默认存放对象到request域中,属性名是
    13. // request域 ("master", master) 属性名是类名/类型名 首字母小写
    14. //返回到一个结果
    15. return "vote_ok";
    16. }

    (3)跳转页面

    1. <h1>获取的的数据显示页面</h1>
    2. <hr>
    3. 取出 request域的数据-通过 el表达式来获取
    4. <br>
    5. address: ${requestScope.address}<br>
    6. 主人名字= ${requestScope.master.name}
    7. 主人id= ${requestScope.master.id}
    8. 宠物名字= ${requestScope.master.pet.name}

    (4)页面显示结果

    1.2 方式 2: 通过请求的方法参数 Map 放入 request

    (1)前端发送请求

    1. <h1>添加主人信息[测试 Map ]</h1>
    2. <form action="vote/vote06" method="post">
    3. 主人号:<input type="text" name="id"><br>
    4. 主人名:<input type="text" name="name"><br>
    5. 宠物号:<input type="text" name="pet.id"><br>
    6. 宠物名:<input type="text" name="pet.name"><br>
    7. <input type="submit" value="添加主人和宠物">
    8. </form>

    (2)后端接收请求

    1. /**
    2. * 通过Map 设置数据到request域
    3. */
    4. @RequestMapping(value = "/vote06")
    5. public String test06(Master master, Map<String, Object> map) {
    6. //1. 需求是通过map对象,添加属性到request中
    7. //2. 原理分析:springmvc会遍历map,然后将map的k-v, 存放到request域
    8. map.put("address", "beijing...");
    9. //返回到一个结果
    10. return "vote_ok";
    11. }

    (3)跳转页面同方式1

    (4)页面显示结果

    1.3 方式 3: 通过返回 ModelAndView 对象 实现 request 域数据

    (1)前端发送请求

    1. <h1>添加主人信息[测试ModelAndView]</h1>
    2. <form action="vote/vote07" method="post">
    3. 主人号:<input type="text" name="id"><br>
    4. 主人名:<input type="text" name="name"><br>
    5. 宠物号:<input type="text" name="pet.id"><br>
    6. 宠物名:<input type="text" name="pet.name"><br>
    7. <input type="submit" value="添加主人和宠物">
    8. </form>

    (2)后端接收请求

    说明:

    • 从本质看,请求响应的方法 return "xx", 是返回了一个字符串,其实本质是返回了一个 ModelAndView 对象,只是默认被封装起来的.
    • ModelAndView 即可以包含 model 数据,也可以包含视图信息
    • ModelAndView 对象的 addObject 方法可以添加 key-val 数据,默认在 request 域中
    • ModelAndView 对象 setView 方法可以指定视图名称
    1. /**
    2. * 通过返回ModelAndView对象,将数据放入到request域
    3. */
    4. @RequestMapping(value = "/vote07")
    5. public ModelAndView test07(Master master) {
    6. System.out.println("----test07----");
    7. ModelAndView modelAndView = new ModelAndView();
    8. //放入属性到modelAndView对象
    9. modelAndView.addObject("address", "shanghai");
    10. //可以把从数据库得到的数据->对象,放入modelAndView
    11. //这里指定跳转的视图名称
    12. modelAndView.setViewName("vote_ok");
    13. //返回结果
    14. return modelAndView;
    15. }

    (3)跳转页面同方式1

    (4)页面显示结果

    2 模型数据处理-数据放入 session

    说明:开发中, 控制器/处理器中获取的数据如何放入 session 域,然后在前端(VUE/JSP/...)取出显 示

    应用实例:

    (1)前端发送请求

    1. <h1>添加主人信息[测试session]</h1>
    2. <form action="vote/vote08" method="post">
    3. 主人号:<input type="text" name="id"><br>
    4. 主人名:<input type="text" name="name"><br>
    5. 宠物号:<input type="text" name="pet.id"><br>
    6. 宠物名:<input type="text" name="pet.name"><br>
    7. <input type="submit" value="添加主人和宠物">
    8. </form>

    (2)后端接收请求

    1. /**
    2. * 将数据设置到session域中
    3. */
    4. @RequestMapping(value = "/vote08")
    5. public String test08(Master master, HttpSession httpSession) {
    6. System.out.println("----test08----");
    7. //master对象是默认放在request域
    8. //这里将master对象放入到session域
    9. httpSession.setAttribute("master", master);
    10. httpSession.setAttribute("address", "guangzhou");
    11. return "vote_ok";//请求转发
    12. }

    (3)跳转页面

    1. 取出 session域的数据 <br>
    2. address: ${sessionScope.address}<br>
    3. 主人名字= ${sessionScope.master.name}
    4. 主人信息= ${sessionScope.master}

    (4)页面显示结果

    3 @ModelAttribute 实现 prepare 方法

    说明:开发中,有时需要使用某个前置方法(比如 prepareXxx(), 方法名由程序员定)给目标方法准 备一个模型对象

    @ModelAttribute 注解可以实现 这样的需求,在某个方法上,增加了@ModelAttribute 注解后 那么在调用该 Handler 的任何一个方法时,都会先调用这个方法

    案例:

    1. /**
    2. * 1. 当Handler的方法被标识 @ModelAttribute,就视为一个前置方法
    3. * 2. 当调用该Handler的其它的方法时,都会先执行该前置方法
    4. * 3. 类似Spring中AOP的前置通知[底层是AOP机制]
    5. * 4. prepareModel前置方法,会切入到其它方法前执行
    6. */
    7. @ModelAttribute
    8. public void prepareModel(){
    9. System.out.println("prepareModel()-----完成准备工作-----");
    10. }

    使用场景举例:

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

    1. 在修改前,在前置方法中从数据库查出这个用户

    2. 在修改方法(目标方法)中,可以使用前置方法从数据库查询的用户

    3. 如果表单中对用户的某个属性修改了,则以新的数据为准,如果没有修改,则以数据库 的信息为准,比如,用户的某个属性不能修改,就保持原来的值 

    4 视图和视图解析器

    4.1 基本介绍

    (1)在 springMVC 中的目标方法最终返回都是一个视图(有各种视图).

    (2)返回的视图都会由一个视图解析器来处理 (视图解析器有很多种)

    4.2 自定义视图

    4.2.1 为什么需要自定义视图

    (1)在默认情况下,我们都是返回默认的视图, 然后这个返回的视图交由 SpringMVC 的 InternalResourceViewResolver 视图处理器来处理的

    1. <!--下面配置springMVC的视图解析器,如果我们的controller return 的是 login_ok
    2. 那么要跳转的页面页面就是 /WEB-INF/pages/login_ok-->
    3. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    4. <!--配置属性suffix(后缀) 和 prefix(前缀)-->
    5. <property name="prefix" value="/WEB-INF/pages/"/>
    6. <property name="suffix" value=".jsp"/>
    7. </bean>

    (2)在实际开发中,我们有时需要自定义视图,这样可以满足更多更复杂的需求.

    4.2.2 自定义视图实例-代码实现

    (1)配置 applicationContext-mvc, 增加自定义视图解析器

    1. <!--
    2. 1. 配置自定义视图解析器BeanNameViewResolver
    3. 2. BeanNameViewResolver可以去解析我们自定义的视图
    4. 3. 配置 属性 order, 表示视图解析器执行的顺序, 值越小, 优先级越高
    5. 4. 属性 order 的默认值是最低优先级 ,值为 Integer.MAX_VALUE
    6. int LOWEST_PRECEDENCE = 2147483647
    7. -->
    8. <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
    9. <property name="order" value="99"/>
    10. </bean>

    (2)创建 MyView.java - 自定义视图类

    1. package com.web.viewresolver;
    2. import org.springframework.stereotype.Component;
    3. import org.springframework.web.servlet.view.AbstractView;
    4. import javax.servlet.http.HttpServletRequest;
    5. import javax.servlet.http.HttpServletResponse;
    6. import java.util.Map;
    7. /**
    8. * 1. MyView继承了AbstractView, 就可以作为一个视图使用
    9. * 2. @Component(value = "myView"),该视图会注入到容器中, 名字/id是 myView
    10. */
    11. @Component(value = "myView")
    12. public class MyView extends AbstractView {
    13. @Override
    14. protected void renderMergedOutputModel(Map<String, Object> model,
    15. HttpServletRequest request,
    16. HttpServletResponse response) throws Exception {
    17. //完成视图渲染
    18. //并且可以确定我们要跳转的页面 [请求转发]
    19. System.out.println("进入到自己的视图..");
    20. //1. 下面就是进行请求转发到 /WEB-INF/pages/my_view.jsp
    21. //2. /WEB-INF/pages/my_view.jsp 会被springmvc解析成 /springmvc/WEB-INF/pages/my_view.jsp
    22. request.getRequestDispatcher("/WEB-INF/pages/my_view.jsp")
    23. .forward(request, response);
    24. }
    25. }

    (3)创建 GoodsHandler.java

    1. @RequestMapping("/goods")
    2. @Controller
    3. public class GoodsHandler {
    4. @RequestMapping(value = "/buy")
    5. public String buy() {
    6. System.out.println("------buy()-----");
    7. // 这里返回自定义视图类在容器中的名字/id
    8. return "myView";
    9. }
    10. }

    (4)创建 web\view.jsp 和 /WEB-INF/pages/my_view.jsp 

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>自定义视图测试</title>
    5. </head>
    6. <body>
    7. <h1>自定义视图测试</h1>
    8. <a href="goods/buy">点击到自定义视图-</a><br/>
    9. <a href="goods/order">测试在目标方法中指定请求转发或者重定向的页面-</a><br/>
    10. </body>
    11. </html>
    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>my_view页面</title>
    5. </head>
    6. <h1>进入到my_view页面</h1>
    7. <p>是从自定义视图来的..</p>
    8. <body>
    9. </body>
    10. </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)默认返回的方式是请求转发,然后用视图处理器进行处理,比如在目标方法中这样写:

    1. @RequestMapping(value = "/login")
    2. public String login(){
    3. System.out.println("login ok....");
    4. return "login_ok";
    5. }

    (2)也可以在目标方法直接指定重定向或转发的 url 地址

    (3)如果指定重定向,不能定向到 /WEB-INF 目录中,因为这个目录是tomcat的一个类路径

    4.3.2 应用实例

    (1)修改 GoodsHandler.java, 增加方法 order() 

    1. /**
    2. * 演示直接指定要请求转发的或者是重定向的页面
    3. */
    4. @RequestMapping(value = "/order")
    5. public String order() {
    6. System.out.println("=======order()=====");
    7. //请求转发到 /WEB-INF/pages/my_view.jsp
    8. //forward 关键字表示请求转发
    9. //请求转发可以到/WEB-INF/ 目录下,也可以转发到这个目录外面的页面
    10. //下面的 /WEB-INF/pages/my_view.jsp 会被解析成 /springmvc/WEB-INF/pages/my_view.jsp
    11. //return "forward:/WEB-INF/pages/my_view.jsp"; // 等价于 return "my_view.jsp"
    12. //请求转发到/WEB-INF/目录外面的页面
    13. //return "forward:/aaa/bbb/ok.jsp";
    14. //直接指定要重定向的页面
    15. //1. 对于重定向来说,可以重定向到web目录,不能重定向到 /WEB-INF/ 目录下
    16. //2. redirect 关键字,表示进行重定向
    17. //3. /login.jsp 在服务器解析 /springmvc/login.jsp
    18. return "redirect:/login.jsp";
    19. // /WEB-INF/pages/my_view.jsp 被解析 /springmvc/WEB-INF/pages/my_view.jsp 该路径是访问不到的
    20. //return "redirect:/WEB-INF/pages/my_view.jsp";//这样写会报错
    21. }

     (2)前端发出请求

    <a href="goods/order">测试在目标方法中指定请求转发或者重定向的页面-</a><br/>

     (3)跳转页面

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <html>
    3. <head>
    4. <title>登录成功</title>
    5. </head>
    6. <body>
    7. <h1>恭喜 登录成功</h1>
    8. </body>
    9. </html>

    (4)跳转成功

  • 相关阅读:
    【spring和容器系列】spring bean
    基于Android的校园好帮手app的设计与实现
    算法leetcode|79. 单词搜索(rust重拳出击)
    liunx配置ssh免密登录
    css如何将border线加到元素内部,占内边距,不占外边距
    【2023高教社杯】C题 蔬菜类商品的自动定价与补货决策 问题分析、数学模型及python代码实现
    作业来了~~~
    Vue2 零基础入门 Vue2 零基础入门第二天 2.1 vue简介 && 2.2 vue的基本使用 && 2.3 vue的调试工具
    中国移动物联网开放平台OneNET学习笔记(2)——设备接入测试(MQTT协议)OneNET Studio篇
    内行看门道,外行看热闹。阿里 P8 大咖离职带出内网专属“高并发系统设计”学习笔记,涨薪跳槽 10k 不成问题吧?
  • 原文地址:https://blog.csdn.net/2301_76144723/article/details/139333501