java - 反序列化为 OffsetDateTime 时如何使 Spring Kafka JsonDeserializer 保留时区偏移量
问题描述
我通过 Kafka 收到一条消息,我知道其中有一个非 UTC 时区。当我使用org.apache.kafka.common.serialization.StringDeserializer
来验证这一点时,我得到了带有时区的 ISO 8601 格式的正确时间戳:
{ "id": "e499f2e8-a50e-4ff8-a9fe-0eaf9d3314bf", "sent_ts": "2021-02-04T14:06:10+01:00" }
当我切换到时,org.springframework.kafka.support.serializer.JsonDeserializer
这丢失了。我的 POJO 看起来像这样:
public class MyMessage {
@JsonProperty("id")
private String id;
@JsonProperty("sent_ts")
private OffsetDateTime sentTs;
@Override
public String toString() {
return "MyMessage{" +
"id='" + id + '\'' +
", sentTs=" + sentTs +
'}';
}
当我记录收到的消息时,我得到:
MyMessage{id='e499f2e8-a50e-4ff8-a9fe-0eaf9d3314bf', sentTs=2021-02-04T13:06:10Z}
我认为JsonDeserializer
必须使用杰克逊,所以在我的application.yml
配置中我设置:
spring.jackson:
deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE: false
这没有用。我还尝试了定制器:
@Configuration
public class ObjectMapperBuilderCustomizer implements Jackson2ObjectMapperBuilderCustomizer {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.modules(new JavaTimeModule());
builder.featuresToDisable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
}
}
这也不起作用。
我虽然可能它需要成为 Kafka 消费者的属性,所以我也尝试了:
spring:
consumer:
auto-offset-reset: earliest
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring.jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE: false
还是不行。
有没有办法使JsonDeserializer
工作正常并保持正确的时区偏移?
解决方案
当您这样做value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
时,该类的实例由完全不了解 Spring 配置的 Apache Kafka 客户端代码创建。
如果你想依赖ObjectMapper
Spring Boot 的配置和你的自定义,你应该考虑做这样的事情:
@Bean
DefaultKafkaConsumerFactory kafkaConsumerFactory(KafkaProperties properties, ObjectMapper objectMapper) {
Map<String, Object> consumerProperties = properties.buildConsumerProperties();
JsonDeserializer<Object> jsonDeserializer = new JsonDeserializer<>(objectMapper);
jsonDeserializer.configure(consumerProperties, false);
return new DefaultKafkaConsumerFactory(consumerProperties,
new StringDeserializer(), jsonDeserializer);
}
注意我怎么称呼jsonDeserializer.configure(consumerProperties, false);
。这样,您仍然可以在applicaiton.yml
.
请考虑为 Spring Boot 提出 GH 问题,因此我们将修改我们处理JsonDeserializer
和自动配置ObjectMapper
的方式,以提供更好的最终用户体验。
推荐阅读
- python - 如何让重复计算更有效率?功能建议?
- javascript - 如何使用 .fetch() 将参数传递给后端中的函数?ReactJS + 节点
- python-3.x - 匹配数据帧的记录多于计数
- android - 在 Android 上使用 Sharedpreferences 的存储问题
- php - While循环PHP内部的多个查询
- selenium - 用于自动化 Oracle ADF 登录的 Selenium Web 驱动程序
- docker - 为什么我不能构建这个 Dockerfile
- visual-studio-code - VSCode 仅在其自己的拆分窗口中循环打开文件
- powershell - 通过 PowerShell 脚本使用 Graph api 将文件上传到共享点
- java - Spring Batch 应用程序无故死亡