Spring 卡夫卡制作人JSON序列化

Spring 卡夫卡制作人JSON序列化,spring,apache-kafka,spring-cloud-stream,spring-kafka,Spring,Apache Kafka,Spring Cloud Stream,Spring Kafka,我正在尝试使用SpringCloudStream与卡夫卡进行集成。正在编写的消息是Java POJO,虽然它按预期工作(消息正在写入主题,我可以使用消费类应用程序读取),但在尝试集成Kafka Connect以接收来自主题的消息时,消息开头添加了一些未知字符,这造成了麻烦 在默认设置下,这是推送到卡夫卡的消息:   contentType "text/plain"originalContentType "application/json;charset=UTF-8"{"pa

我正在尝试使用SpringCloudStream与卡夫卡进行集成。正在编写的消息是Java POJO,虽然它按预期工作(消息正在写入主题,我可以使用消费类应用程序读取),但在尝试集成Kafka Connect以接收来自主题的消息时,消息开头添加了一些未知字符,这造成了麻烦

在默认设置下,这是推送到卡夫卡的消息:

     contentType   "text/plain"originalContentType    "application/json;charset=UTF-8"{"payload":{"username":"john"},"metadata":{"eventName":"Login","sessionId":"089acf50-00bd-47c9-8e49-dc800c1daf50","username":"john","hasSent":null,"createDate":1511186145471,"version":null}}
如果我在Java应用程序中配置Kafka producer,则消息将写入主题,而不包含前导字符/标题:

@Configuration
public class KafkaProducerConfig {

    @Bean
    public ProducerFactory<String, Object> producerFactory() {
        Map<String, Object> configProps = new HashMap<>();
        configProps.put(
            ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,
            "localhost:9092");
        configProps.put(
            ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,
            StringSerializer.class);
        configProps.put(
            ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,
            JsonSerializer.class);

        return new DefaultKafkaProducerFactory<String, Object>(configProps);
    }

    @Bean
    public KafkaTemplate<String, Object> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }
}
因为我只是在设置键/值序列化程序,所以我希望能够在
application.yml
properties文件中进行设置,而不是通过代码进行设置。 但是,当更新yml以指定序列化程序时,它并没有像我预期的那样工作,即它没有生成与Java中配置的生产者相同的消息(如上所述):

关于卡夫卡的信息:

{"payload":{"username":"john"},"metadata":{"eventName":"Login","sessionId":"089acf50-00bd-47c9-8e49-dc800c1daf50","username":"john","hasSent":null,"createDate":1511186145471}
"/wILY29udGVudFR5cGUAAAAMInRleHQvcGxhaW4iE29yaWdpbmFsQ29udGVudFR5cGUAAAAgImFwcGxpY2F0aW9uL2pzb247Y2hhcnNldD1VVEYtOCJ7InBheWxvYWQiOnsidXNlcm5hbWUiOiJqb2huIn0sIm1ldGFkYXRhIjp7ImV2ZW50TmFtZSI6IkxvZ2luIiwic2Vzc2lvbklkIjoiNGI3YTBiZGEtOWQwZS00Nzg5LTg3NTQtMTQyNDUwYjczMThlIiwidXNlcm5hbWUiOiJqb2huIiwiaGFzU2VudCI6bnVsbCwiY3JlYXRlRGF0ZSI6MTUxMTE4NjI2NDk4OSwidmVyc2lvbiI6bnVsbH19"

是否可以仅通过应用程序yml对此进行配置?是否缺少其他设置?

请参见生产者属性(
…session.producer.useNativeEncoding
)中的
headerMode
useNativeEncoding

headerMode

设置为raw时,禁用输出上的标头嵌入。仅对本机不支持消息头且需要嵌入消息头的消息传递中间件有效。在为非Spring云流应用程序生成数据时非常有用

默认值:embeddedHeaders

使用NativeEncode

设置为true时,出站消息由客户端库直接序列化,客户端库必须进行相应配置(例如,设置适当的Kafka生产者值序列化程序)。使用此配置时,出站消息编组不基于绑定的contentType。使用本机编码时,使用者有责任使用适当的解码器(例如:Kafka使用者值反序列化器)对入站消息进行反序列化。此外,当使用本机编码/解码时,headerMode属性将被忽略,并且头不会嵌入到消息中

默认值:false


以上答案归功于@Gary

为了完整起见,我现在使用的配置如下

spring:
  profiles: local
  cloud:
    stream:
      bindings:
        session:
          producer:
            useNativeEncoding: true
          destination: session
          contentType: application/json
      kafka:
        binder:
          brokers: localhost
          zkNodes: localhost
          defaultZkPort: 2181
          defaultBrokerPort: 9092
        bindings:
          session:
            producer:
              configuration:
                value:
                  serializer: org.springframework.kafka.support.serializer.JsonSerializer
                key:
                  serializer: org.apache.kafka.common.serialization.StringSerializer

现在,可以使用
spring.kafka.producer.value序列化程序
属性

yml:

特性:

spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer

谢谢你的建议。然而,我之前尝试过这两种方法,但运气都不好。当使用
headeMode=raw
时,我得到的是一个字节流;当我使用
useNativeEncoding=true
时,我会收到一条关于主题的消息,内容类型为
application/octet stream
,其中仍然包含标题。
spring:
   kafka:
     producer:
        value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer