Spring Kafka跨项目传同字段DTO报ClassNotFoundException问题求助
问题根因
Spring Kafka默认的JsonSerializer在序列化对象时,会自动将发送方数据类的全限定名写入消息头的__TypeId__字段,消费方的JsonDeserializer默认会根据该字段查找对应类完成反序列化,两个项目的PostViewCountDTO包路径不一致,就会抛出类找不到异常。
解决方案
方案1:消费端直接指定反序列化目标类(改法最少,无需修改生产者代码)
直接修改消费者配置,忽略消息头中的类路径信息,强制用本地项目的PostViewCountDTO反序列化:
- 调整
postViewCountDTO_ConsumerFactory配置,显式传入自定义的JsonDeserializer:
@Bean public ConsumerFactory<String, PostViewCountDTO> postViewCountDTO_ConsumerFactory() { // 直接指定用本地的PostViewCountDTO反序列化 JsonDeserializer<PostViewCountDTO> valueDeserializer = new JsonDeserializer<>(PostViewCountDTO.class); // 忽略消息头中携带的发送方类路径信息 valueDeserializer.setUseTypeHeaders(false); return new DefaultKafkaConsumerFactory<>( postViewConsumerConfigs(), new StringDeserializer(), valueDeserializer ); }
配置完成后重启消费者即可正常接收数据。
方案2:生产端关闭类路径信息写入(适合可修改生产者代码的场景)
在生产者的序列化配置中添加参数,禁止写入类路径头:
// 通用JsonSerializer类的getStringObjectMap方法中添加配置 props.put(JsonSerializer.ADD_TYPE_INFO_HEADERS, false);
该配置生效后,生产者发送的消息不会携带发送方类路径,消费端只要字段匹配就能正常反序列化,配合方案1的消费端配置稳定性更高。
方案3:改用字符串序列化/反序列化(兼容性最强,不受框架序列化逻辑限制)
如果不想依赖Spring Kafka的JSON序列化逻辑,可以改用字符串作为中间格式,自行处理JSON转换:
- 生产者配置value序列化器为
StringSerializer,发送前将DTO转为JSON字符串 - 消费者配置value反序列化器为
StringDeserializer,接收后将JSON字符串转为本地DTO - 序列化/反序列化工具可以直接用Spring自带的
ObjectMapper。
方案4:抽取公共DTO依赖(适合多服务频繁交互的场景)
将PostViewCountDTO这类公共数据类抽成独立的公共Jar包,生产者和消费者都引入该Jar包,保证类全限定名完全一致,从根源避免类路径不一致问题。
内容的提问来源于stack exchange,提问作者YeonCheol Jang
相关产品推荐
相关产品推荐

