前言
在学习Kafka的过程中,我想实现秒杀和下单功能,其中下单使用消息队列
相关代码
Order类
@Data
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Order {
Long id;
Long user_id;
String user_name;
String phone;
}
测试方法:
public void test_func(Long id){
RLock rLock = redissonClient.getLock("test_"+ id);
try {
rLock.lock(30, TimeUnit.SECONDS);
String res = stringRedisTemplate.opsForValue().get("test_seckill_count");
int count = Integer.parseInt(res);
if(count<=0){}
else{
count--;
stringRedisTemplate.opsForValue().increment("test_seckill_count",-1);
Order order = new Order();
order.setUser_id(id);
// 前端传参
// order.setUser_name();
// order.setPhone();
kafkaTemplate.send("test_order",order);
}
} catch (NumberFormatException e) {
throw new RuntimeException(e);
} finally {
rLock.unlock();
}
}
消费者:
@KafkaListener(topics = "test_order",groupId = "group_test")
public Result createOrder(Order order){
// save(order);//Mybatis-plus
System.out.println(order);//测试用例直接输出
return Result.ok("success");
}
问题
但是在发送消息时出现了如下错误
Cannot convert from [com.kafkatest.kafkatest.entity.Order] to [java.lang.Long] for GenericMessage [payload=Order(id=null, user_id=1, user_name=null, phone=null), headers={kafka_offset=29, kafka_consumer=org.springframework.kafka.core.DefaultKafkaConsumerFactory$ExtendedKafkaConsumer@6bcd609, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=test_order, kafka_receivedTimestamp=1720598058294, kafka_groupId=group_test}]
或者其他的错误,主要就是can not convert from xxx to xxx
解决方法:
因为我是用yml配置的Kafka,所以我仅提供yml的解决方法
spring:
redisson:
config: classpath:redisson.yaml
application:
name: kafkaTest
kafka:
bootstrap-servers: localhost:9092
producer:
key-serializer: org.springframework.kafka.support.serializer.JsonSerializer//加入序列化器
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer//加入序列化器
consumer:
group-id: group_test
key-deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer//注意,如果不配置此项可能会报因为错误找不到ErrorHandling...的错
value-deserializer: org.springframework.kafka.support.serializer.ErrorHandlingDeserializer
properties:
spring.deserializer.key.delegate.class: org.springframework.kafka.support.serializer.JsonDeserializer//加反序列化器
spring.deserializer.value.delegate.class: org.springframework.kafka.support.serializer.JsonDeserializer//加反序列化器
spring.json.trusted.packages: com.kafkatest.kafkatest.entity
如果使用Producer和Consumer来发送消息则需要在props中put相应的key、value serializer和deserializer,以下来自Apache Kafka 简单生产者示例_w3cschool,代码示例如下
//new一个properties
Properties props = new Properties();
//添加kafka地址
props.put("bootstrap.servers", "localhost:9092");
//设置有无返回ack(可选)
props.put("acks", "all");
//设置是否在消息发送失败后自动重试(可选)默认0
props.put("retries", 0);
//关键
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
Producer<String, String> producer = new KafkaProducer<String, String>(props);
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("session.timeout.ms", "30000");
//关键
props.put("key.deserializer",
"org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer",
"org.apache.kafka.common.serialization.StringDeserializer");
@SuppressWarnings("resource")
KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(props);