学习SpringMVC必知必会(3)~springmvc的请求和响应
一、处理器方法响应处理
▷ Controller方法该怎么返回、Controller数据该怎么进行共享
- 返回void/ModelAndView/String
 
1、Controller方法返回void
	//返回void类型,此时可以把Controller方法当做Servlet使用【适合用来下载文件】
	@RequestMapping("/test1")
	public void test(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//请求转发
		request.getRequestDispatcher("/WEB-INF/views/welcome.jsp").forward(request, response);
		//设置共享数据
		request.setAttribute("msg", "hello");
		//输出json格式
		response.setContentType("text/json;charset=utf-8");
		response.getWriter().println();
	}
2、【常用】返回ModelAndView
	//返回ModelAndView
	@RequestMapping("/test3")
	public ModelAndView test3() {
		ModelAndView mv = new ModelAndView();
		//设置视图名称
//		mv.setViewName("/WEB-INF/views/welcome.jsp");
		mv.setViewName("welcome");
		mv.addObject("msg", "返回ModelNAndView");//设置共享数据的key和value
		mv.addObject("叩丁狼教育");//设置共享数据的value,此时会把value类型的首字母作为key:string
		return mv;
	}
3、【常用】返回String类型(是逻辑视图名称),参数是Model类型(是共享数据)
	//返回string,逻辑视图名称,此时需要结合参数Model类型 一起使用
	@RequestMapping("/test4")
	public String test4(Model model) {
		//设置共享数据
		model.addAttribute("叩丁狼");
		model.addAttribute("msg", "教育");
		return "welcome";//设置跳转的视图
	}
二、请求跳转
- 请求转发、URL重定向、URL重定向共享数据
 
1、请求转发
	//请求转发,浏览器地址栏不变,可以共享请求中的数据
	//原理:request.getRequestDispatcher("").forward(request, response);
	@RequestMapping("/test5")
	public String test5(Model model) {
		return "forward:/hello.jsp";//设置跳转的视图
	}
2、URL重定向
	//重定向,浏览器地址栏改变,不能共享请求中的数据
	//原理:request.sendRedirect("");
	@RequestMapping("/test6")
	public String test6(Model model) {
		return "redirect:/hello.jsp";//设置跳转的视图
	}
■ 请求资源的路径问题:[总结:访问资源的时候,都使用/开头]
- 访问资源的时候前面带上/,表示绝对路径,从
根路径开始去寻找资源 - 访问资源的时候签名不加/,表示相对路径,从
上一级上下文路径中去寻找资源 
✿ 请求转发和URL重定向的选择:
| 请求转发/URL重定向 | 请求转发 | URL重定向 | 
|---|---|---|
| 地址栏改变? | 不会 | 会改变 | 
| 共享数据? | 可以 | 不可以? | 
| 表单重复提交? | 会发生 | 不会发生 | 
传统的方式,在url重定向的时候,因为是两次不同的请求,所以不能共享请求中的数据。
在开发中,有时候真的需要重定向跳转后共享数据------------spring3.1开始,提供了Flash属性。
★
只能是从Controller 重定向到 Controller,不能到jsp
3、URL重定向共享数据
	//重定向:从a跳转到b
	@RequestMapping("/a")
	public String a(RedirectAttributes ra) {
		ra.addAttribute("msg1", "a传递的数据");
		ra.addFlashAttribute("msg2", "msg2");
		return "redirect:/response/b";//设置跳转的视图
	}
	@RequestMapping("/b")
	public ModelAndView b(String msg1, @ModelAttribute("msg2") String msg2) {
		System.out.println("msg1:" + msg1);
		System.out.println("msg2:" + msg2);
		return null;
	}
重定向共享数据的原理:更大的作用域--session

三、处理器方法参数处理(接收请求参数的处理)
- 处理器方法的请求参数该怎么携带、请求参数该怎么获取
 
