我正在使用JsonDeserializer
反序列化自定义对象,但是在用@KafkaListener
注释的方法中,获取Map字段为null的对象。
public ConsumerFactory<String, BizWebKafkaTopicMessage> consumerFactory(String groupId) {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress);
props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId);
return new DefaultKafkaConsumerFactory<>(props, new StringDeserializer(), new JsonDeserializer<>(BizWebKafkaTopicMessage.class));
}
我的BizWebKafkaTopicMessage是
@Data
public class BizWebKafkaTopicMessage {
// Elastic Search Index Name
private String indexName;
// ElasticSearch Index's type name
private String indexType;
// Source document to be used
private Map<String, Object> source; <=== This is being delivered as null.
// ElasticSearch document primary id
private Long id;
}
和侦听器方法 listenToKafkaMessages
@KafkaListener(topics = "${biz-web.kafka.message.topic.name}", groupId = "${biz-web.kafka.message.group.id}")
public void listenToKafkaMessages(BizWebKafkaTopicMessage message) {
............................................
............................................
// Here message.source is null
............................................
............................................
}
在listenToKafkaMessages
方法中,消息参数看起来像这样
message.indexName = 'neeraj';
message.indexType = 'jain';
message.id = 123;
message.source = null;
答案 0 :(得分:2)
我强烈怀疑这是您价值的多态性,而不是Maps本身。
Spring在引擎盖下使用Jackson进行序列化/反序列化-默认情况下,Jackson(序列化)在处理Object实例时不对序列化的类进行编码。
为什么?好吧,这会导致糟糕的兼容性问题,例如您在1年前将一个对象(Really MyPojoV1.class)序列化到数据库中,然后又将其读出-但是您的代码不再有MyPojoV1.class,因为事情进展了...如果移动MyPojoV1,它甚至可能导致问题在应用程序生存期内的任何地方都可以使用其他软件包!
因此,在反序列化时,杰克逊不知道将该对象反序列化到哪个类。
一个骇人听闻的主意是在某处运行以下命令:
ObjectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
或者更好/更春季的方式是:
@Configuration
public class JacksonConfiguration {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
#Your Configuration Here for example mapper.configure(DeserializationFeature.something, true);
return mapper;
}
}
最后值得一提的是,任意反序列化类通常会带来很大的安全风险。 Java中存在一些类,它们根据其字段中的值执行命令行甚至基于反射的逻辑(Jackson会很乐意为您填充)。因此,有人可以制作JSON,以便您反序列化为一个类,该类基本上执行value = {}字段中的任何命令。
您可以在此处阅读有关漏洞利用的更多信息-尽管我知道它可能与您无关,因为您的Kafka集群及其生产者可能固有地处于您的“受信任范围”内: https://www.nccgroup.trust/globalassets/our-research/us/whitepapers/2018/jackson_deserialization.pdf