Springboot整合kafka

本文详细介绍了如何在Kafka中使用自定义序列化器和反序列化器处理复杂对象,包括配置依赖、修改配置文件以及实现序列化与反序列化的具体代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(一)添加依赖

	    <dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId>
		</dependency>
  • 1
  • 2
  • 3
  • 4

(二)配置文件

spring:
  kafka:
    bootstrap-servers: 192.168.10.130:9092,192.168.10.130:9093,192.168.10.130:9094
    #生产者 “值” 序列化(自定义ObjectSerializer类)
    producer:
      value-serializer: org.pc.serializer.ObjectSerializer
    consumer:
          group-id: cluster-group
      #消费者 “值” 反序列化(自定义ObjectDeserializer类)
      value-deserializer: org.pc.deserializer.ObjectDeserializer

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

(三)注册KafkaTemplate
  Springboot自动装载了KafkaTemplate,无需手动注册

(四)使用Kafka生产者客户端生产消息

@RestController
public class KafkaController {
    private KafkaTemplate<String, Object> kafkaTemplate;
    @Autowired
    public KafkaController(KafkaTemplate<String, Object> kafkaTemplate) {
        this.kafkaTemplate = kafkaTemplate;
    }
    @GetMapping("/message/send")
    public String sendMessage(@RequestParam String message){
        //向kafka集群中的"cluster-topic"发送消息
        kafkaTemplate.send("cluster-topic", 0, "message", message);
        return message;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

(五)使用Kafka消费者客户端消费消息

/**
 * 消费者监听器
 * 作用:只要加上@KafkaListener,设置好topics,就可以订阅该主题产生的消息(相当于消费者客户端)
 */
@Component
public class ConsumerListener {
    @KafkaListener(topics = "cluster-topic")
    public void consume(String message){
        System.out.println(message);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(六)出现问题及其解决
1、当发送Object类型消息时,报错"Can’t convert value of class org.pc.entity.User to class org.apache.kafka.common.serialization.StringSerializer specified in value.serializer"?

原因解析:在生产消息时,Kafka的Java客户端默认使用的是StringSerializer序列化类,但是他只能序列化String类型对象,要是其他类型对象,就会无法序列化。同理,在消费消息时,需要反序列化,也会遇到这个问题。

解决办法:自定义Kafka“生产者客户端的序列化类”和“消费者客户端的反序列化类”,目的实现对Object对象的序列化与反序列化。

(1)生产者客户端 “值” 的序列化:

/**
 * Object 序列化
 * @author 咸鱼
 * @date 2018/10/14 8:43
 */
public class ObjectSerializer implements Serializer<Object> {
@Override
public void configure(Map configs, boolean isKey) {

}

@Override
public byte[] serialize(String topic, Object data) {
    byte[] dataArray = null;
    try {
        //1、创建OutputStream对象
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        //2、创建OutputStream的包装对象ObjectOutputStream,PS:对象将写到OutputStream流中
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
        //3、将对象写到OutputStream流中
        objectOutputStream.writeObject(data);
        //4、将OutputStream流转换成字节数组
        dataArray = outputStream.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return dataArray;
}

@Override
public void close() {

}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

(2)消费者客户端 “值” 的反序列化:

/**
 * Object 反序列化
 * @author 咸鱼
 * @date 2018/10/14 9:13
 */
public class ObjectDeserializer implements Deserializer<Object> {
@Override
public void configure(Map configs, boolean isKey) {

}

@Override
public Object deserialize(String topic, byte[] data) {
    Object object = null;

    try {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        object = objectInputStream.readObject();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return object;
}

@Override
public void close() {

}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

(3)修改配置文件

spring:
  kafka:
    bootstrap-servers: 192.168.10.130:9092,192.168.10.130:9093,192.168.10.130:9094
    #生产者 “值” 序列化
    producer:
      value-serializer: org.pc.serializer.ObjectSerializer
    consumer:
          group-id: cluster-group
      #消费者 “值” 反序列化
      value-deserializer: org.pc.deserializer.ObjectDeserializer

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

(4)测试
生产消息:

@PostMapping("/user")
    public User saveUser(@RequestBody User user){
        kafkaTemplate.send("object-topic", 0, "message", user);
        return user;
    }
  • 1
  • 2
  • 3
  • 4
  • 5

消费消息:

@KafkaListener(topics = "object-topic")
    public void consume(Object object){
        System.out.println(object);
    }
  • 1
  • 2
  • 3
  • 4

2、报错如下:javax.management.InstanceAlreadyExistsException: kafka.consumer:type=app-info,id=gx-test-20170629?

原因解析:如果使用了ConcurrentMessageListenerContainer 的实现,并且配置了并发度大于1,同时配置了kafka的 client.id属性则会出现上述问题,而当你配置为1的时候不会出现上述log。

解决办法:不配置client.id这一项,kakfa中会默认为多个线程生成id

        </div>
					<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-778f64ae39.css" rel="stylesheet">
            </div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值