likes
comments
collection
share

Springboot 开发实践-HttpMessageConverter

作者站长头像
站长
· 阅读数 25

稻花香里说丰年,听取蛙声一片。

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 时间格式化配置。

Springboot 开发实践-HttpMessageConverter

3 jackson 的其他配置

除了以上的 @JsonFormat 注解之外,还有以下几个常用的注解:

# 标注在字段上,表示不参与序列化
@JsonIgnore 
# 标注在字段上,如果字段为空,则不参与序列化
@JsonInclude(JsonInclude.Include.NON_NULL)
# 反序列化时可以起作用,序列化时不起作用,可以指定多个别名
@JsonAlias(value = {"aa", "ab", "ac"})
# 序列化和反序列化时只能使用别名
@JsonProperty(value="alias_name")

4 HttpMessageConverter 消息转换器

HttpMessageConverterSpring 框架中的一个核心组件,用来处理 java 对象和 Http 协议之间的转换,比如常见的 @RequestBody@ResponseBody 可以根据请求头 Content-Type 的类型来对请求进行解析。

@RequestBody 为例,当接收到 POST 或者 GET 方法的 HTTP 请求时,Spring 框架经过过滤器以及拦截器,会根据请求头 Content-Type 来选择适当的 HttpMessageConverter 进行请求体解析,并将解析转换后的 java 对象作为方法参数传递给适配的控制器。当然在接受请求或者返回参数时,可以使用泛型类 RequestEntity(可以表示完整的请求头、请求体、请求方法和URI等信息) 和 ResponseEntity(可以表示响应头、响应体和响应状态)。

除了 MappingJackson2HttpMessageConverter 之外,还可以使用 GsonHttpMessageConverterFastJsonHttpMessageConverter 两个消息转换器, 配置如下所示:

// 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
评论
请登录