文章目录
- 一、HttpMessageConverter
- 二、获取请求报文信息
- 2.1 使用原生servletAPI
- 2.2 使用@RequestBody注解获取请求体信息
- 2.3 使用RequestEntity对象获取请求报文信息
- 三、设置响应报文信息
- 3.1 使用原生的servletAPI
- 3.2 使用@ResponseBody注解设置响应体信息
- 3.3 ResponseEntity类的使用
- 3.4 关于响应体信息的中文乱码问题
- 四、Spring MVC处理Json和Ajax数据
- 4.1 处理Json数据
- 4.2 处理Ajax数据
学习视频🎥:https://www.bilibili.com/video/BV1Ry4y1574R
一、HttpMessageConverter
💬概述:HttpMessageConverter
是Spring MVC中的一个类,意思是报文信息转换器
🔑作用:可以将报文信息和Java对象进行转换,即请求报文信息转换成Java对象,Java对象转换成响应报文信息
🔑HttpMessageConverter提供了两个注解和两个类型,用于实现报文信息与Java对象的转化
- @RequestBody:获取请求体信息的注解,作用于控制器方法形参,此时形参中就封装了请求体信息
- @ResponseBody:设置响应体信息的注解,作用于控制器方法,此时控制器方法的返回值就作为响应体的信息
- RequestEntity:获取请求报文的类,作为控制器方法的形参类型上,此时该形参对象就封装了请求报文的全部信息,包括请求头和请求体
- ResponseEntity:设置响应报文的类,作为控制器方法的返回值类型,此时可以在控制器方法内创建一个
ResponseEntity
对象,通过该对象可以设置响应报文的信息(自定义响应报文),最后返回该对象
二、获取请求报文信息
❓ 解决中文乱码问题:获取请求报文信息时,可能会出现中文乱码问题,尤其是获取请求参数,解决办法就是在web.xml中配置Spring MVC内部的字符编码过滤器
CharacterEncodingFilter
,然后设置encoding
属性值为utf-8即可
2.1 使用原生servletAPI
🔑使用方式:在控制器方法中添加HttpServletRequest
类型的形参req
,通过req
请求对象调用相关方法获取请求报文信息
@RequestMapping("/testReqMsg01")
public String showTestReqMsg01(HttpServletRequest req) throws IOException {
// 获取请求头信息
System.out.println("请求头Host的信息 --> " + req.getHeader("Host"));
return "success";
}
2.2 使用@RequestBody注解获取请求体信息
🔑使用方式:在控制器方法中添加String类型的形参reqBody
,然后在形参前添加@RequestBody
注解,此时请求体信息就以字符串形式封装在reqBody
,打印reqBody
就能看到对应的请求体信息
@RequestMapping("/testReqMsg02")
public String showTestReqMsg02(@RequestBody String reqBody) {
System.out.println("请求体信息 -->" + reqBody);
return "success";
}
2.3 使用RequestEntity对象获取请求报文信息
🔑使用方式:在控制器方法中添加RequestEntity<String>
类型的形参reqEntity
,此时reqEntity
对象中就封装了请求报文中的全部信息,reqEntity
同样可以调用相关方法获取请求头信息和请求体信息
@RequestMapping("/testReqMsg03")
public String showTestReqMsg03(RequestEntity<String> reqEntity) {
// 获取请求头信息
System.out.println("全部请求头信息 -->" + reqEntity.getHeaders());
// 获取请求体信息
System.out.println("请求体信息 --> " + reqEntity.getBody());
return "success";
}
🔑RequestEntity对象 🆚 HttpServletRequest对象
- 请求头信息的获取
①RequestEntity
对象能获取直接获取请求头的全部信息,并以字符串形式打印 -->getHeaders()
②HttpServletRequest
对象只能通过请求头的某个键来获取对应的值 -->getHeader("键名")
、getHeaders("键名")
- 请求体信息的获取
①RequestEntity
对象能直接获取请求体的信息(即全部请求参数),并以字符串形式打印 -->getBody()
②HttpServletRequest
对象只能通过IO流来获取请求体中的请求参数 -->getReader()
、getInputStream()
三、设置响应报文信息
3.1 使用原生的servletAPI
🔑使用方法:创建控制器方法,因为设置响应体信息只需将信息打印到当前页面(是指控制器方法中@RequestMapping
注解所设置的请求路径)即可,无需跳转页面,所以方法不需要返回值,直接返回类型设置为void
,然后在方法中添加HttpServletResponse
类型的形参resp
,通过resp
调用相关方法设置响应报文信息
@RequestMapping("/testRespMsg01")
public void showTestRespMsg01(HttpServletResponse resp) throws IOException {
// 设置响应体的编码方式
resp.setContentType("text/html;charset=utf-8");
// 设置响应体信息,将信息打印到页面
resp.getWriter().print("测试原生servletAPI设置响应报文信息成功!");
}
3.2 使用@ResponseBody注解设置响应体信息
🔑使用方式:在控制器方法上添加@ResponseBody
注解,此时控制器方法的返回值不再是视图名称,而是作为响应体信息,即打印到页面上的信息
@RequestMapping("/testRespMsg02")
@ResponseBody
public String showTestRespMsg02() {
return "测试@ResponseBody注解成功!";
}
🔑复合注解——@RestController(以后常用)
- 概述:因为在以后的开发中,
@ResponseBody
注解会经常使用,因此Spring MVC提供了一个复合注解@RestController
,该复合注解是@Controller
注解和@ResponseBody
注解的组合,也结合了两个注解的作用 - 标识的位置:
@RestController
注解作用于控制器上(此时不用添加@Controller
注解) - 作用
① 将类标识为控制器类 -->@Controller
的作用
② 在对应控制器的所有控制器方法上自动添加上@ResponseBody
注解,不用我们手动添加 -->@ResponseBody
的作用
3.3 ResponseEntity类的使用
💬概述:ResponseEntity
对象就是响应报文对象,它作用于控制器方法返回值类型,需要加上泛型<T>
,在控制器方法中创建一个ResponseEntity
对象respEntity
,通过该对象能自定义响应报文信息,设置完信息后就将对象返回,此时控制器方法返回值就是响应到浏览器的响应报文
🔑使用:ResponseEntity
对象多用于文件下载功能的实现,因为文件下载中需要设置响应头以及响应体的MIME类型,而ResponseEntity
对象正好可以实现,文件下载的具体实现下面介绍
🔑ResponseEntity对象的创建:ResponseEntity
类中有多个构造器,这里介绍构造器中需要传入的几个重要参数
构造器的参数 | 参数类型 | 解释 |
---|---|---|
body | T | 响应体对象,可以为null,对应响应体信息;T表示泛型,即创建ResponseEntity 时指定的泛型 |
headers | MultiValueMap<String, String> | 请求头对象,可以为null,对应响应头信息;用于设置响应头信息;MultiValueMap 是继承Map 的接口,因此创建Headers 对象时需要使用MultiValueMap 接口的实现类——HttpHeaders |
status | HttpStatus | 响应状态码对象,对应响应状态码;可以直接通过HttpStatus.状态 来获取对应的状态码,如HttpStatus.OK (200) |
💡 文件下载功能中泛型
T
设置为byte[]
类型,即字节数组类型,用于存储文件对应的全部字节,此时文件对应的字节数组就是响应体信息
💡ResponseEntity
在文件下载中的使用:SpringMVC实现文件上传和下载#文件下载⬇
3.4 关于响应体信息的中文乱码问题
🔑解决办法
-
对于
HttpServletResponse
对象:使用原生的servletAPIHttpServletResponse
设置响应体信息时,需要在设置响应体信息前设置响应体信息编码方式,使用setContentType("text/html;charset-utf-8")
方法,告知浏览器响应体的MIME类型以及编码方式,才能避免出现中文乱码问题(即使在web.xml中配置的CharacterEncodingFilter
过滤器已经设置过forceResponseEncoding
属性,也要添加setContentType()
方法(具体原因🚩) -
对于
@ResponseBody
注解:使用@ResponseBody
注解时也会遇到中文乱码问题,有多种解决方式,这里介绍两种① 在springmvc.xml的开启注解驱动
<mvc:annoattion-driven>
标签修改报文信息转换器默认的编码方式<mvc:annotation-driven > <!-- 报文信息转换器 --> <mvc:message-converters register-defaults="true"> <!-- 修改字符集编码方式,解决@RequestBody出现中文乱码问题 --> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes" value="text/html;charset=UTF-8"/> </bean> </mvc:message-converters> </mvc:annotation-driven>
② 对于
@ResponseBody
所标识的控制器方法,在控制器方法的@RequestMapping
注解中添加一个produces
属性,属性值设置为"text/html;charset=UTF-8"
即可(适合完全注解开发)@RequestMapping( value = "/testRespMsg02", produces = "text/html;charset=utf-8" ) @ResponseBody public String showTestRespMsg02() { return "测试@ResponseBody注解成功!"; }
-
设置响应时的编码方式的两种方式
①resp.setCharacterEncoding("UTF-8")
:仅设置了服务器中servlet对响应体进行编码时采用的编码方式,没有对浏览器解码时的解码方式做要求。但不同浏览器对响应信息的解码方式一般不同,与服务器编码时的编码方式也不一定会相同,所以用这种方式设置响应时编码方式可能会失效。🚩而字符编码过滤器CharsetEncodingFilter
中设置响应时编码方式采用的正是这种方式,所以配置过滤器时设置的forceResponseEncoding
属性也可能会失效
②resp.setContentType("MIME类型;charset=UTF-8")
:该方式一举三得,Ⅰ)设置响应体的MIME类型;Ⅱ)设置响应体在服务器端编码时的编码方式;Ⅲ)告知浏览器响应体的编码方式并让浏览器采用相同的解码方式对响应体信息进行解码。因此就能避免打印到页面的响应体信息出现中文乱码,一般都直接采用这种方式设置响应时编码方式,不采用上面的方式 -
不同格式的中文乱码
① 中文字符部分类似于
'烇湫'
的格式,而且有可能隔壁的英文字母也会被乱码吃掉,说明服务器端对响应体的编码方式与浏览器的解码方式不一样,一般是因为没有设置响应时编码方式或者仅添加了resp.setCharacterEncoding("UTF-8")
② 中文字符都是问号
'??'
,说明服务器端的编码方式与浏览器的解码方式一样,但采用的编解码方式不能识别中文字符,比如采用了默认的iso8859-1,一般是因为没有设置响应时的编码方式所造成的
四、Spring MVC处理Json和Ajax数据
4.1 处理Json数据
① 导入相关jar包:添加jackson-databind.jar包
② 开启注解驱动:在springmvc.xml核心配置文件中开启注解驱动,此时在HandlerAdaptor中会自动装配一个消息转换器——MappingJackson2HttpMessageConverter
,该转换器可以将Java对象转换为Json格式的字符串响应到浏览器中
③ 将Java对象作为响应体信息:创建控制器方法,方法上添加@ResponseBody
注解,方法返回值类型为实体类类型,即返回值为Java对象,此时该Java对象就会被转换成Json格式的字符串,最后在页面上打印出来的是Json格式的字符串
@RequestMapping("/testJson")
@ResponseBody
public User showTestJson() {
return new User(1, "王小明", "男", 35);
}
💡 如果不做前两部操作(导入Json相关jar包以及开启注解驱动),直接在控制器方法中添加
@ResponseBody
注解并返回一个Java对象,即直接将Java对象作为响应体信息打印到页面上,页面会直接报500错误(服务器端错误)
④ 页面打印结果
4.2 处理Ajax数据
① 创建测试超链接,超链接标签<a>
添加@click
属性,用于绑定单击事件
<div id="testAjaxId">
<a @click="testAjax" th:href="@{/testAjax}">测试处理Ajax数据</a>
</div>
② 导入vue.js和axios.min.js文件,使用vue和axios处理超链接的点击事件
<script type="text/javascript" th:src="@{/static/js/vue.js}"></script>
<script type="text/javascript" th:src="@{/static/js/axios.min.js}"></script>
<script type="text/javascript">
var vue = new Vue({
el:"#testAjaxId",
methods:{
testAjax:function (event) {
axios({
method:"post",
url:event.target.href,
params:{
username:"Key",
pwd:"123456"
}
}).then(function (response) {
// 用警示框显示响应体的数据
alert(response.data);
});
// 阻止超链接的默认行为
event.preventDefault();
}
}
});
</script>
③ 创建控制器方法,方法上添加@ResponseBody
注解,并添加两个形参,对应两个请求参数,返回值为响应体的信息
@RequestMapping("/testAjax")
@ResponseBody
public String showTestAjax(String username, String pwd) {
System.out.println("用户名 --> " + username);
System.out.println("密码 --> " + pwd);
return "测试处理Ajax数据成功!";
}