我认为总的来说这是个好方法。关于主题或多个模式的单一消息模式总是一个好问题,两者都有一些亮点和缺点,您可以在Martin Kleppmann article.中阅读更多相关信息
当您决定在单个主题上有多个事件时,从 rest api 开始,然后是 Kafka 生产者和消费者,您可以使用相同的方法序列化和反序列化事件,@JsonTypeInfo 和 @JsonSubTypes 可以完成这项工作:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = LMSEvent.class, name = "LMSEvent"),
@JsonSubTypes.Type(value = YetAnotherEvent.class, name = "YetAnotherEvent")
})
public interface Event {
String getType();
default boolean hasType(String type) {
return getType().equalsIgnoreCase(type);
}
default <T> T getConcreteEvent(Class<T> clazz) {
return clazz.cast(this);
}
}
当您使用 spring-kafka 使用该类型的消息时,您可以定义一些非常简洁的代码,其中每个方法都使用具体的事件类型,因此您不需要自己编写一些肮脏的转换:
@KafkaListener(topics = "someEvents", containerFactory = "myKafkaContainerFactory")
public class MyKafkaHandler {
@KafkaHandler
void handleLMSEvent(LMSEvent event) {
....
}
@KafkaHandler
void handleYetAnotherEvent(YetAnotherEvent yetAnotherEvent) {
...
}
@KafkaHandler(isDefault = true)
void handleDefault(@Payload Object unknown,
@Header(KafkaHeaders.OFFSET) long offset,
@Header(KafkaHeaders.RECEIVED_PARTITION) int partitionId,
@Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
logger.info("Server received unknown message {},{},{}", offset, partitionId, topic);
}
}
Full code