Springboot集成RabbitMQ关于对象传输过程中的序列化及反序列化

1、问题介绍

    在Springboot项目中使用RabbitMQ作为消息中间件使用过程中,有时候我们会使用java对象作为传输的消息,默认情况下允许使用java对象作为传输的消息,但是却有着严格的条件限制:

    1、生产者和消费者中的java对象必须相同;

    2、java对象中的包名也必须一致。

    如果在项目中开发者和消费者属于同一个项目则没有问题,如果开发者和消费者属于不同项目则第2个条件则比较麻烦,当然也有解决办法。比如实体类作为基础包引入生产者和消费者项目中等等。

    还有一种方法是通过在生产者中将java对象转为json字符串,在消费者中将json字符串转回java对象。这种方法有很多弊端,首先要增加代码量(互相装换),还有就是针对不同的对象需要增加转换的代码。

2、解决办法

     针对上面的问题,翻阅了很多资料,也阅读了部分源码,发现可以通过设置RabbitMQ的MessageConverter解决,废话不多说直接上图。

    生产者:

    生产者中只需要设置消息转换器为Jackson2JsonMessageConverter;

  消费者:

    消费者中需要增加一个配置类,如上图所示,贴上代码:

import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurer;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;

@Configuration
public class RabbitConfig implements RabbitListenerConfigurer {
    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar rabbitListenerEndpointRegistrar) {
        rabbitListenerEndpointRegistrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
    }

    @Bean
    MessageHandlerMethodFactory messageHandlerMethodFactory(){
        DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
        messageHandlerMethodFactory.setMessageConverter(mappingJackson2MessageConverter());
        return messageHandlerMethodFactory;
    }

    @Bean
    public MappingJackson2MessageConverter mappingJackson2MessageConverter(){
        return  new MappingJackson2MessageConverter();
    }
}

     注意:在消费者的java对象中必须有一个无参的构造函数,否则也会报错。

    以上,问题解决。

 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
# seckill 基于SpringBoot+Reds+RabbitMQ实现的分布式秒杀系统 #### 整体流程 前端页面采用隐藏秒杀地址和使用随机秒杀地址来防止用户恶意刷接口,点击秒杀时会让用户输入数字计算验证码,输入正确后进入后端业务逻辑。 后端业务逻辑分为生产者和消费者。 **生产者** 1. 生产者**首先进行预加载**,查询所有的商品列表,把每一个商品根据商品ID 和 库存容量 加入到redis ,其次做一个内存标记,使用hashMap,将每一个商品id 都标记为 false。 2. 使用令牌桶算法对其进行限流 3. 判断刚刚随机生成的路径是否正确,然后在判断该商品是否已经卖出根据内存标记,如果都满足那么在redis预减库存(因为初始化时,每一个商品Id和库存都存入redis) 4. 判断库存是否小于 0 ,如果不小于0说明减库存成功, 5. 接着判断是否秒杀成功,从redis 根据用户id 和商品id查询,如果存在说明该用户已经秒杀,不能重复秒杀 6. 加入MQ,将用户id 和商品ID封装成对象序列化成JSON 字符串。 **消费者** 1. 从队列数据,将JSON字符串转换为对象,取出用户ID 和商品Id 2. 从数据库判断库存是否 <= 0,如果小于 0 说明库存为0直接返回。 3. 从缓存查看该订单是否秒杀到,如果秒杀到直接返回。没有秒杀到在缓存写入该秒杀订单 4. 执行秒杀事务,先判断减库存是否成功,如果成功写入秒杀订单。 #### 商品超卖问题 在商品表添加一个版本号字段,减库存业务时,通过商品id获取商品的版本号,在减库存操作时,先判断查询的verison 是否一致,一致则减库存成功。写入秒杀订单。 ``` update set seckill_goods stock = stock - 1, version = version + 1 where id = #{goodsId} and stock > 0 and version = #{version} ``` #### ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
在Java,可以使用RabbitMQ进行消息传递,并且可以对对象进行序列化反序列化。下面是一个示例代码,展示了如何使用RabbitMQ和Java对象进行序列化。 首先,你需要在你的项目引入RabbitMQ的相关依赖。可以在Maven添加以下依赖项: ```xml <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.12.0</version> </dependency> ``` 接下来,你需要创建一个Java对象,该对象需要实现`Serializable`接口,以便能够在网络上进行序列化反序列化。例如: ```java import java.io.Serializable; public class Message implements Serializable { private String content; public Message(String content) { this.content = content; } public String getContent() { return content; } } ``` 然后,你可以使用RabbitMQ发送和接收消息。下面是一个简单的示例: ```java import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; import com.rabbitmq.client.MessageProperties; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.concurrent.TimeoutException; public class RabbitMQExample { private static final String QUEUE_NAME = "my_queue"; public static void main(String[] args) { // 创建连接工厂 ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { // 创建队列 channel.queueDeclare(QUEUE_NAME, true, false, false, null); // 发送消息 Message messageToSend = new Message("Hello RabbitMQ!"); byte[] serializedMessage = serializeObject(messageToSend); channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, serializedMessage); // 接收消息 channel.basicConsume(QUEUE_NAME, true, (consumerTag, delivery) -> { Message receivedMessage = (Message) deserializeObject(delivery.getBody()); System.out.println("Received message: " + receivedMessage.getContent()); }, consumerTag -> {}); } catch (IOException | TimeoutException | ClassNotFoundException e) { e.printStackTrace(); } } private static byte[] serializeObject(Object object) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(object); oos.flush(); return bos.toByteArray(); } private static Object deserializeObject(byte[] bytes) throws IOException, ClassNotFoundException { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } } ``` 在上面的示例,`serializeObject`和`deserializeObject`方法分别将Java对象序列化为字节数组和将字节数组反序列化为Java对象。通过调用`basicPublish`方法,可以将序列化后的消息发送到指定的队列。 使用RabbitMQ进行对象序列化时,需要确保发送方和接收方都可以访问相同的对象类定义。否则,可能会导致反序列化失败。 希望以上信息能对你有所帮助!如有任何疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值