【问题标题】:Spring Kafka The class is not in the trusted packagesSpring Kafka 类不在可信包中
【发布时间】:2019-01-12 07:25:20
【问题描述】:

在库更新之前的 Spring Boot/Kafka 应用程序中,我使用以下类 org.telegram.telegrambots.api.objects.Update 将消息发布到 Kafka 主题。现在我使用以下org.telegram.telegrambots.meta.api.objects.Update。如您所见 - 它们有不同的包。

应用程序重启后,我遇到了以下问题:

[org.springframework.kafka.KafkaListenerEndpointContainer#1-0-C-1] o.s.kafka.listener.LoggingErrorHandler : Error while processing: null

org.apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition telegram.fenix.bot.update-0 at offset 4223. If needed, please seek past the record to continue consumption.
Caused by: java.lang.IllegalArgumentException: The class 'org.telegram.telegrambots.api.objects.Update' is not in the trusted packages: [java.util, java.lang, org.telegram.telegrambots.meta.api.objects]. 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 (*).
at org.springframework.kafka.support.converter.DefaultJackson2JavaTypeMapper.getClassIdType(DefaultJackson2JavaTypeMapper.java:139) ~[spring-kafka-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.kafka.support.converter.DefaultJackson2JavaTypeMapper.toJavaType(DefaultJackson2JavaTypeMapper.java:113) ~[spring-kafka-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.springframework.kafka.support.serializer.JsonDeserializer.deserialize(JsonDeserializer.java:221) ~[spring-kafka-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at org.apache.kafka.clients.consumer.internals.Fetcher.parseRecord(Fetcher.java:967) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.internals.Fetcher.access$3300(Fetcher.java:93) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.internals.Fetcher$PartitionRecords.fetchRecords(Fetcher.java:1144) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.internals.Fetcher$PartitionRecords.access$1400(Fetcher.java:993) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.internals.Fetcher.fetchRecords(Fetcher.java:527) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.internals.Fetcher.fetchedRecords(Fetcher.java:488) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.KafkaConsumer.pollOnce(KafkaConsumer.java:1155) ~[kafka-clients-1.1.0.jar!/:na]
at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:1115) ~[kafka-clients-1.1.0.jar!/:na]
at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:699) ~[spring-kafka-2.1.8.RELEASE.jar!/:2.1.8.RELEASE]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]

这是我的配置:

@EnableAsync
@Configuration
public class ApplicationConfig {

    @Bean
    public StringJsonMessageConverter jsonConverter() {
        return new StringJsonMessageConverter();
    }

}

@Configuration
public class KafkaProducerConfig {

    @Value("${spring.kafka.bootstrap-servers}")
    private String bootstrapServers;

    @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);
        props.put(ProducerConfig.MAX_REQUEST_SIZE_CONFIG, 15000000);

        return props;
    }

    @Bean
    public ProducerFactory<String, Update> updateProducerFactory() {
        return new DefaultKafkaProducerFactory<>(producerConfigs());
    }

    @Bean
    public KafkaTemplate<String, Update> updateKafkaTemplate() {
        return new KafkaTemplate<>(updateProducerFactory());
    }

}

@Configuration
public class KafkaConsumerConfig {

    @Value("${kafka.consumer.max.poll.interval.ms}")
    private String kafkaConsumerMaxPollIntervalMs;

    @Value("${kafka.consumer.max.poll.records}")
    private String kafkaConsumerMaxPollRecords;

    @Value("${kafka.topic.telegram.fenix.bot.update.consumer.concurrency}")
    private Integer updateConsumerConcurrency;

