简体   繁体   English

使用Spring Kafka模板时如何指定类类型?

[英]How to specify class type when using spring kafka template?

My current setup has the following configuration: 我当前的设置具有以下配置:

@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> myKafkaListenerContainerFactory(
        ConsumerFactory<String, String> consumerFactory) {

    ConcurrentKafkaListenerContainerFactory<String, String> factory = new
            ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory);
    factory.setMessageConverter(stringJsonMessageConverter());

    return factory;
}

where stringJsonMessageConverter has 其中stringJsonMessageConverter具有

@Bean
public StringJsonMessageConverter stringJsonMessageConverter() {
    return new StringJsonMessageConverter(objectMapper());
}

to make use of my object mapper 利用我的对象映射器

@Bean
public ObjectMapper objectMapper() {
    return new ObjectMapper()
            .registerModule(new JavaTimeModule())
            .registerModule(myCustomJacksonModules())
            .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
            .configure(ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
            .configure(WRITE_DATES_AS_TIMESTAMPS, false);
}

With this configuration, i am able to publish as: 使用此配置,我可以将其发布为:

...
headers = new MessageHeaders(singletonMap(TOPIC, topic));
Foo foo = ....
Message<?> message = new GenericMessage<>(foo, headers);
kafkaTemplate.send(message);

And consume as: 并用作:

@KafkaListener(topics = "myTopic",
        groupId = "g1",
        containerFactory = "myKafkaListenerContainerFactory")
public void onMessageReceived(Foo foo) {
    ... works with foo here
}

This works fine in this example if Foo is concrete class. 如果Foo是具体类,则在此示例中可以正常工作。 If however Foo is an abstract and what is send as message are it's subclasses 但是,如果Foo是一个抽象,并且作为消息发送的是它的子类

F1 extends Foo; F2 extends Foo ...

... // publisher

headers = new MessageHeaders(singletonMap(TOPIC, topic));
F1 f1 = ....
Message<?> message = new GenericMessage<>(f1, headers);
kafkaTemplate.send(message);

... // Listener

@KafkaListener(topics = "myTopic",
        groupId = "g1",
        containerFactory = "myKafkaListenerContainerFactory")
public void onMessageReceived(Foo foo) {
    ... wont work
}

Declaring Foo in my consumer as type would fail but this would work: 在我的使用者中将Foo声明为type会失败,但这会起作用:

@KafkaListener(topics = "myTopic",
        groupId = "g1",
        containerFactory = "myKafkaListenerContainerFactory")
public void onMessageReceived(Map<String,Object> fooAsMap) {
    ... this works too
}

Aside from the option mentioned above which is to use Map, ive also tried the following: 除了上面提到的使用地图的选项外,我还尝试了以下方法:

- class level kafka listener ([from here)][1]; it still requires method with param of type Map
- custom deserializer registered in object mapper?

Is there a way to specify the target type when i send the message? 发送消息时是否可以指定目标类型?

Configure the StringJsonMessageConverter with a custom DefaultJackson2JavaTypeMapper where it has the setTypePrecedence(TypePrecedence.TYPE_ID) . 配置StringJsonMessageConverter具有自定义DefaultJackson2JavaTypeMapper它有setTypePrecedence(TypePrecedence.TYPE_ID)

Also set the type mappings to map to the desired class, based on the sending type id header (only needed if the producer's class is different to the consumer's class). 还要根据发送的类型ID标头设置类型映射以映射到所需的类(仅在生产者的类与消费者的类不同时才需要)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM