在整个数据流转过程中,前端的请求报文转化为Java对象,Java对象转化为响应报文,这里就用到了HttpMessageConverter(消息转换器)。
消息转化器的作用
- 将请求报文转化为Java对象
- 将Java对象转化为响应报文
消息转化器的主要方法
- getSupportedMediaTypes:获取支持的MediaType集合(如:text/html,text/plain,application/json)
- canRead:判断是否能读(请求)
- read:将请求数据进行格式转换(canRead方法返回值为true时调用)
- canWrite:判断是否能写(响应)
- write:将响应数据进行格式转换(canWrite方法返回值为true时调用)
默认配置的消息转化器
SpringMVC启动时会自动配置一些HttpMessageConverter(WebMvcConfigurationSupport类的addDefaultHttpMessageConverters)方法
源码如下:
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
messageConverters.add(new ByteArrayHttpMessageConverter());
messageConverters.add(new StringHttpMessageConverter());
messageConverters.add(new ResourceHttpMessageConverter());
messageConverters.add(new ResourceRegionHttpMessageConverter());
try {
messageConverters.add(new SourceHttpMessageConverter<>());
}
catch (Throwable ex) {
// Ignore when no TransformerFactory implementation is available...
}
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
if (romePresent) {
messageConverters.add(new AtomFeedHttpMessageConverter());
messageConverters.add(new RssChannelHttpMessageConverter());
}
if (jackson2XmlPresent) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
}
else if (jaxb2Present) {
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
}
if (jackson2Present) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
else if (gsonPresent) {
messageConverters.add(new GsonHttpMessageConverter());
}
else if (jsonbPresent) {
messageConverters.add(new JsonbHttpMessageConverter());
}
if (jackson2SmilePresent) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
}
if (jackson2CborPresent) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
}
}
部分消息转换器解析
- MappingJackson2HttpMessageConverter 负责读、写JSON格式数据(利用Jackson)
- AllEncompassingFormHttpMessageConverter 负责读、写Form表单数据
- Jaxb2RootElementHttpMessageConverter 负责读、写XML格式数据(使用JAXB)
- ByteArrayHttpMessageConverter 负责读、写二进制格式数据
- StringHttpMessageConverter 负责读、写字符串格式数据
- ResourceHttpMessageConverter 负责读、写资源文件数据
- SourceHttpMessageConverter 负责读、写资源数据
注意事项
- 系统有默认配置的消息转换器集合。
- 处理过程会按集合顺序匹配合适的消息转换器,如果有合适的,就会使用该消息转换器处理(读、写),后续的消息转换器不再执行。
- 自定义的消息转换器要想生效,必须放到集合中相同类型的消息转换器前面,原因参考第二点。
- 思考:既然自定义的消息转换器必须放到集合中相同类型的消息转换器前面,那是否能直接改动集合中原有的消息转换器来达到自定义的效果,而不必在加一个(暂未没研究)。
- 添加自定义消息转换器时注意默认消息转换器是否生效
- WebMvcConfigurer.configureMessageConverters方法会覆盖默认消息转换器集合
- WebMvcConfigurer.extendMessageConverters方法不会覆盖默认消息转换器集合