1、request 和 response 参数
■ 情况一:为了操作Servlet API 对象,此时可以直接以参数形式传递,也可以直接使用DI注入。
@Controller
@RequestMapping("/request")
public class HandlerRequestController {
	@Autowired
	private ServletContext context;
	@RequestMapping("/test1")
	public void test(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws ServletException, IOException {
		System.out.println("request:" + request);
		System.out.println("response:" + response);
		System.out.println("session:" + session);
		System.out.println("ServletContext:" + this.context);
	}
}
- request、response、session:建议使用参数
 - context 上下文:单例,建议使用属性,注入
 
▷ 因为Controller(Servlet) 是单例的,线程不安全,一般不用成员变量,除非要共享的数据,才作为成员变量。
2、简单类型参数
- 处理简单类型的请求参数
 
■ 获取请求参数:【保证输入的参数和定义的形参名称一致】
	//获取请求参数:通过保证请求参数名称和Controller方法定义的形参(入参)同名即可
	@RequestMapping("/test2")
	public void test2(String username, int age)  {
		System.out.println(username);
		System.out.println(age);
	}

■ 获取请求参数:【输入的参数和定义的形参名称不一致】----注解@RequestParam
	//获取请求参数:若请求参数和请求参数名称和形参不同----注解@RequestParam
	@RequestMapping("/test3")
	public void test3(@RequestParam("name") String username, @RequestParam(value="age",required=false) Integer age)  {
		System.out.println("username:" +username);
		System.out.println("age:" + age);
	}
3、中文乱码处理
■ 在"全局配置"【web.xml】,添加上编码过滤器:
	<!-- (针对post请求)配置过滤器 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<!-- 配置初始化参数 -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>utf-8</param-value>
		</init-param>
		<init-param>
			<param-name>forceRequestEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>forceResponseEncoding</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
4、restfull风格传参
- restfull 风格:软件架构风格,严格讲是一种编码风格,充分利用http协议本身的语义,从而提供一些设计原则和约束条件,主要是用来作为客户端和服务端的交互。
 - 简洁、有层次、容易实现缓存机制
 
	//restfull风格传递参数
	//PathVariable: 可以将url中占位符绑定到方法的形参中
	@RequestMapping("/r/{id}")
	public ModelAndView rest(@PathVariable("id") Integer id) {
		System.out.println("id:" + id);
		return null;
	}
5、数组和List类型参数
	//接收一个参数有很多值的情况
	//使用数组:可以直接接收  Long[] ids
	//使用List: 不可以直接接收,可以在对象中存在一个集合   List<Long> ids
	@RequestMapping("/batchDelete") //batchDelete?ids=10&ids=20&ids=30
	public void batchDelete(FormBean fb) {
		System.out.println(fb.getIds());
	}
★ 操作一个参数有多个值的情况,一般直接使用数组接收即可,或者使用javaBean对象来封装数据。
6、■ 获取请求参数:
JavaBean类型参数【将请求参数封装成一个对象】
	//封装成一个对象
	@RequestMapping("/bean") //batchDelete?ids=10&ids=20&ids=30
	public void bean(User user) {
		System.out.println(user);
	}
- 请求参数封装成javaBean对象,浏览器地址栏直接输入参数为对象的属性即可.
 

✿ 总结处理器方法参数处理:
1、直接把请求参数封装成javaBean对象
2、配置解决中文乱码的过滤器
3、简单类型参数----输入参数名和定义的形参不同-> @ResultParam
4、使用数组接收多个参数
5、restfull风格传参
四、ModelAttribute
给共享的model数据设置key名,贴在形参上,也可以贴在方法上,
针对复合类型参数,缺省情况下就会放到model中(共享), 缺省的key就是类型首字母小写
- 使用注解 @ModelAttribute,起个别名
 
