HttpMessageConverter
一、概述
-
定义
报文信息转换器:将请求报文转换为Java对象,或将Java对象转换为响应报文
-
两个注解和两个类型
@RequestBody、@ResponseBody、RequestEntity、ResponseEntity
-
html - 首页
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h1>首页</h1> <form th:action="@{/requestBodyTest}" method="post"> <input type="text" name="name"> <input type="text" name="password"> <input type="submit" value="测试@RequestBody"> </form><br/> <form th:action="@{/requestEntityTest}" method="post"> <input type="text" name="name"> <input type="text" name="password"> <input type="submit" value="测试@RequestEntity"> </form><br/> <a th:href="@{/responseApiTest}">测试ServletResponse</a><br/> <a th:href="@{/responseBodyTest}">测试ResponseBody</a><br/> <a th:href="@{/responseUserTest}">测试ResponseUser</a><br/> </body> </html>
二、@RequestBody
-
在控制器方法设置一个形参,使用@RequestBody进行标识,当前请求的请求体就会为当前注解所标识的新参赋值
-
controller
@Controller public class HttpController { @PostMapping("/requestBodyTest") public String requestBodyTest(@RequestBody String requestBody) { System.out.println("requestBody = " + requestBody); return "success"; } }
-
输出结果
三、RequestEntity
-
RequestEntity是封装请求报文的一种类型,需要在控制器方法的形参中设置该类型的参数,当前请求的请求报文就会赋值给该参数。在方法体内可通过getHeaders获取请求头信息,通过getBody获取请求体信息
-
controller
@Controller public class HttpController { @PostMapping("/requestEntityTest") public String requestBodyTest(RequestEntity<String> requestEntity) { System.out.println("请求头 = " + requestEntity.getHeaders()); System.out.println("请求体 = " + requestEntity.getBody()); return "success"; } }
-
输出结果
四、ResponseAPI
-
通过responseAPI进行响应,会将返回值直接作为响应体响应到浏览器
-
controller
@Controller public class HttpController { @RequestMapping("/responseApiTest") public void responseTest(ServletResponse response) throws IOException { // 会将响应直接显示在一个页面上 response.getWriter().print("hello,java"); } }
-
响应结果
五、@ResponseBody( - 常用 - )
-
@ResponseBody用于标识一个控制器方法,可以将该方法的返回值直接作为响应报文的响应体相应到浏览器
-
controller
@Controller public class HttpController { @RequestMapping("/responseBodyTest") @ResponseBody public String responseTest() { return "hello,responseBody"; } }
-
响应结果
五、springMVC处理 JSON
-
如果返回的是一个自建类型数据,就需要将Java对象自动转会为JSON字符串进行响应,否则报错500
-
在pom.xml文件内引入依赖
<!-- jackson依赖: --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.1</version> </dependency>
-
开启mvc的注解驱动:可以在HandlerAdaptor中自动装配一个消息转换器 - MappingJackson2HttpMessageConverter,会将响应到浏览器的Java对象自动转换为JSON格式的字符串
<!-- 已经在springMVC.xml中配置了 --> <mvc:annotation-driven />
-
controller
@Controller public class HttpController { @RequestMapping("/responseUserTest") @ResponseBody public User responseBodyTest() { return new User(1,"admin","123456",23,"male"); } }
-
引入依赖后的响应结果
-
也可以使用xml进行响应,但是xml文件进行解析的时候很麻烦,会需要Document从根标签开始,获取根标签内的子标签,再获取子标签内的子标签 . . . 一层层的解析
上述json字符串对应的xml文件如下:
<User> <id>1</id> <uname>admin</uname> <password>123456</password> <age>23</age> <gender>male</gender> </User>
-
Json数据类型
对象:大括号,数据是以键值对的形式存放
数组:中括号,数据是一个一个的存放
故返回的:java实例对象转换为了json对象,map转换为了json对象,list转换为了json数组
六、springMVC处理Ajax
-
html页面
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <!-- 点击跳转链接 --> <div id="add"> <a @onclick="axiosTest" th:href="@{/axiosTest}">测试Axios</a> </div> <!-- 引入vue和axios依赖,并在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:"#add", methods: { axiosTest:function(event){ axios({ method:"post", url:event.target.href, params:{ username:"admin", password:"123" } }).then(function(response) { alert(response.data) }); <!-- 取消超链接的默认动作 --> event.preventDefault(); } } }); </script> </body> </html>
-
controller
@Controller public class HttpController { @RequestMapping("/axiosTest") @ResponseBody public String axiosTest(String username, String password) { return "username :" + username + ",password :" + password; } }
-
响应效果
七、@RestController( - 最常用 - )
-
SpringBoot 和 SpringCloud 后,都是使用微服务。
微服务指的是以业务逻辑为边界,将一个完整的工程分成一个又一个可以单独运行和单独部署的小工程,每个小工程就是一个微服务。
因为都属于一个工程,故微服务和微服务之间是一定要进行数据交互的,而数据交互使用的就是Http + Json,所以每个微服务中控制器的每个方法都要加上@ResponseBody这个注解。
-
为了简化注解的添加数量
在springMVC中,提供了**@RestController注解(本质是复合注解**),该注解相当于为控制器添加了@Controller,又同时为该控制器内的每个方法都添加了@ResponseBody注解
八、ResponseEntity:实现文件上传和下载
-
作用
可以自定义一个响应报文,对浏览器进行响应
-
下载,使用get请求
html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>测试文件上传和下载</title> </head> <body> <a th:href="@{/downTest}">下载2022.jpg</a> </body> </html>
controller
@Controller public class FileUpAndDownController { @RequestMapping("/downTest") public ResponseEntity<byte[]> downTest(HttpSession session) throws IOException { ServletContext servletContext = session.getServletContext(); // 1.获取响应体 // 1.1 获取服务器中文件的真实路径 String realPath = servletContext.getRealPath("/static/img/2022.jpg"); // 1.2 创建该文件对应的输入流: 上传和下载都是一个复制过程 FileInputStream is = new FileInputStream(realPath); // 1.3 创建字节流,is.available()是该路径的输入流的长度 byte[] bytes = new byte[is.available()]; // 1.4 将流读取到字节数组中 is.read(bytes); // 2.获取响应头 // 2.1 创建HttpHeaders对象设置响应头信息 MultiValueMap<String,String> headers = new HttpHeaders(); /* 2.2 设置要下载方式以及下载文件的名字 Content-Disposition:内容处置,键名 attachment:以附件的方式进行下载 filename:文件的默认名字 */ headers.add("Content-Disposition","attachment;filename=2022.jpg"); // 3.设置响应状态码 HttpStatus statusCode = HttpStatus.OK; // 创建ResponseEntity对象,需要三个要素:响应体、响应头、状态码 ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode); // 关闭流 is.close(); return responseEntity; } }
-
上传,使用post请求
① 在maven中添加依赖
<dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency>
② 在springMVC中配置文件上传解析器
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
③ html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>测试文件上传和下载</title> </head> <body> <!-- 实现上传:method 与 enctype的设置缺一不可 --> <form th:action="@{/updateTest}" method="post" enctype="multipart/form-data"> 头像:<input type="file" name="photo"><br/> <input type="submit" value="上传"/> </form> </body> </html>
④ controller
@Controller public class FileUpAndDownController { @PostMapping("/updateTest") // springMVC将上传的文件及上传后对文件的操作都封装到了MultipartFile对象中, public String updateTest(MultipartFile photo, HttpSession session) throws IOException { // 1.获取上传文件的文件名 String fileName = photo.getOriginalFilename(); // 2.获取服务器路径下的photo目录 ServletContext servletContext = session.getServletContext(); String photoPath = servletContext.getRealPath("photo"); // 3.若photo目录不存在,就创建该目录 File file = new File(photoPath); if (!file.exists()) { file.mkdir(); } // 4.确定文件的最终上传路径,其中File.separator是指文件分隔符 String finalPath = photoPath + File.separator + fileName; // 5.文件上传 photo.transferTo(new File(finalPath)); return "success"; } }
⑤ 上传界面及上传至服务器的路径