    @Bean
    public ConsumerFactory<String, String> consumerFactory(KafkaProperties kafkaProperties) {
        return new DefaultKafkaConsumerFactory<>(kafkaProperties.buildConsumerProperties(), new StringDeserializer(), new JsonDeserializer<>(String.class));
    }

    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory(KafkaProperties kafkaProperties) {

        kafkaProperties.getProperties().put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, kafkaConsumerMaxPollIntervalMs);
        kafkaProperties.getProperties().put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, kafkaConsumerMaxPollRecords);

        ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
        factory.setConsumerFactory(consumerFactory(kafkaProperties));

        return factory;
    }

    @Bean
    public ConsumerFactory<String, Update> updateConsumerFactory(KafkaProperties kafkaProperties) {
        return new DefaultKafkaConsumerFactory<>(kafkaProperties.buildConsumerProperties(), new StringDeserializer(), new JsonDeserializer<>(Update.class));
    }

    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, Update> updateKafkaListenerContainerFactory(KafkaProperties kafkaProperties) {

        kafkaProperties.getProperties().put(ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG, kafkaConsumerMaxPollIntervalMs);
        kafkaProperties.getProperties().put(ConsumerConfig.MAX_POLL_RECORDS_CONFIG, kafkaConsumerMaxPollRecords);

        ConcurrentKafkaListenerContainerFactory<String, Update> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
        factory.setConsumerFactory(updateConsumerFactory(kafkaProperties));
        factory.setConcurrency(updateConsumerConcurrency);

        return factory;
    }

}

application.properties

spring.kafka.bootstrap-servers=${kafka.host}:${kafka.port}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.consumer.group-id=postfenix
spring.kafka.consumer.enable-auto-commit=false
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer

如何解决这个问题,让 Kafka 将旧消息反序列化成新消息?

更新

这是我的听众

@Component
public class UpdateConsumer {

    @KafkaListener(topics = "${kafka.topic.update}", containerFactory = "updateKafkaListenerContainerFactory")
    public void onUpdateReceived(ConsumerRecord<String, Update> consumerRecord, Acknowledgment ack) {

        //do some logic here

        ack.acknowledge();
    }

}