	//ModelAttribute注解:
	/*
	 *1、给共享的model数据设置key名,贴在形参上,也可以贴在方法上
	 *	针对复合类型(非简单类型)参数,缺省情况下就会放到model中(共享), 缺省的key就是类型首字母小写
	 * 2、可以标注一个非请求处理的方法,被标注的方法,每次在请求处理方法之前都会优先被执行[存放多个请求需要共享的数据]
	 */
	@RequestMapping("/test11")
	public String test1(@ModelAttribute("u") User user)  {
		System.out.println(user);
		return "welcome";
	}
五、其他请求信息
1、获取请求头   @RequestHeader
	@RequestMapping("/test1")
	public ModelAndView test1(@RequestHeader("User-Agent") String userAgent) {
		System.out.println("test1");
		System.out.println("User-Agent:" + userAgent);
		return null;
	}
2、获取Cookie    @CookieValue
	@RequestMapping("/test1")
	public ModelAndView test1(@RequestHeader("User-Agent") String userAgent, @CookieValue("Webstorm-5895a979") String cName) {
		System.out.println("test1");
		System.out.println("User-Agent:" + userAgent);
		System.out.println("cName:" + cName);
		return null;
	}
3、操作HttpSession   @SessionAttributes
- 默认情况下模型数据是保存到 request 作用域的
 
@Controller
@RequestMapping("/other")
@SessionAttributes("errMsg")
public class OtherController {
	@RequestMapping("/test2")
	public String test2(Model model) {
		System.out.println("操作session");
		model.addAttribute("errMsg", "错误信息");
		return "redirect:/hello.jsp";
	}
}
六、数据绑定流程

1、框架把 ServletRequest 对象和请求参数传递给 DataBinder;
2、DataBinder 首先调用 Spring Web 环境中的 ConversionService 组件,进行数据类型转换和格式化等操作,将 ServletRequest 中的信息填充到形参对象中;
3、DataBinder 然后调用 Validator 组件对已经绑定了请求消息数据的形参对象进行数据合法性校验;
4、DataBinder 最后输出数据绑定结果对象 BindingResult
- BindingResult 包含了已完成数据绑定的形参对象和校验错误信息对象
 
七、多对象封装传参
	/*
	 * 需要吧表单数据封装到多个对象中去,若各个对象有相同的属性时
	 * 不知道该把哪一个参数封装到哪一个对象
	 */
	@RequestMapping("/save")
	public ModelAndView save(Cat cat, Dog dog) {
		System.out.println("提交数据");
		System.out.println(cat);
		System.out.println(dog);
		return null;
	}
- input.jsp 传递多个对象的参数时:
 
	<form action="/save" method="post">
		猫名:<input type="text" name="name" /><br/>
		猫年龄:<input type="text" name="age" /><br/>
		狗名:<input type="text" name="name" /><br/>
		狗年龄:<input type="text" name="age" /><br/>
		<input type="submit" value="提交">
	</form>

解决:
input.jsp:加上前缀做区分
	<form action="/save" method="post">
		猫名:<input type="text" name="cat.name" /><br/>
		猫年龄:<input type="text" name="cat.age" /><br/>
		狗名:<input type="text" name="dog.name" /><br/>
		狗年龄:<input type="text" name="dog.age" /><br/>
		<input type="submit" value="提交">
	</form>
- 处理器Controller添加方法:
 
	//从参数--> 对象,封装规则需要我们来设置
	//自定义数据绑定注册,将请求参数转化成对应对象的属性
	@InitBinder("cat")
	public void initBinderCat(WebDataBinder binder) {
		//设置字段以什么做为前缀
		binder.setFieldDefaultPrefix("cat.");
	}
	@InitBinder("dog")
	public void initBinderDog(WebDataBinder binder) {
		//设置字段以什么做为前缀
		binder.setFieldDefaultPrefix("dog.");
	}

八、JSON数据处理
- JSON处理
 
1、依赖:
- jackson-annotations-2.12.2.jar
 - jackson-core-2.12.2.jar
 - jackson-databind-2.12.2.jar
 
2、处理json的注解  @ResponseBody    @RestController   @RequestBody
(1) @ResponseBody: 处理响应,把对象转化成json字符串
- @ResponseBody 处理响应,把对象转化成json字符串
- 贴到方法上:只会针对当前方法做json处理
 - 贴到类上:会对当前类中所有方法做json处理
 
 
	//把单个对象/Map转化成json格式
	@RequestMapping("/test1")
	@ResponseBody
	public User test1() {
		User u = new User();
		u.setUsername("shan");
		u.setAge(18);
		return u;
	}
	//把多个对象转化成json格式
	@RequestMapping("/test2")
	@ResponseBody
	public List<User> test2() {
		User u = new User();
		u.setUsername("shan");
		u.setAge(18);
		return Arrays.asList(u, u, u);
	}
	//返回一个String,默认返回字符串是逻辑视图名称,加上@ResponseBody,当做json格式的数据
	@RequestMapping(value="/test3", produces="application/json;charset=utf-8")
	@ResponseBody
	public String test3() {
		return "success, 你好~";
	}
(2) @RestController = @Controller + @ResponseBody
(3) @RequestBody
- @RequestBody: 处理请求,用于读取Http请求的内容,把json格式的请求数据封装成对象
- application/x-www-form-urlencoded: 表单提交用得比较多,是传统的key-value格式,处理起来非常方便,无需RequestBody都可以,贴上也可以
 - application/multipart: 文件上传的请求,springmvc 装饰设计模式,既可以处理文件上传,也可以处理表单数据
 - application/json: 参数是json格式的,此时必须使用RequestBody\
 - application/xml
 
 
九、日期类型处理
1、前台往后台传参转化为Date类型
★ 时间格式的注解:@DateTimeFormat
- 注意细节:时间Date在util包(java中常用)有,在sql包也有,使用快捷键导包的时候可能会默认自动报错包~
 
