theme: nico
你们好,我是金金金。
场景
购物车里面有5个商品,用户勾选了并且提交订单了,此时需要删除购物车对应勾选的商品,
mq
的话涉及到传递用户信息~因为删除对应的购物车商品是需要传递用户信息来知晓对应用户的
- 生产者
- 消费者
排查
看报错很明显就是参数不支持,点击convertAndSend方法,可以看到第四个参数是MessagePostProcessor类型,我们传递的类型不对当然报错了
- 我们在看一下MessagePostProcessor是啥
这个函数是一个函数式接口,用于处理消息。其中,postProcessMessage(Message var1) 是一个必需的方法,用于对消息进行处理。另外,还提供了两个默认方法 postProcessMessage(Message message, Correlation correlation) 和 postProcessMessage(Message message, Correlation correlation, String exchange, String routingKey),用于在处理消息时提供额外的参数,但最终都会调用 postProcessMessage(Message var1) 方法进行实际的消息处理。
解决
-
生产者第四个参数new MessagePostProcessor接口重写postProcessMessage方法
-
消费者使用Message接收数据
测试
- 可以看到用户id已经拿到了,说明用户信息传递成功
优化
监听器逻辑优化
- 为了避免在每个
Listener
都加同样的setUserId
的方法,考虑在公用模块里加。因为无论哪个listener
接受,都需要经过消息转换器,因此考虑在启动类里面里重写消息转化器的fromMessage
方法。
- 监听器里面的set逻辑就不用写了,还是很方便的
优化消息转换器
- 现在我在生产者和消费者的启动类上都写了消息转换器,意味着消息咱们使用的JSON消息转换器 需要在每个模块的启动类里面都定义一个方法并且注入到spring容器当中才能使用,假设微服务有十个模块 都需要,难不成咱们写十遍吗?太繁琐了
- 咱们可以把这个bean放在一个全局模块当中,这个全局模块配置文件里面把定义的方法注入到spring容器里面就可以,需要使用的模块引入这个全局模块依赖坐标就行了。
- 咱们把逻辑放在一个公共模块的配置文件里面
- 我的公共模块资源里面有一个spring.factories文件
意味着Spring Boot在启动时会扫描并激活这些配置类(MyBatisConfig、JsonConfig、MvcConfig)。如果这些配置类中包含@Bean注解的方法,那么这些方法将会被调用,它们的返回值会被注册到Spring容器中作为一个Bean,从而可以被其他组件依赖注入和使用。
- 需要使用的服务只要导入了common这个公共模块的依赖即可,相当于也就有了公共模块里面的bean
- 记得公共模块引入如下依赖
总结
生产者使用
MessagePostProcessor
在消息发送前设置消息属性头,消费者使用Message
参数接收即可
- 编写有误还请大佬指正,万分感谢。