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

模型数据处理-数据放入 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)跳转成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/19489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用dockerfile快速构建一个带ssh的docker镜像

不多说先给代码 FROM ubuntu:22.04 # 基础镜像 可替换为其他镜像 USER root RUN echo root:root |chpasswd RUN apt-get update -y \&& apt-get install -y git wget curl RUN apt-get install -y openssh-server vim && apt clean \&& rm -rf /tmp/…

在SpringBoot项目中实现切面执行链功能

1.定义切面执行链顶级接口 AspectHandler /*** 切面执行链**/ public interface AspectHandler {/*** 设置排除项* param excludes*/default void setExcludes(List<String> excludes) {}/*** 获取排除项* return*/default List<String> getExcludes() {return ne…

事务与并发控制

事务&#xff08;Transaction0&#xff09;&#xff1a;要么全做&#xff0c;要么全不做&#xff1b; 事务ACID&#xff1a;原子性Atomicity&#xff1b;一致性Consistency&#xff1b;隔离性Isolation&#xff1b;持久性Durability&#xff1b; 并发操作问题&#xff1a; 1.…

基于RNN和Transformer的词级语言建模 代码分析 _generate_square_subsequent_mask

基于RNN和Transformer的词级语言建模 代码分析 _generate_square_subsequent_mask flyfish Word-level Language Modeling using RNN and Transformer word_language_model PyTorch 提供的 word_language_model 示例展示了如何使用循环神经网络RNN(GRU或LSTM)和 Transforme…

汽车IVI中控开发入门及进阶(二十二):video decoder视频解码芯片

前言: 视频解码器在许多汽车、专业和消费视频应用中仍有需求。Analog Devices是模拟视频产品领域的行业领导者,提供一系列视频解码器,可将标准(SD,standard definition)和高清(HD,High definition)分辨率的模拟视频高质量转换为MIPI或TTL格式的数字视频数据。典型的应…

【AI大模型】如何让大模型变得更聪明?基于时代背景的思考

【AI大模型】如何让大模型变得更聪明 前言 在以前&#xff0c;AI和大模型实际上界限较为清晰。但是随着人工智能技术的不断发展&#xff0c;基于大规模预训练模型的应用在基于AI人工智能的技术支持和帮助上&#xff0c;多个领域展现出了前所未有的能力。无论是自然语言处理、…

算法刷题笔记 差分矩阵(C++实现)

文章目录 题目前言题目描述解题思路和代码实现 题目前言 这道题是一道差分算法的拓展题型&#xff0c;是算法刷题笔记到目前为止我认为最困难的题目之一。因此&#xff0c;这篇题解博客的过程记录也最为详细&#xff0c;希望能够为你带来帮助。 题目描述 输入一个n行m列的整…

JavaScript的垃圾回收机制

No.内容链接1Openlayers 【入门教程】 - 【源代码示例300】 2Leaflet 【入门教程】 - 【源代码图文示例 150】 3Cesium 【入门教程】 - 【源代码图文示例200】 4MapboxGL【入门教程】 - 【源代码图文示例150】 5前端就业宝典 【面试题详细答案 1000】 文章目录 一、垃圾…

匹配字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Python提供了re模块&#xff0c;用于实现正则表达式的操作。在实现时&#xff0c;可以使用re模块提供的方法&#xff08;如search()、match()、finda…

深入理解Redis:多种操作方式详解

Redis&#xff08;Remote Dictionary Server&#xff09;是一款高性能的开源键值存储系统&#xff0c;广泛应用于缓存、会话管理、实时分析等领域。它支持多种数据结构&#xff0c;如字符串、哈希、列表、集合和有序集合等&#xff0c;提供了丰富的操作命令。本篇博客将详细介绍…

信息系统项目管理师0603:项目整合管理 — 考点总结(可直接理解记忆)

点击查看专栏目录 文章目录 项目整合管理 — 考点总结(可直接理解记忆) 输入、输出、工具和技术 历年考题直接考输入,输出、工具和技术的有17年11月第34、35,19年5月第34、35,20年11月27、28,21年5月第26,28,21年11月第28,22年5月第25,22年11月第22考题 项目章程是正…

CasaOS玩客云安装全平台高速下载器Gopeed并实现远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

BufferQueue 的工作原理

bufferQueue 是 Android 图形栈中的一个核心组件,它在生产者和消费者之间传递缓冲区(buffer)。它通常用于图形缓冲区管理,特别是在 SurfaceFlinger 和其他图形相关的组件中。理解 BufferQueue 的工作原理对开发高性能图形应用和解决图形渲染问题非常有帮助。 BufferQueue …

基于Python的酒店客房入侵检测系统的设计与实现

基于Python的酒店客房入侵检测系统的设计与实现 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat、Maven 系统功能实现 酒店客房入侵管理界面 结合上文的结构搭建和用户需求&#xff0c;酒店客房入侵检测系统的…

【Unity Shader入门精要 第12章】屏幕后处理效果(一)

1. 原理和过程 屏幕后处理是绑定摄像机的&#xff0c;通过抓取当前摄像机渲染的图像作为 SrcTextrue&#xff0c;然后按需依次调用处理接口&#xff0c;对 SrcTexture 进行处理&#xff0c;最后将处理完成的 DstTexture 显示到屏幕上&#xff0c;整个过程的调度通过 C# 脚本完…

使用 C++ 在当前进程中获取指定模块的基址

C 实现 , 获取指定模块在该进程中的基址 1、流程: 获取进程的所有模块信息–>遍历模块列表 2、实现&#xff1a; // 我自己定义的 typedef struct moudle_date_ {HANDLE mhandle; // 句柄char mname[64]; // 名称char* date; // 数据DWORD mdword; // 基址…

【机器学习】Adaboost: 强化弱学习器的自适应提升方法

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Adaboost: 强化弱学习器的自适应提升方法引言Adaboost基础概念弱学习器与强学习…

存储器容量小才使用SRAM芯片,容量较大时使用DRAM芯片。为什么?

在计算机系统中&#xff0c;存储器容量的选择涉及到多种因素&#xff0c;包括成本、速度和复杂性。SRAM&#xff08;静态随机存取存储器&#xff09;和DRAM&#xff08;动态随机存取存储器&#xff09;是两种常见的内存类型&#xff0c;它们在设计和应用上有显著的不同。以下是…

【蓝桥杯嵌入式】 第六届国赛

目录 题目 配置 注意事项 代码 - 默写大师 EEPROM读写函数 LED驱动函数 ADC采集 上电初始化 LCD 按键 PWM互补输出 全部代码 hardware.c hardware.h control.c control.h main.c 题目 配置 注意事项 复制LCD的工程&#xff0c;先配置资源 --- 勾选完选项一…

CCIG 2024:合合信息文档解析技术突破与应用前景

目录 背景当前大模型训练和应用面临的问题训练Token耗尽训练语料质量要求高LLM文档问答应用中文档解析不精准 合合信息的文档解析技术1. 具备多文档元素识别能力2. 具备版面分析能力3. 高性能的文档解析4. 高精准、高效率的文档解析文档多板式部分示例 文档解析典型技术难点元素…