SpringMVC笔记--5处理响应数据ModelAndView

第5章 处理响应数据

5.1 SpringMVC 输出模型数据概述

对于MVC框架来说模式数据是最重要的,因为控制C是为了产生模型数据M,而视图V则是为了渲染模型数据。

如何将模型数据暴露给视图是Spring MVC框架的一项重要工作,Spring MVC提供了多种途径输出模型数据

  • ModelAndView: 处理方法返回值类型为 ModelAndView 时, 方法体即可通过该对象添加模型数据
  • @ModelAttribute:方法入参标准该注解后,入参的对象就会放到数据模型中
  • Map及Model: 入参为 org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 时,处理方法返回时,Map 中的数据会自动添加到模型中。
  • @SessionAtributes:将模型中的某个属性暂存到HttpSession中,以便多个请求之间可以共享这个属性。

5.2 处理模型数据之ModelAndView

5.2.1 ModelAndView介绍

1)控制器处理方法的返回值如果为 ModelAndView,则其既包含视图信息,也包含模型数据信息。这样Spring MVC就可以使用视图对模型数据进行渲染了。可以简单地将模型数据看成一个Map<String,Object>对象

构造器的有参无参   有参写法:ModelAndView mv = new ModelAndView(viewName );无参写法:ModelAndView mav = new ModelAndView();mav.setViewName("success");//设置视图信息

2)添加模型数据:

MoelAndView addObject(String attributeName, Object attributeValue)
ModelAndView addAllObject(Map<String, ?> modelMap)

3)设置视图:

void setView(View view)//指定一个具体的视图对象
void setViewName(String viewName)//指定一个逻辑视图名//返回逻辑地址

5.2.2 实验代码

1) 增加控制器方法

/*** 目标方法的返回类型可以是ModelAndView类型*                 其中包含视图信息和模型数据信息 结论: Springmvc会把ModelAndView中的模型数据存放到request域对象中.*/
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){System.out.println("testModelAndView");String viewName = "success";//设置到了ModelAndView中ModelAndView mv = new ModelAndView(viewName );mv.addObject("time",new Date().toString()); //实质上存放到request域中 return mv;
}/*  @ModelAttribute的用法:
Spring MVC将请求消息绑定到User对象中,然后再以"user:user对象"为键值对放到模型中。在准备对视图进行渲染前,Spring MVC还会进一步将模型中的数据转储到视图的上下文中以暴露给视图对象。对于JSP视图来说,Spring MVC会将模型数据转储到ServletRequest的属性列表中(即通过ServletRequest#setAttribute(String name,Object o)保存)*/
@RequestMapping("/testModelAndView1")
public ModelAndView testModelAndView1(@ModelAttribute("user") User user){System.out.println("testModelAndView1");return "success";
}
/*也可以在方法上标@ModelAttribute,此时Spring MVC在调用目标处理方法前,会先逐个调用在方法级上标准了@ModelAttribute的方法,并将这些方法的返回值添加到模型中。*/
@ModelAttribute("user")//返回的健名
public User getUser(){User user = new User();user.setUseId("1001");return user;
}
@RequestMapping("/testModelAndView2")
public ModelAndView testModelAndView2(@ModelAttribute("user") User user){System.out.println("testModelAndView2");return "success";
}

2) 增加页面链接

<!--测试 ModelAndView 作为处理返回结果 -->
<a href="springmvc/testModelAndView">testModelAndView</a>

3) 增加成功页面,显示数据

time: ${requestScope.time }

4) 断点调试

5.2.2 源码解析

5.3 处理模型数据之 Map

5.3.1 Map介绍

Spring MVC在内部使用了

1)Spring MVC 在内部使用了一个 org.springframework.ui.Model 接口存储模型数据,他的功能类似于java.util.Map,但它比Map易用。org.springframework.ui.ModelMap实现了Map接口,而org.springframework.ui.ExtendedModelMap扩展于ModelMap同时实现了Model接口。

2)Spring MVC在调用方法前会创建一个隐含的模型对象作为模型数据的存储容器。

3)如果方法的入参为 Map或 Model类型,Spring MVC 会将隐含模型的引用传递给这些入参。

