Kafka 模板 - 使用通配符时不适用于参数

Kafka Template - Not Applicable for the Arguments when using wildcard

我一直在构建 Kafka Producer Service。我使用 ? 通配符类型的泛型作为键值,因此它可以是 Integer String

@Slf4j
public abstract class ProducerService<T> {

    protected KafkaClientConfigProperties properties;

    @Autowired
    protected KafkaTemplate<?, T> kafkaTemplate;

    public void send(T value, Iterable<Header> headers) {
        ProducerRecord<?, T> record = new ProducerRecord<>(properties.getTopic(), null, null, null, value, headers);
        this.kafkaTemplate.send(record);
    }

然而,在使用参数 ProducerRecord 调用 send 方法时,我遇到了

的错误

The method send(ProducerRecord<capture#2-of ?,T>) in the type KafkaTemplate<capture#2-of ?,T> is not applicable for the arguments (ProducerRecord<capture#3-of ?,T>)

我也试过了

ProducerRecord<String, T> record = new ProducerRecord<>(properties.getTopic(), null, null, null, value, headers);

错误为

ProducerRecord<String, T> record = new ProducerRecord<>(properties.getTopic(), null, null, null, value, headers);

有人可以帮我理解代码有什么问题吗?谢谢

changed/fixed 这里有各种各样的东西。首先回答你问的问题。您收到相关错误的原因是,您正在创建的 ProducerRecord 接受了一个 null 键变量。

因为这个 class 是通用的,期望 K 作为键的类型和 V 作为值的类型,传入 null 意味着没有推断 K 类型的方式,这也是由于您 ? 作为键类型也是不正确的事实而增加的。

有多种方法可以缓解这种情况。

  1. 如果您真的有兴趣通过 headers 发送,那么您的 class 也应该接受密钥类型(而不是通配符)。考虑以下示例:
public abstract class ProducerService<K, T> {

    @Autowired
    protected KafkaTemplate<K, T> template;

    public void send(T value, Iterable<Header> headers) {
    ProducerRecord<K, T> record = new ProducerRecord<>("topic", null, null, null, value, headers);
    template.send(record);
    }

}
  1. 如果您对通过自定义 headers 发送不感兴趣,只需调用 KafkaTemplate#send 并传入要发送的 object 就足够了:
public abstract class ProducerService<T> {

    @Autowired
    protected KafkaTemplate<String, T> template;

    public void send(T value, Iterable<Header> headers) {
    template.send("topic", value);
    }

}

正如您从上面的两个示例中看到的那样,键入正确的键类型而不使用通配符对您来说应该没问题。最后,还有一个建议是避免使 class 通用。

无需为特定 object 类型实现生产者服务的多个实现。您可以简单地尝试概括您的方法,以便能够处理任何类型的值。