- Spring mvc 通过 json 数据进行交互。那么前端传入的 json 数据如何被解析成 Java 对象作为 API入参,API 返回结果又如何将 Java 对象解析成 json 格式数据返回给前端,其实在整个数据流转过程中,HttpMessageConverter 起到了重要作用
- org.springframework.http.converter.HttpMessageConverter 是一个策略接口,是 HTTP request (请求)和response (响应)的转换器。
- 该接口有只有5个方法,简单来说就是获取支持的 MediaType(application/json之类),接收到请求时判断是否能读(canRead),能读则读(read);返回结果时判断是否能写(canWrite),能写则写(write)
方法 |
说明 |
返回类型 |
异常捕获 |
canRead(Class<?> clazz, MediaType mediaType) |
是否可读,若可读则调用read()方法 |
boolean |
|
canWrite(Class<?> clazz, MediaType mediaType); |
是否可写,若可写则点用write()方法 |
boolean |
|
getSupportedMediaTypes(); |
获取支持的媒体转换类型 |
List<MediaType> |
|
read(Class<? extends T> clazz, HttpInputMessage inputMessage) |
转换类型后读取 |
T |
throws IOException, HttpMessageNotReadableException; |
write(T t, MediaType contentType, HttpOutputMessage outputMessage) |
转换类型后写入 |
void |
throws IOException, HttpMessageNotWritableException; |
HttpMessageConverter接口实现类
- 在Spring中,内置了大量的HttpMessageConverter。通过请求头信息中的MIME类型(Json,xml,text…),选择相应的HttpMessageConverter进行格式转换。
- 它们都实现了HttpMessageConverter这个接口
实现类 |
说明 |
StringHttpMessageConverter |
将请求信息转换为字符串 |
FormHttpMessageConverter |
将表单数据读取到MutilValueMap中 |
XmlAwareFormHttpMessageConverter |
扩展于FormHttpMessageConverter,如果部分表单数据属性是XML数据,可用该转换器进行读取 |
ResourceHttpMessageConverter |
读写org.springframework.core.io.Resource对象 |
BufferedImageHttpMessageConverter |
读写BufferedImage对象 |
ByteArrayHttpMessageConverter |
读写二进制数据 |
SourceHttpMessageConverter |
读写javax.xml.transform.Source对象 |
MarshallingHttpMessageConverter |
通过Spring对org.springframework.xml.Marshaller和Unmarshaller读写XML消息 |
Jaxb2RootElementHttpMessafeConverter |
通过JAXB2读写XML消息,将请求消息转换到标注XmlRootElement和XxmlType消息的类中 |
MappingJackson2HttpMessageConverter |
利用Jackson开源包的ObjectMapper读写JSON数据 |
RssChannelHttpMessageConverter |
能够读写RSS种子消息 |
AtomFeedHttpMessageConverter |
和RssChannelHttpMessageConverter能够读写RSS种子消息 |
- 我们写 Demo 没有配置任何 MessageConverter,但是数据前后传递依旧好用,是因为 SpringMVC 启动时会自动配置一些HttpMessageConverter,在 WebMvcConfigurationSupport 类中添加了缺省 MessageConverter
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters){ StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); stringConverter.setWriteAcceptCharset(false);
messageConverters.add(new ByteArrayHttpMessageConverter()); messageConverters.add(stringConverter); messageConverters.add(new ResourceHttpMessageConverter()); messageConverters.add(new SourceHttpMessageConverter<Source>()); messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) { messageConverters.add(new AtomFeedHttpMessageConverter()); messageConverters.add(new RssChannelHttpMessageConverter()); }
if (jackson2XmlPresent) { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.xml().applicationContext(this.applicationContext).build(); messageConverters.add(new MappingJackson2XmlHttpMessageConverter(objectMapper)); } else if (jaxb2Present) { messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); }
if (jackson2Present) { ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().applicationContext(this.applicationContext).build(); messageConverters.add(new MappingJackson2HttpMessageConverter(objectMapper)); } else if (gsonPresent) { messageConverters.add(new GsonHttpMessageConverter()); } } |
- 我们看到很熟悉的 MappingJackson2HttpMessageConverter ,如果我们引入 jackson 相关包,Spring 就会为我们添加该 MessageConverter,但是我们通常在搭建框架的时候还是会手动添加配置 appingJackson2HttpMessageConverter
- 是因为当我们配置了自己的 MessageConverter, SpringMVC 启动过程就不会调用 addDefaultHttpMessageConverters 方法,且看下面代码 if 条件,这样做也是为了定制化我们自己的 MessageConverter
protected final List<HttpMessageConverter<?>> getMessageConverters(){ if (this.messageConverters == null) { this.messageConverters = new ArrayList<HttpMessageConverter<?>>(); configureMessageConverters(this.messageConverters); if (this.messageConverters.isEmpty()) { addDefaultHttpMessageConverters(this.messageConverters); } extendMessageConverters(this.messageConverters); } return this.messageConverters; } |