在构建RESTful数据服务过程中,我们定义了controller、repositories,并用一些注解修饰它们,但是到现在为止我们还没执行过对象的转换——将java实体对象转换成HTTP的数据输出流。

Spring Boot底层通过HttpMessageConverters和Jackson库将Java实体类输出为JSON格式。当有多个转换器可用时,根据消息对象类型和需要的内容类型选择最适合的转换器使用。

SpringMVC源码剖析(五)-消息转换器HttpMessageConverter一文中,有一张图可以很清楚得表示消息转换器的位置。

消息转换器的目标是:

  1. HTTP输入请求格式向Java对象的转换;
  2. Java对象向HTTP输出请求的转换。

有的消息转换器只支持多个数据类型,有的只支持多个输出格式,还有的两者兼备。

例如:MappingJackson2HttpMessageConverter可以将Java对象转换为application/json,而ProtobufHttpMessageConverter仅支持com.google.protobuf.Message类型的输入,但是可以输出application/json、application/xml、text/plain和application/x-protobuf这么多格式。

实践

在项目中有三种办法配置消息转换器,主要是从可定制性易用度两个方面进行衡量。

  1. 在WebConfiguration类中加入@Bean定义
@Bean
public ByteArrayHttpMessageConverter byteArrayHttpMessageConverter() {
return new ByteArrayHttpMessageConverter();
}
  1. 重写(override)configureMessageConverters方法,扩展现有的消息转换器链表;
@Override
public
void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new ByteArrayHttpMessageConverter());
}
  1. 更多的控制,可以重写extendMessageConverters方法,首先清空转换器列表,再加入自定义的转换器。
@Override
public
void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.clear();
converters.add(new ByteArrayHttpMessageConverter());
}

分析

Spring Boot提供了多种方法完成同样的任务,选择哪个取决于我们更侧重便捷性还是更侧重可定制性。

上述提到的三种方法各有什么不同呢?

通过@Bean定义HttpMessageConverter是向项目中添加消息转换器最简便的办法,这类似于之前提到的添加Servlet Filters。如果Spring扫描到HttpMessageConverter类型的bean,就会将它自动添加到调用链中。推荐让项目中的WebConfiguration继承自WebMvcConfigurerAdapter。

通过重写configureMessageConverters方法添加自定义的转换器很方便,但有一个弱点:如果项目中存在多个WebMvcConfigurers的实例(我们自己定义的,或者Spring Boot默认提供的),不能确保重写后的configureMessageConverters方法按照固定顺序执行。

如果需要更精细的控制:清除其他消息转换器或者清楚重复的转换器,可以通过重写extendMessageConverters完成,仍然有这种可能:别的WebMvcConfigurer实例也可以重写这个方法,但是这种几率非常小。

Spring Boot 1.x系列

  1. Spring Boot的自动配置、Command-line-Runner
  2. 了解Spring Boot的自动配置
  3. Spring Boot的@PropertySource注解在整合Redis中的使用

本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。

最新文章

  1. MFC 鼠标 移动到某控件时 修改鼠标形状为手的形状
  2. Python之路第一课Day1--随堂笔记
  3. AD帐户操作C#示例代码(二)——检查密码将过期的用户
  4. 看了让人笑了很多很多次的NB的痔疮经历
  5. Mono 之 Jexus
  6. Delphi自定义消息应用及delphi托盘实现
  7. mysql问题: alter导致速度慢
  8. Havel-Hakimi定理---通过度数列判断是否可图化
  9. Ubuntu14.04和Windows双系统时无法挂载磁盘解决方法
  10. 面试题: 多个 await 处理,有一个失败,就算作失败
  11. Laravel 常见错误 1071 Specified key was too long
  12. 在django restful framework中设置django model的property
  13. 取得项目的 Git 仓库
  14. C10K问题及解决方案
  15. Java垃圾回收精粹 — Part1
  16. Java反射机制在代理模式中的使用
  17. 六十四 asyncio
  18. Python绘制直方图 Pygal模拟掷骰子
  19. c#各类型转byte[]或转回
  20. Ajax分页功能的实现

热门文章

  1. FBCTF平台安装
  2. Java 内存溢出分析
  3. 迥异和诡异的SendMessage和PostMessage
  4. Widget 基础
  5. C#连接Mongo报Unable to authenticate using sasl protocol mechanism SCRAM-SHA-1错的解决方案
  6. GStreamer基础教程09 - Appsrc及Appsink
  7. 读《深入理解Elasticsearch》点滴-查询二次评分
  8. 阿里云服务器CentOS6.9防火墙启动无效--iptables消失
  9. jQuery九大选择器和jQuery对ajax的支持
  10. .net core 3.0 Signalr - 03 使用MessagePack压缩传输内容