Springboot 开发实践-HttpMessageConverter
稻花香里说丰年,听取蛙声一片。
1 前言
在日常的开发中经常会遇到 Http
请求和响应的转换问题,比如常见的时间格式的问题。本文将从 @JsonFormat
注解失效为出发点来讲解消息转换器-HttpMessageConverter
。
2 @JsonFormat
失效分析
首先需要说明一下,spring-boot-starter-web
已经包含了 jackson
的依赖,所以不需要添加额外的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
默认情况下,spring
采用 MappingJackson2HttpMessageConverter
来处理数据的转换, jackson
的配置可以通过配置文件来进行配置,可以配置时间的格式,时区以及字段的策略,还有序列化的方式。
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss.SSS
time-zone: Asia/Shanghai
# CamelCase 驼峰策略 userId -> userId
# PascalCase 帕斯卡策略,即首字母大写 userId -> UserId
# SnakeCase 下划线策略 userId -> user_id
# KebabCase 横短线策略 userId -> user-id
property-naming-strategy: CamelCase
serialization:
write-dates-as-timestamps: true
@JsonFormat
是 Jackson 提供的一个注解,主要用于指定字段如何序列化和反序列化,特别是对日期和时间类型非常有用。然而,在实际开发中,我们可能会遇到 @JsonFormat
注解不起作用的情况。总结一下失效的场景如下:
1 全局配置覆盖,如果配置了全局日志格式,可能会覆盖类或者字段级别上使用的 @JsonFormat 注解。
2 注解配置错误,注解需要直接配置在字段或者字段的get 方法上才能生效。
3 类库或者版本冲突,这个是最麻烦的,也是最难解决的。需要通过配置 MappingJackson2HttpMessageConverter 来解决。
4 时区问题,如果服务器和客户端存在跨时区的问题,也可能会导致时间序列化失效,需要重新修改时区即可。
当注解@JsonFormat
失效时,展示的时间格式为 yyyy-MM-dd'T'HH:mm:ss.SSSZ
,需要通过java 配置的方式来解决,通常这个是最终解决方案。如下所示,通过实现WebMvcConfigurer
的方法configureMessageConverters
即可实现 jackson
时间格式化配置。
3 jackson 的其他配置
除了以上的 @JsonFormat
注解之外,还有以下几个常用的注解:
# 标注在字段上,表示不参与序列化
@JsonIgnore
# 标注在字段上,如果字段为空,则不参与序列化
@JsonInclude(JsonInclude.Include.NON_NULL)
# 反序列化时可以起作用,序列化时不起作用,可以指定多个别名
@JsonAlias(value = {"aa", "ab", "ac"})
# 序列化和反序列化时只能使用别名
@JsonProperty(value="alias_name")
4 HttpMessageConverter
消息转换器
HttpMessageConverter
是 Spring
框架中的一个核心组件,用来处理 java
对象和 Http
协议之间的转换,比如常见的 @RequestBody
和 @ResponseBody
可以根据请求头 Content-Type
的类型来对请求进行解析。
以 @RequestBody
为例,当接收到 POST
或者 GET
方法的 HTTP
请求时,Spring 框架经过过滤器以及拦截器,会根据请求头 Content-Type
来选择适当的 HttpMessageConverter
进行请求体解析,并将解析转换后的 java 对象作为方法参数传递给适配的控制器。当然在接受请求或者返回参数时,可以使用泛型类 RequestEntity
(可以表示完整的请求头、请求体、请求方法和URI等信息) 和 ResponseEntity
(可以表示响应头、响应体和响应状态)。
除了 MappingJackson2HttpMessageConverter
之外,还可以使用 GsonHttpMessageConverter
和 FastJsonHttpMessageConverter
两个消息转换器, 配置如下所示:
// gson 消息转换
@Bean
public GsonHttpMessageConverter gsonHttpMessageConverters() {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.setPrettyPrinting() // 设置自定义选项
.create();
GsonHttpMessageConverter converter = new GsonHttpMessageConverter(gson);
return converter;
}
// fastjson 消息转换
@Bean
public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue);
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
converter.setFastJsonConfig(fastJsonConfig);
return converter;
}
如果需要实现消息转换器,需要在 WebMvcConfigurer.configureMessageConverters
进行配置即可实现消息转换。
5 总结
本文以 @JsonFormat
时间格式失效为切入点,讲解了 jackson
相关的消息转换内容,进而延伸到了 HttpMessageConverter
的其它实现方式,补齐了 Spring
消息转换的内容。本文中所涉及的代码已经上传至 gitee
, 欢迎交流学习。项目地址 fortunecloud。
转载自:https://juejin.cn/post/7395021416570175525