	//从前台---->后台传递参数 java.lang.String -> java.util.Date
	//请求参数是Date类型
	@RequestMapping("/test1")
	public ModelAndView test(@DateTimeFormat(pattern = "yyyy-MM-dd")Date date) {
		System.out.println("date:" + date);
		if(date instanceof Date) {
			System.out.println("yes");
		}
		return null;
	}
对象的属性有时间Date类型的,方式一:贴注解 @DateTimeFormat
◆ 方式二:数据绑定的时候处理,通过@InitBinder定义处理时间格式的方法
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		//日期格式
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		//属性编辑器
		binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
	}
让项目中的所有用到时间格式的类都使用到咱定义的处理时间格式的方法,咱将方法抽离出去,定义成一个类,贴上注解处理增强
@ControllerAdvice,只要抽离的类在ioc的注解驱动扫描范围内,即可~
@ControllerAdvice
public class DateFormateAdvice {
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		//日期格式
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		//属性编辑器
		binder.registerCustomEditor(java.util.Date.class, new CustomDateEditor(sdf, true));
	}
}
2、jsp中显示时间格式:将欧美时间格式-->中国时间格式
(1)导入jar包[tomcat服务器examples案例下的lib就有]:
- taglibs-standard-impl-1.2.5.jar
 - taglibs-standard-spec-1.2.5.jar
 
(2)配置引入标签库taglib
<%@taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
(3) 使用jstl:
	<% pageContext.setAttribute("myDate", new java.util.Date()); %>
	北京时间: <fmt:formatDate value="${myDate}" pattern="yyyy=MM-dd HH:mm:ss"/>

3、后台往前台响应JSON时---Date类型
(1)方法1:在springmvc框架配置中添加json类型转化相关的配置[配置全局解析器]:
	<!-- MVC注解解析器 -->
	<mvc:annotation-driven>
		<mvc:message-converters>
			<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
				<property name="objectMapper">
					<bean class="com.fasterxml.jackson.databind.ObjectMapper">
						<property name="dateFormat">
							<bean class="java.text.SimpleDateFormat">
								<constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
							</bean>
						</property>
					</bean>
				</property>
			</bean>
		</mvc:message-converters>
	</mvc:annotation-driven>
(2)方式2:使用注解@JsonFormat
@Data
public class User {
	private Long id;
	private String username;
	private Integer age;
	//@DateTimeFormat(pattern = "yyyy-MM-dd")
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
	private Date hireDate;
}
★ 注意:@DateTimeFormat 是前台往后台传参【前台String类型-》后台Date类型】
★ 注意: 是后台响应给前台,响应为json格式(对时间Date类型的处理)
如果本文对你有帮助的话记得给一乐点个赞哦,感谢!
学习SpringMVC必知必会(3)~springmvc的请求和响应的更多相关文章
- [ 学习路线 ] 2015 前端(JS)工程师必知必会 (2)
		
http://segmentfault.com/a/1190000002678515?utm_source=Weibo&utm_medium=shareLink&utm_campaig ...
 - 《SQL必知必会》学习笔记二)
		
<SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...
 - 学习《SQL必知必会(第4版)》中文PDF+英文PDF+代码++福达BenForta(作者)
		
不管是数据分析还是Web程序开发,都会接触到数据库,SQL语法简洁,使用方式灵活,功能强大,已经成为当今程序员不可或缺的技能. 推荐学习<SQL必知必会(第4版)>,内容丰富,文字简洁明快 ...
 - 《MySQL必知必会》学习笔记——前言
		
前言 MySQL已经成为世界上最受欢迎的数据库管理系统之一.无论是用在小型开发项目上,还是用来构建那些声名显赫的网站,MySQL都证明了自己是个稳定.可靠.快速.可信的系统,足以胜任任何数据存储业务的 ...
 - 《SQL必知必会》学习笔记整理
		
简介 本笔记目前已包含 <SQL必知必会>中的所有章节. 我在整理笔记时所考虑的是:在笔记记完后,当我需要查找某个知识点时,不需要到书中去找,只需查看笔记即可找到相关知识点.因此在整理笔记 ...
 - 《SQL必知必会》学习笔记(一)
		
