Appearance
SpringMVC教程 - 11 消息转换器
在HTTP协议章节,我们学习了 请求协议 与 响应协议,知道了请求体、响应体会有不同的格式,服务器接收到请求,会将不同格式的请求数据转换为 Java 对象,然后经过处理,最终再将 Java 对象转换为不同格式的数据返回给请求者。
在这个过程中,Spring MVC 为此提供了一套强大的 消息转换机制 —— HttpMessageConverter,用于在 HTTP 请求和响应体之间完成 Java 对象与数据格式的相互转换。
| 方向 | 作用 |
|---|---|
| 读取请求数据 | 把请求体的数据(如 JSON、表单数据)转换成 Java 对象 |
| 写出响应数据 | 把 Java 对象转换成响应体(如 JSON、文本、图片等)返回给客户端 |
一句话总结:
消息转换器HttpMessageConverter负责: Request Body ⇋ Java Object ⇋ Response Body 的转换常用的消息转换器有:
| 转换器 | 负责内容(请求 / 响应) | 支持的 Content-Type | 描述 |
|---|---|---|---|
StringHttpMessageConverter | 文本 ⇋ 字符串 | text/plain、text/html | 将请求体中的文本转换为 String;返回值为 String 时,用它输出文本页面或纯文本。例如使用thymeleaf模板生成的HTML,最终通过该转换器转换为文本返回给浏览器。 |
FormHttpMessageConverter | 表单 —> MultiValueMap / 对象 | application/x-www-form-urlencoded | 通过表单提交数据到服务器时,可将表单键值对绑定为对象,需要使用 @RequestBody 来接收表单内容时才会用到。 |
MappingJackson2HttpMessageConverter | JSON ⇋ 对象 | application/json | 需要依赖 Jackson;请求时负责将 JSON 转换为 Java 对象(反序列化),响应时将Java对象转换为JSON(序列化)。也就是序列化和反序列化的处理。 |
ByteArrayHttpMessageConverter | 二进制 ⇋ byte[] | application/octet-stream | 主要用于文件下载 / 返回二进制内容,如下载文件、验证码图片 |
ResourceHttpMessageConverter | 文件资源 ⇋ Resource | 多种类型(如 image/png、application/octet-stream) | 用于返回资源对象(FileSystemResource、UrlResource 等),多用于文件下载或图片显示 |
这些转换器都是实现或间接实现 HttpMessageConverter 接口,其中,前后端分离最常用的是 MappingJackson2HttpMessageConverter,用于 JSON 转换。
在前面我们使用 @RequestBody 和 @ResponseBody 注解的时候,就已经在使用了,这里在回顾和理解一下。
11.1 HttpServletResponse
在前面 域对象 章节中介绍了 HttpServletRequest 对象,用于浏览器向 Controller 传递参数,而服务器向浏览器返回数据,需要使用 HttpServletResponse 对象,我们只需要向 response 对象写入数据,就可以返回数据了。
举个栗子:
创建一个
java
package com.foooor.hellospringmvc.controller;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import java.io.IOException;
import java.io.PrintWriter;
@Controller
public class HelloController {
// ...接口
/**
* 测试HttpServletResponse
* @param response
*/
@GetMapping("/test-response")
public void testResponse(HttpServletResponse response) {
try {
// 一定要在 getWriter() 之前设置,否则浏览器会乱码,同时设置text/html,让浏览器以html格式解析
response.setContentType("text/html;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write("<html><body><b>For技术栈</b></body></html>");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}- 首先在 Controller 方法上,添加
HttpServletResponse参数,就会自动注入response对象,这和 request 对象是一样的; - 然后就可以通过 response 对象来获取字节流(
getOutputStream())或字符流(getWriter()),就可以写出数据了。
HttpServletResponse 的输出流(getWriter() 或 getOutputStream())由 容器统一管理,请求结束后会自动 flush 和关闭,所以不需要手动关闭。但是如果你是读取文件的内容通过 response 写出,那么需要自己关闭读取文件的流就可以了。
测试:使用浏览器访问上面的接口,就可以在浏览器中看到加粗的 For技术栈 了。
通过上面的方式,是不会使用消息转换器来帮我们转换的,HttpServletRequest 是属于 Servlet API,是属于更底层的输出,而消息转换器是完成消息转换后,才调用 HttpServletResponse 输出数据的,所以 HttpServletResponse 是 SpringMVC 封装的上层工具。
内容未完......