[英]Json Message Communication With Apache Kafka in Spring Boot
我已经实现了两种不同的应用程序,一种用于生产者,另一种用于消费者,并且在 apache kafka 的支持下传递了消息。 当我发布 String 消息时,通信正确完成,但是当我传递 Json 消息时,发生了以下错误。
错误
java.lang.IllegalStateException: This error handler cannot process 'SerializationException's directly; please consider configuring an 'ErrorHandlingDeserializer' in the value and/or key deserializer
Caused by: org.apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition Kafka_Example_Json-0 at offset 0. If needed, please seek past the record to continue consumption.
Caused by: java.lang.IllegalArgumentException: The class 'com.benz.kafka.api.model.User' is not in the trusted packages: [java.util, java.lang, com.benz.kafka.consumer.api.model, com.benz.kafka.consumer.api.model.*]. If you believe this class is safe to deserialize, please provide its name. If the serialization is only done by a trusted source, you can also enable trust all (*).
ConsumerConfig 类
@Configuration
@EnableKafka
public class KafkaConfig {
private ConsumerFactory<String, User> userConsumerFactory()
{
Map<String,Object> config=new ConcurrentHashMap<>();
config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"127.0.0.1:9092");
config.put(ConsumerConfig.GROUP_ID_CONFIG,"group_json");
config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
config.put(ErrorHandlingDeserializer.KEY_DESERIALIZER_CLASS, JsonDeserializer.class);
config.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS,JsonDeserializer.class.getClass());
config.put(JsonDeserializer.TRUSTED_PACKAGES,"*");
return new DefaultKafkaConsumerFactory<>(config,new StringDeserializer(),new JsonDeserializer<>(User.class));
}
@Bean
public ConcurrentKafkaListenerContainerFactory<String,User> userKafkaListenerContainerFactory()
{
ConcurrentKafkaListenerContainerFactory<String,User> factory
=new ConcurrentKafkaListenerContainerFactory<>();
factory.setConsumerFactory(userConsumerFactory());
return factory;
}
}
模型
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class User {
private int userId;
private String userName;
private double salary;
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", salary=" + salary +
'}';
}
}
ProducerConfig 类
@Configuration
public class KafkaConfig {
private ProducerFactory<String,User> producerFactory()
{
Map<String,Object> config=new ConcurrentHashMap<>();
config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"127.0.0.1:9092");
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return new DefaultKafkaProducerFactory<>(config);
}
@Bean
public KafkaTemplate<String,User> kafkaTemplate()
{
return new KafkaTemplate<>(producerFactory());
}
}
模型
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class User {
private int userId;
private String userName;
private double salary;
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", salary=" + salary +
'}';
}
}
您需要使用@Bean 对其进行注释并添加此配置:
@Bean
private ProducerFactory<String,User> producerFactory()
{
Map<String,Object> config=new ConcurrentHashMap<>();
config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"127.0.0.1:9092");
config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return new DefaultKafkaProducerFactory<>(config);
}
@Bean
public Map<String, Object> producerConfigs() {
Map<String, Object> props = new HashMap<>();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
return props;
}
@Bean
public ProducerFactory<String, AccountEvent> producerFactory() {
return new DefaultKafkaProducerFactory<>(producerConfigs());
}
@Bean
public KafkaTemplate<String, AccountEvent> kafkaTemplate() {
return new KafkaTemplate<>(producerFactory());
}
如果你想使用带有 kafka 基础设施的项目,我在我的 github 中有它。 https://github.com/gabryellr/banking-system
这个
config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
应该
config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ErrorHandlingDeserializer.class);
但是,不清楚为什么您的受信任包配置没有被应用; 建议您在JsonDeserializer.configure()
方法中设置断点。
编辑
哦...
return new DefaultKafkaConsumerFactory<>(config,new StringDeserializer(),new JsonDeserializer<>(User.class));
当您传入这样的反序列化器实例时,不会使用这些属性; 您必须完全自己构建和配置解串器。
由于您无论如何都想使用ErrorHandlingDeserializer
,因此您应该在此处传递其中一个。
或者,将其更改为
return new DefaultKafkaConsumerFactory<>(config);
我已经找到了发生此错误的原因。 您可以看到在错误部分模型类下创建了两个不同的包。 在Producer中,在com.benz.kafka.api.model
包下创建模型类,在Consumer部分,在com.benz.kafka.consumer.api.model
包下创建模型。 这是根本原因,我将com.benz.kafka.consumer.api.model
更改为com.benz.kafka.api.model
然后它起作用了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.