这两天看了<SQL必知必会>第四版这本书,并照着书上做了不少实验,也对以前的概念有得新的认识,也发现以前自己有得地方理解错了.我采用的数据库是SQL Server2012.数据库中有一张比 ...
 - mysql学习--mysql必知必会1
		
 例如以下为mysql必知必会第九章開始: 正則表達式用于匹配特殊的字符集合.mysql通过where子句对正則表達式提供初步的支持. keywordregexp用来表示后面跟的东西作为正則表達式 ...
 - mysql学习--mysql必知必会
		
上图为数据库操作分类: 下面的操作參考(mysql必知必会) 创建数据库 运行脚本建表: mysql> create database mytest; Query OK, 1 row ...
 - 数据库学习之中的一个: 在 Oracle sql developer上执行SQL必知必会脚本
		
1 首先在開始菜单中打开sql developer: 2. 创建数据库连接 点击左上角的加号 在弹出的对话框中填写username和password 測试假设成功则点击连接,记得角色要写SYSDBA ...
 - SQL必知必会,带你系统学习
		
你一定听说过大名鼎鼎的Oracle.MySQL.MongoDB等,这些数据库都是基于一个语言标准发展起来的,那就是SQL. SQL可以帮我们在日常工作中处理各种数据,如果你是程序员.产品经理或者是运营 ...
 
随机推荐
- Spring Druid多数据源配置
			
SpringBoot 多数据源配置 如果需要在一个应用中使用多个数据源,应当如何实现呢,在Spring配置MyBatis中,我们可以看到以下的代码 <!-- mybatis 的SqlSessio ...
 - Linux系统安装(CentOS-7)详细操作步骤
			
Linux系统安装(CentOS-7)详细操作步骤 一.创建虚拟机 首先创建一个虚拟机,然后才能在虚拟机里面安装系统. 第一步,创建虚拟机的向导 第二步,兼容性默认即可. 第三步,我们等创建完虚拟机后 ...
 - 转:Minikuberar的含义很不错可以看看
			
Kubernetes的主要意图是通过杂乱的负载均衡和资源分配功用跨服务器集群保管使用程序.即使某些服务器呈现毛病,也能够保证使用程序平稳运转.因而在出产布置中,有必要为Kubernetes装备多个服务 ...
 - Gateway 简介
			
概述 微服务可能分布在不同的主机上,这样有许多缺点:前端需要硬编码调用不同地址的微服务很麻烦:存在跨域访问的问题:微服务地址直接暴露是不安全的.还有所以需要为前端提供一个统一的访问入口.Gateway ...
 - jenkins持续集成go应用
			
上文讲到使用supervisor管理我们的终端应用,这次讲一下使用jenkins持续集成 下面分别讲一下pipeline里每一个段落的含义 agent any 使用任意节点构建 parameters ...
 - RFC3918聚合组播吞吐量测试——网络测试仪实操
			
一.简介 1.RFC3918简介 历史 · 在1999年3月成为正式标准 功能 · 评测网络互连设备或网络系统的性能 · 网络设备: 交换机,路由器- 内容 · 定义了一整套测试方法,为不同厂家的设备 ...
 - 【基础知识】cache 管线(Pipeline)的建立便可以提升cpu的性能,为什么还要去发展多核的cpu?
			
多管线 (Pipeline)的确可以提高主频,比如搭配 NetBurs架构的Pentium4,它拥有20级的管线技术,虽然可以轻易提高主频,但是效率会降低.而且随着频率的上升,功率也大幅上升温度问题也 ...
 - Mybatis学习笔记(详细)
			
介绍 三层架构:视图层.业务逻辑层.持久层 mybatis框架: 执行数据库操作,完成对数据库的增删改查,封装了jdbc mapper映射,将表中数据转为一个Java对象,一个表对应一个接口 Myba ...
 - ORACLE 12c RAC日常维护命令
			
转至:https://blog.51cto.com/ixdba/901545 CRS提供了很多命令可以管理和查看集群服务状态,常用的有crs_stat.crs_start.crs_stop.crsct ...
 - 第九周shell脚本编程练习
			
转至:http://www.178linux.com/88838 1.写一个脚本,判断当前系统上所有用户的shell是否为可登录shell(即用户的shell不是/sbin/nologin):分别这两 ...