【1】需求:Kafka 使用 Avero 反序列化時,同時需要對 String 類型的 JSON數據進行反序列化。AvroConfig的配置信息如下:
/**
* @author zzx
* @creat 2020-03-11-20:23
*/
@Configuration
@EnableKafka
public class AvroConfig {
//生產者配置 略。。。。 主要說消費者問題
//消費者配置 avro 反序列化如下 主要是注入 Bean 的名稱不同
@Bean
public Map<String, Object> consumerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
//主要區別
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, AvroDeserializer.class);
props.put(ConsumerConfig.GROUP_ID_CONFIG, "avro");
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,"true");
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,"1000");
return props;
}
@Bean
public ConsumerFactory<String, LatData> consumerFactory() {
return new DefaultKafkaConsumerFactory<>(consumerConfigs(), new StringDeserializer(),
new AvroDeserializer<>(LatData.class));
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, LatData> kafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, LatData> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(consumerFactory());
return factory;
}
//消費者配置 String 反序列化如下
@Bean
public Map<String, Object> stringConsumerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
//主要區別
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG,"latest");
props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG,"true");
props.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG,"1000");
return props;
}
@Bean
public DefaultKafkaConsumerFactory stringConsumerFactory() {
return new DefaultKafkaConsumerFactory<>(stringConsumerConfigs(), new StringDeserializer(),
new StringDeserializer());
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String, Object> stringKafkaListenerContainerFactory() {
ConcurrentKafkaListenerContainerFactory<String, Object> factory =
new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(stringConsumerFactory());
return factory;
}
}
【2】消費者監聽:當直接使用 @KafkaListener(topics = {"xx"})時,出現反序列化錯誤問題。
@KafkaListener(topics = {LOADING_TOPIC_NAME})
public void revice(String data) throws Exception {
【3】問題: ERROR c.y.c.exception.BDExceptionHandler - Can't convert value of class java.lang.String to class com.yunda.common.utils.avro.AvroSerializer specified in value.serializer
org.apache.kafka.common.errors.SerializationException: Can't convert value of class java.lang.String to class com.yunda.common.utils.avro.AvroSerializer specified in value.serializer
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.avro.specific.SpecificRecordBase
ERROR c.y.c.exception.BDExceptionHandler - Can't convert value of class java.lang.String to class com.yunda.common.utils.avro.AvroSerializer specified in value.serializer
org.apache.kafka.common.errors.SerializationException: Can't convert value of class java.lang.String to class com.yunda.common.utils.avro.AvroSerializer specified in value.serializer
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to org.apache.avro.specific.SpecificRecordBase
【4】問題解決:添加具體需要使用的容器 containerFactory 問題迎刃而解
@KafkaListener(topics = {ENTRY_TOPIC_NAME},containerFactory="stringkafkaListenerContainerFactory")
public void revice(String data) throws Exception {