4)在方法体内,开发者可以通过这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据

Spring MVC在调用方法之前会创建一个隐含的模型对象,作为模型数据的存储容器,我们称之为“隐含模型”。如果处理方法的入参为Map或Model模型,Spring MVC会将隐含模型的引用传递给这些入参。在方法体内,开发者可以同这个入参对象访问到模型中的所有数据,也可以向模型中添加新的属性数据。

5.3.2 实验代码

1) 增加控制器方法

//目标方法的返回类型也可以是一个Map类型参数(也可以是Model,或ModelMap类型)
@RequestMapping("/testMap")
public String testMap(Map<String,Object> map){ //【重点】System.out.println(map.getClass().getName());//org.springframework.validation.support.BindingAwareModelMapmap.put("names", Arrays.asList("Tom","Jerry","Kite"));return "success";
}

2) 增加页面链接

<!-- 测试 Map 作为处理返回结果 -->
<a href="springmvc/testMap">testMap</a>

3) 增加成功页面,显示结果

names: ${requestScope.names }

4) 显示结果截图

5) 注意问题:Map集合的泛型,key为String,Value为Object,而不是String

6) 测试参数类型

//目标方法的返回类型也可以是一个Map类型参数(也可以是Model,或ModelMap类型)
@RequestMapping("/testMap2")
public String testMap2(Map<String,Object> map,Model model,ModelMap modelMap){System.out.println(map.getClass().getName());map.put("names", Arrays.asList("Tom","Jerry","Kite"));model.addAttribute("model", "org.springframework.ui.Model");modelMap.put("modelMap", "org.springframework.ui.ModelMap");System.out.println(map == model);System.out.println(map == modelMap);System.out.println(model == modelMap);System.out.println(map.getClass().getName());System.out.println(model.getClass().getName());System.out.println(modelMap.getClass().getName());/*truetruetrueorg.springframework.validation.support.BindingAwareModelMaporg.springframework.validation.support.BindingAwareModelMaporg.springframework.validation.support.BindingAwareModelMap*/ return "success";
}

7) 类层次结构

8) 推荐:Map, 便于框架移植。

9) 源码参考

public class BindingAwareModelMap extends ExtendedModelMap {@Overridepublic Object put(String key, Object value) {removeBindingResultIfNecessary(key, value);return super.put(key, value);}@Overridepublic void putAll(Map<? extends String, ?> map) {for (Map.Entry<? extends String, ?> entry : map.entrySet()) {removeBindingResultIfNecessary(entry.getKey(), entry.getValue());}super.putAll(map);}private void removeBindingResultIfNecessary(Object key, Object value) {if (key instanceof String) {String attributeName = (String) key;if (!attributeName.startsWith(BindingResult.MODEL_KEY_PREFIX)) {String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attributeName;BindingResult bindingResult = (BindingResult) get(bindingResultKey);if (bindingResult != null && bindingResult.getTarget() != value) {remove(bindingResultKey);}}}}
}

放到session里:

在控制器(类)上加@SessionAttributes(value={“user”}),既放在session里面,也放在请求域里面

Model

	/*** Model*/@RequestMapping("/testModel")public String testModel(Model model) {//模型数据 : loginMsg=用户名或者密码错误model.addAttribute("loginMsg", "用户名或者密码错误");return "success";}

@ SessionAttributes

如果希望在多个请求之间共用某个模型属性数据,则可以在控制器类标注一个@SessionAttributes,Spring MVC会将模型中对应的属性暂存到HttpSession中。

在类上标准@SessionAttributes(“user”),然后类中某个方法的参数是@ModelAttribute("user") User user,此时就会把这个方法中的参数变为全局都可以获得的参数,别的方法获取方式为modelMap.get("user");

整合代码

package com.atguigu.springmvc.handler;import java.util.Map;import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;@Controller
public class SpringmvcHandler {/*** 重定向*/@RequestMapping("/testRedirectView")public String testRedirectView() {return "redirect:/ok.jsp";}/*** 视图 View*/@RequestMapping("/testView")public String testView() {return "success";}/*** Model*/@RequestMapping("/testModel")public String testModel(Model model) {//模型数据 : loginMsg=用户名或者密码错误model.addAttribute("loginMsg", "用户名或者密码错误");return "success";}/*** Map* 结论: SpringMVC会把Map中的模型数据存放到request域对象中.*      SpringMVC再调用完请求处理方法后,不管方法的返回值是什么类型,都会处理成一个ModelAndView对象(参考DispatcherServlet的945行)* */		@RequestMapping("/testMap")public String  testMap(Map<String,Object> map ) {//模型数据: password=123456System.out.println(map.getClass().getName()); //BindingAwareModelMapmap.put("password", "123456");return "success";}/*** ModelAndView* 结论: Springmvc会把ModelAndView中的模型数据存放到request域对象中.*/@RequestMapping("/testModelAndView")public  ModelAndView  testModelAndView() {//模型数据: username=AdminModelAndView mav = new ModelAndView();//添加模型数据mav.addObject("username", "Admin");//设置视图信息mav.setViewName("success");return mav ;}
}

使用spring ResponseEntity处理http响应

简介

使用spring时,达到同一目的通常有很多方法,对处理http响应也是一样。本文我们学习如何通ResponseEntity设置http相应内容、状态以及头信息。

ResponseEntity

ResponseEntity标识整个http相应:状态码、头部信息以及相应体内容。因此我们可以使用其对http响应实现完整配置。

如果需要使用ResponseEntity,必须在请求点返回,通常在spring rest中实现。ResponseEntity是通用类型,因此可以使用任意类型作为响应体:

@GetMapping("/hello")
ResponseEntity<String> hello() {return new ResponseEntity<>("Hello World!", HttpStatus.OK);
}

可以通过编程方式指明响应状态,所以根据不同场景返回不同状态:

@GetMapping("/age")
ResponseEntity<String> age(@RequestParam("yearOfBirth") int yearOfBirth) {if (isInFuture(yearOfBirth)) {return new ResponseEntity<>("Year of birth cannot be in the future", HttpStatus.BAD_REQUEST);}return new ResponseEntity<>("Your age is " + calculateAge(yearOfBirth), HttpStatus.OK);
}

另外,还可以设置http响应头:

@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {HttpHeaders headers = new HttpHeaders();headers.add("Custom-Header", "foo");return new ResponseEntity<>("Custom header set", headers, HttpStatus.OK);}

而且, ResponseEntity提供了两个内嵌的构建器接口: HeadersBuilder 和其子接口 BodyBuilder。因此我们能通过ResponseEntity的静态方法直接访问。

最简单的情况是相应包括一个主体及http 200响应码:

@GetMapping("/hello")
ResponseEntity<String> hello() {return ResponseEntity.ok("Hello World!");
}

大多数常用的http 响应码,可以通过下面static方法:

BodyBuilder accepted();
BodyBuilder badRequest();
BodyBuilder created(java.net.URI location);
HeadersBuilder<?> noContent();
HeadersBuilder<?> notFound();
BodyBuilder ok();

另外,可以能使用BodyBuilder status(HttpStatus status)和BodyBuilder status(int status) 方法设置http状态。使用ResponseEntity BodyBuilder.body(T body)设置http响应体:

@GetMapping("/age")
ResponseEntity<String> age(@RequestParam("yearOfBirth") int yearOfBirth) {if (isInFuture(yearOfBirth)) {return ResponseEntity.badRequest().body("Year of birth cannot be in the future");}return ResponseEntity.status(HttpStatus.OK).body("Your age is " + calculateAge(yearOfBirth));

也可以自定义头信息:

@GetMapping("/customHeader")
ResponseEntity<String> customHeader() {return ResponseEntity.ok().header("Custom-Header", "foo").body("Custom header set");
}

因为BodyBuilder.body()返回ResponseEntity 而不是 BodyBuilder,需要最后调用。注意使用HeaderBuilder 不能设置任何响应体属性。

尽管ResponseEntity非常强大,但不应该过度使用。在一些简单情况下,还有其他方法能满足我们的需求,使代码更整洁。

替代方法

@ResponseBody

典型spring mvc应用,请求点通常返回html页面。有时我们仅需要实际数据,如使用ajax请求。这时我们能通过@ResponseBody注解标记请求处理方法,审批人能够处理方法结果值作为http响应体。

@ResponseStatus

当请求点成功返回,spring提供http 200(ok)相应。如果请求点抛出异常,spring查找异常处理器,由其返回相应的http状态码。对这些方法增加@ResponseStatus注解,spring会返回自定义http状态码。

直接操作相应
Spring 也允许我们直接 javax.servlet.http.HttpServletResponse 对象;只需要申明其作为方法参数:

@GetMapping("/manual")
void manual(HttpServletResponse response) throws IOException {response.setHeader("Custom-Header", "foo");response.setStatus(200);response.getWriter().println("Hello World!");
}

但需要说明,既然spring已经提供底层实现的抽象和附件功能,我们不建议直接操作response。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

浅入浅出 iptables 网络隔离原理

01 iptables简介 iptables ipfirewall&#xff08;内核1.x时代&#xff09; ipchains&#xff08;内核2.x时代&#xff09; iptables 网络协议栈 Link Layer 数据链路层的数据流向&#xff0c;根据mac寻址找到对应的网卡后向上进入网络层 Network Layer 网络层的数据流向&am…

ModelAndView 详解

当控制器处理完请求时&#xff0c;通常会将包含视图名称或视图对象以及一些模型属性的ModelAndView对象返回到DispatcherServlet。 因此&#xff0c;经常需要在控制器中构造ModelAndView对象。ModelAndView类提供了几个重载的构造器和一些方便的方法&#xff0c; 让你可以根据…

ModelAndView

ModelAndView 前提 首先梳理一下Spring Web MVC处理http请求的大致过程&#xff1a; 当http请求到来时&#xff0c;DispatcherServlet负责将请求进行分发。DispatcherServlet可以认为是Spring提供的前端控制器&#xff0c;所有的请求都要经过它来统一分发。 在DispatchServle…

SpringMVC中的Model和ModelAndView详解

原文链接&#xff1a; 0.前言 1.Model是什么? model是”模型“的意思&#xff0c;是MVC架构中的”M“部分&#xff0c;是用来传输数据的。 2.ModelAndView是什么&#xff1f; 如果翻译过来就是”模型和视图“&#xff0c;可以理解成MVC架构中的”M“和”V“&#xff0c;其…

5.1 - Web漏洞 - XSS漏洞详解

「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 XSS漏洞 一、什么是XSS&#xff1f;二、XSS概述三、靶场练习四、XSS使用步骤五、XSS攻击类…

影响代理ip纯净度的原因及目标网站如何识别代理ip

网络上代理ip很多&#xff0c;但真正可以为我们所用的大部分都是付费ip&#xff0c;那为什么免费ip不能为我们所用呢&#xff1f;下面我们就纯净度和目标网站是如何识别代理ip来分析一下。 一、纯净度 ip纯净度是什么意思呢&#xff1f;简单一点开始就是指使用这个ip的人少&…

如果你当架构师,从0开始,如何做一个后台项目的架构?

前言 在40岁老架构师 尼恩的读者社群(50)中&#xff0c;很多小伙伴要拿高薪&#xff0c;这就要面试架构师&#xff0c;要完成架构的升级&#xff0c;进入架构赛道。 在架构师的面试过程中&#xff0c;常常会遇到下面的问题&#xff1a; 如果给你一个项目要你从0到1做架构&…

数字化艺术时代的新趋势:虚拟数字展厅的崛起

引言&#xff1a; 艺术与技术的融合正带领我们进入一个全新的数字化艺术时代。在这个时代中&#xff0c;虚拟数字展厅正在以惊人的速度崛起&#xff0c;并引领着展览的新趋势。 一&#xff0e;虚拟数字展厅的定义和特点 虚拟数字展厅是一种基于虚拟现实和全景技术的数字化艺术…

pycharm2018如何关闭自动更新提示

1.点击左上角File,如图进入Settings(或者按CtrlAlts) 2.搜索到updates选项,把Automatically check updates for(自动检查更新以…规则) 前面够选去掉即可.

两天搞定计算机专业毕业设计,附源码

两天搞定计算机专业毕业设计&#xff0c;附源码 适用者毕设专业 使用要求具备基本Unity 基本操作小白即可&#xff0c;无需编码 博主诉求快乐毕业 点赞 关注 收藏 资源说明Free资源太多了&#xff0c;看截图目录就知道了 适用者 毕设专业 鄙人也是计算机狗一只&#xff0c;会…

电脑关闭自动更新

1.winr 打开运行窗口输出services.msc,点击确定 2.在服务窗口中&#xff0c;我们找到Windows update选项,双击打开 3.在启动类型选择禁用 4.点击上面的恢复&#xff0c;在恢复选项里面&#xff0c;我们把第一、第二、后续失败&#xff0c;都改为无操作&#xff0c;后点击应用…

ubuntu20关闭自动更新

1、在GUI上关闭自动更新。设置-关于-软件更新-更新&#xff0c;能关的关&#xff0c;不能关的改成最低频率。 2、阻止软件更新弹窗&#xff08;眼不见为净~&#xff09; 打开终端执行命令&#xff1a; sudo chmod a-x /usr/bin/update-notifier 如果想恢复弹窗执行下面的命令…

vscode配置html页面自动刷新,Vscode关闭自动更新设置

如何关闭Vscode自动更新&#xff1f; 有时侯在使用Vscode时会发现自己都不知道它就自已更新了&#xff0c;如何关闭Vscode的自动更新呢&#xff1f;下面介绍一下关闭Vscode自动更新的方法步骤&#xff1a; 打开Vscode&#xff0c;点击文件》首选项》设置&#xff0c;在打开的设…

关闭Postman v5.0自动更新

Postman大约每1个月&#xff0c;就会在后台更新一次&#xff0c;这种更新是可以屏蔽的。 在Postman的[设置]页面 --> Update —> Disable 即可&#xff0c;如图(1)所示。 图(1) 设置自动更新为Disabled 需要说明的是&#xff0c;此操作只对Postman v5.0以下的版本有效&am…

Chrome浏览器如何关闭自动更新

首先是【右键计算机->管理】&#xff0c;在【计算机管理(本地)->系统工具->任务计划程序->任务计划程序库】中找到两个和Google自动更新相关的任务计划【GoogleUpdateTaskMachineCore】与【GoogleUpdateTaskMachineUA】&#xff0c;并把它俩禁用掉。印象中介绍这方…

Windows Server 2016关闭自动更新

场景描述 平时使用系统时总提示需要更新系统&#xff0c;而更新系统后发现有些功能会出现新的异常&#xff0c;故而关闭自动更新的需求产生&#xff0c;这里介绍如何再Windos server 2016中关闭自动更新~ 解决方法 Step 1&#xff1a;进入cmd&#xff0c;之后输入sconfig St…

eclipse如何关闭自动更新

一、问题描述 eclipse如何关闭自动更新 二、解决方法 1. Window --> Preferences --> General --> Startup and Shutdown -->在列表项里面找到"Automatic Updates Scheduler " 项去掉前面的勾 2. Window --> Preferences --> Myeclips…

windows10 关闭自动更新

暂停自动更新 打开Windows更新的高级选项 win10专业版即以上关闭自动更新 Windows10专业版及其以上版本的操作系统可以使用组策略编辑器&#xff0c;可以在组策略编辑器中配置Windows更新。首先按下winR&#xff0c;在命令窗口中输入“gpedit.msc”&#xff0c;打开组策略编辑…

Chrome浏览器关闭自动更新

背景是&#xff1a; 在用Python抓取的时候&#xff0c;经常会遇到Chrome浏览器版本和Chromedriver版本不一致的情况&#xff0c;为此有必要关闭Chrome的自动更新功能。 1、在Windows电脑桌面上&#xff0c;右键点击“此电脑” -》选择“管理”&#xff0c;弹出下面&#xff1a;…

Intellig idea关闭自动更新

idea关闭自动更新 idea是java编程语言开发的集成环境。IntelliJ在业界被公认为最好的java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超常的。 IDEA是…