【问题讨论】:

    标签: java spring-boot apache-kafka spring-kafka


    【解决方案1】:

    the documentation

    从 2.1 版开始,类型信息可以在记录头中传达,允许处理多种类型。此外,可以使用 Kafka 属性配置序列化器/反序列化器。

    JsonSerializer.ADD_TYPE_INFO_HEADERS(默认为真);设置为 false 以禁用 JsonSerializer 上的此功能(设置 addTypeInfo 属性)。

    JsonDeserializer.KEY_DEFAULT_TYPE;如果不存在标头信息,则用于密钥反序列化的备用类型。

    JsonDeserializer.VALUE_DEFAULT_TYPE;如果不存在标头信息,则用于反序列化值的后备类型。

    JsonDeserializer.TRUSTED_PACKAGES (默认 java.util, java.lang);允许反序列化的包模式的逗号分隔列表; * 表示全部反序列化。

    默认情况下,序列化器会将类型信息添加到标头中。

    the boot documentation

    同样,您可以禁用 JsonSerializer 在 headers 中发送类型信息的默认行为:

    spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer spring.kafka.producer.properties.spring.json.add.type.headers=false

    或者您可以在入站消息转换器中添加类型映射,以将源类型映射到目标类型。

    编辑

    说了这么多,你用的是什么版本?

    【讨论】:

    • 感谢您的回答!我添加了@KafkaListener 实现。我使用 Kafka 1.1.0
    • 我的意思是哪个版本的 spring-kafka。您将需要执行我提出的建议之一 - 禁止发送方的类型标头或将映射添加到反序列化器中的类型映射器。类型标头优先于传递给反序列化器构造函数的目标类型。 new JsonDeserializer&lt;&gt;(Update.class)。我们可能应该在反序列化器中添加一个布尔值,以允许使用提供的类型,即使标头存在。
    • 否;您需要在生产者端使用spring.kafka.producer.properties.spring.json.add.type.headers=false - 但您需要在消费者端使用类型映射来读取任何已经具有标头的现有消息(除非您可以使用旧应用程序版本来使用它们)。请参阅解串器上的setTypeMapperDefaultJackson2JavaTypeMapper 上的setIdClassMapping()。您需要将源类名称映射到目标类。
    • 查看我指向您的链接(引导 Kafka 章节)。这不是标准的引导属性。它确实出现在附录中:spring.kafka.producer.properties.*= # Additional producer-specific properties used to configure the client.
    • 我打开了an issue for this problem
    【解决方案2】:

    有两个重点要提一下。

    1. 生产者和消费者有两个独立的项目。
    2. 那么发送message(value)是Object类型而不是原始类型。

    问题是生产消息对象在消费者端不可用,因为它们是两个独立的项目。

    解决这个问题的两个方法,请按照下面提到的 Spring boot Producer 和 Consumer 应用程序中的步骤操作。

    ----生产者应用程序 -------------

    ** 生产者配置类 **

    import com.kafka.producer.models.Container;    
    import org.apache.kafka.clients.producer.ProducerConfig;
    import org.apache.kafka.common.serialization.StringSerializer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.kafka.core.DefaultKafkaProducerFactory;
    import org.springframework.kafka.core.KafkaTemplate;
    import org.springframework.kafka.core.ProducerFactory;
    import org.springframework.kafka.support.serializer.JsonSerializer;
    import java.util.HashMap;
    import java.util.Map;
    
    @Configuration
    public class KafkaProducerConfig {
    
    @Bean
    public ProducerFactory<String, Container> producerFactory(){
    
        Map<String, Object> config = new HashMap<>();
    
    config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost: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, Container> kafkaTemplate(){
        return new KafkaTemplate<>(producerFactory());
    }
    }
    

    注意:Container 是要在 kafka 主题中发布的自定义对象。


    ** 生产者类 **

    import com.kafka.producer.models.Container;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.kafka.core.KafkaTemplate;
    import org.springframework.kafka.support.KafkaHeaders;
    import org.springframework.messaging.Message;
    import org.springframework.messaging.support.MessageBuilder;
    import org.springframework.stereotype.Service;
    
    @Service
    public class Producer {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(Producer.class);
    private static final String TOPIC = "final-topic";
    
    @Autowired
    private KafkaTemplate<String, Container> kafkaTemplate;
    
    public void sendUserMessage(Container msg) {
        LOGGER.info(String.format("\n ===== Producing message in JSON ===== \n"+msg));
        Message<Container> message = MessageBuilder
                .withPayload(msg)
                .setHeader(KafkaHeaders.TOPIC, TOPIC)
                .build();
        this.kafkaTemplate.send(message);
    }
    }
    

    ** 生产者控制器 **

    import com.kafka.producer.models.Container;
    import com.kafka.producer.services.Producer;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    @RestController
    @RequestMapping("/message")
    public class MessageController {
    
    @Autowired
    private Producer producer;
    
    @PostMapping(value = "/publish")
    public String sendMessageToKafkaTopic(@RequestBody Container containerMsg) {
        this.producer.sendUserMessage(containerMsg);
        return "Successfully Published !!";
    }
    }
    

    注意:Container 类型的消息将作为 JSON 消息发布到 kafka 主题名称 :final-topic。

    ================================================ =================================

    -- 消费者应用程序--

    ** 配置类**

    import com.kafka.consumer.models.Container;
    import org.apache.kafka.clients.consumer.ConsumerConfig;
    import org.apache.kafka.common.serialization.StringDeserializer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.kafka.annotation.EnableKafka;
    import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
    import org.springframework.kafka.core.ConsumerFactory;
    import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
    import org.springframework.kafka.support.serializer.JsonDeserializer;
    import java.util.HashMap;
    import java.util.Map;
    
    @Configuration
    @EnableKafka
    public class KafkaConsumerOneConfig {
    
    @Bean
    public ConsumerFactory<String, Container> consumerFactory(){
        JsonDeserializer<Container> deserializer = new JsonDeserializer<>(Container.class);
        deserializer.setRemoveTypeHeaders(false);
        deserializer.addTrustedPackages("*");
        deserializer.setUseTypeMapperForKey(true);
    
        Map<String, Object> config = new HashMap<>();
    
        config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        config.put(ConsumerConfig.GROUP_ID_CONFIG, "group_one");
        config.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
        config.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);
        config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deserializer);
    
        return new DefaultKafkaConsumerFactory<>(config, new StringDeserializer(), deserializer);
    }
    
    @Bean
    public ConcurrentKafkaListenerContainerFactory<String, Container> kafkaListenerContainerFactory(){
        ConcurrentKafkaListenerContainerFactory<String, Container> factory = new ConcurrentKafkaListenerContainerFactory<>();
        factory.setConsumerFactory(consumerFactory());
        return factory;
    
    }
    }
    

    注意:在这里您可以看到,我们必须使用自定义 JsonDeserializer 来使用来自 final-topic(主题名称)的容器对象类型 Json 消息,而不是使用默认的 JsonDeserializer()。


    ** 消费者服务 **

    import com.kafka.consumer.models.Container;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.kafka.annotation.KafkaListener;
    import org.springframework.messaging.MessageHeaders;
    import org.springframework.messaging.handler.annotation.Headers;
    import org.springframework.messaging.handler.annotation.Payload;
    import org.springframework.stereotype.Service;
    import java.io.IOException;
    
    @Service
    public class ConsumerOne {
    
    private final Logger LOGGER = LoggerFactory.getLogger(ConsumerOne.class);
    
    @KafkaListener(topics = "final-topic", groupId = "group_one", containerFactory = "kafkaListenerContainerFactory")
    public void consumeUserMessage(@Payload Container msg, @Headers MessageHeaders headers) throws IOException {
        System.out.println("received data in Consumer One ="+ msg.getMessageTypes());
    }
    }
    

    【讨论】:

    • 错误Invalid value org.springframework.kafka.support.serializer.JsonDeserializer@279489ac for configuration value.deserializer: Expected a Class instance or class name. 到达这里时:config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deserializer); 看来我必须使用工厂而不是实例。
    【解决方案3】:

    对于这个,有两种方法可以做到这一点,要么在你的反序列化器中,要么在你的 application.yml 中。

    在你的反序列化器中

    在您的解串器中,您在 DefaultKafkaConsumerFactory 中使用它(用于创建您的消费者工厂)。 假设您想创建一个ConsumerFactory&lt;String, Foo&gt; ,其中Foo 是您想用于kafka 消息的模型/POJO。

    你需要 addTrustedPackages from JsonDeserializer 我在 Kotlin 中有一个例子,但它在 java 中的语法几乎相同:

     val deserializer = JsonDeserializer<Foo>()
     deserializer.addTrustedPackages("com.example.entity.Foo") // Adding Foo to our trusted packages
    
     val consumerFactory = DefaultKafkaConsumerFactory(
          consumerConfigs(),  // your consumer config
          StringDeserializer(), 
          deserializer // Using our newly created deserializer
     )
    

    或者在你的application.yml中

    在您的 application.yml 文件中遵循spring-kafka 说明。我们使用以下方法将 com.example.entity.Foo 包中的 Foo 类添加到受信任的商店中:

    spring:
      kafka:
        consumer:
          properties:
            spring.json.trusted.packages: "com.example.entity.Foo"
    

    spring.json.trusted.packages 接受一系列包。您可以指定一个类包,或对任何包使用*。在这种情况下,您无需在 DefaultKafkaConsumerFactory() 中仅在消费者配置中传递您的 deserializer

    【讨论】:

    • 第一种方法帮助我完成了测试,其中消费者是手工创建的。谢谢。
    【解决方案4】:

    我也遇到过这个问题,但是上面的解决方案对我不起作用。但是,诀窍是按如下方式配置 kafka 消费者工厂:

    props.put(JsonDeserializer.TRUSTED_PACKAGES, "your.package.name");
    

    【讨论】:

      【解决方案5】:
      jsonDeserializer.addTrustedPackages("*");
      

      解决了我的 spring-kafka-2.2.8 问题。


      添加到application.properties:

      spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
      spring.kafka.consumer.properties.spring.json.trusted.packages=*
      

      重要提示:

      如果您提供了 Serializer 和 Deserializer,它们将无效 分别为 KafkaConsumer 和 KafkaProducer 的实例。

      参考:
      [1]https://docs.spring.io/spring-kafka/reference/html/#json-serde
      [2]https://github.com/spring-projects/spring-kafka/issues/535

      【讨论】:

      • 如何在application.yml文件中添加这个,请回复。
      【解决方案6】:

      当我想在消费者应用程序中使用消息时遇到类似的问题,我收到 2 个错误:

      1-The class 'someClass' is not in the trusted packages: [java.util, java.lang,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 (*)

      2-org.apache.kafka.common.errors.SerializationException: Error deserializing key/value for partition partion at offset 9902. If needed, please seek past the record to continue consumption.

      我可以通过将此属性添加到 KafkaConfig 类的 kafka 消费者配置生成器方法(makeConfig)中来解决这个问题,以便使用这种方法使用配置,我的问题已经解决:

      private Map<String, Object> makeConfig(ServiceMessagePriority input)
      {
          Map<String, Object> configProps = new HashMap<>();
          configProps.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
          configProps.put(ErrorHandlingDeserializer.KEY_DESERIALIZER_CLASS, ErrorHandlingDeserializer.class);
          configProps.put(ErrorHandlingDeserializer.VALUE_DESERIALIZER_CLASS, ErrorHandlingDeserializer.class);
          configProps.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
          configProps.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
          configProps.put(JsonDeserializer.VALUE_DEFAULT_TYPE, "com.core.model.ServiceMsgDTO");
          configProps.put(JsonDeserializer.USE_TYPE_INFO_HEADERS,false);
          configProps.put(JsonDeserializer.TRUSTED_PACKAGES, "*");
      return configProps;
      }
      

      【讨论】:

      • 你的回答很好,非常感谢。
      【解决方案7】:

      对于那些在使用 时遇到此问题的人,您必须为消费者和流指定受信任的包,因为 Kafka 初始化了 2 个不同的反序列化器

      spring:
        kafka:
          bootstrap-servers: localhost:9092
        producer:
          value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
      
        consumer:
      ...
          properties:
             spring.json.trusted.packages:  "YOUR ENTTIES PACKAGE"
        streams:
      ...
          properties:
            spring.json.trusted.packages: "YOUR ENTTIES PACKAGE"
      

      【讨论】:

        【解决方案8】:

        我的 spring-kafka 版本是 2.2.11,我也遇到了这个错误。

        我收到此错误是因为我在同一个 kafta 主题中使用不同的配置配置了两个消费者。其中一个有 ConsumerFactory,另一个有 ConsumerFactory

        我解决了更改一个消费者配置的错误,因为是错误的。

        只需检查主题的消费者

        【讨论】:

          【解决方案9】:

          解决问题的方法有两种:

          1. 在生产者中禁用类型标头
          2. 在消费者中添加受信任的生产者列表

          在生产者中禁用类型标头

          您的生产者属性文件应如下所示,

          spring:
            profiles: dev
            kafka:
              producer:
                bootstrap-servers: localhost:9092, localhost:9093
                key-serializer: org.apache.kafka.common.serialization.IntegerSerializer
                value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
                properties:
                  acks: 1
                  spring:
                    json:
                      add:
                        type:
                          headers: false
          

          你的消费者属性文件应该如下,

          spring:
            profiles: dev
            kafka:
              consumer:
                bootstrap-servers: localhost:9092
                key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
                value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
                group-id: consumer-group-1
                properties:
                  spring:
                    json:
                      value:
                        default:
                          type: 'com.kafka.consumer.Message'
          

          在消费者中添加受信任的生产者列表

          如果您不想更改生产者属性文件中的任何内容,请按如下方式更新您的消费者属性文件,

          spring:
            profiles: dev
            kafka:
              consumer:
                bootstrap-servers: localhost:9092
                key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
                value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
                group-id: consumer-group-1
                properties:
                  spring:
                    json:
                      value:
                        default:
                          type: 'com.kafka.consumer.Message'
                      type:
                        mapping: 'com.kafka.producer.Message:com.kafka.consumer.Message'
                      trusted:
                        packages: 'com.kafka.producer'
          

          在我的Message 类中,确保你有setter 和getter 以及NoArgsConstructor,否则它不会工作。

          @AllArgsConstructor
          @Setter
          @Getter
          @NoArgsConstructor
          public
          class Message {
          
              Integer id;
          
              String name;
          
              String address;
          
              String phone;
          
              boolean isActive;
          }
          

          消费者监听器:

          @Component
          @Slf4j
          public class KafkaMessageListener {
          
              @KafkaListener(topics = {"test_json"})
              public void OnMessage(Message rc){
                  log.info(rc.getName());
              }
          }
          

          注意:我的生产者和消费者是两个不同的项目,它们的包名称如下,

          制作人:com.kafka.producer.Message

          消费者:com.kafka.consumer.Message

          【讨论】:

            猜你喜欢
            • 2019-08-23
            • 2019-07-05
            • 2019-05-26
            • 1970-01-01
            • 1970-01-01
            • 2019-01-15
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多