MQ传递用户信息

115 阅读5分钟

你们好,我是金金金。

image.png

场景

购物车里面有5个商品,用户勾选了并且提交订单了,此时需要删除购物车对应勾选的商品,mq的话涉及到传递用户信息~因为删除对应的购物车商品是需要传递用户信息来知晓对应用户的

  • 生产者

image.png

  • 消费者 image.png
  • 启动服务时,报错如上:数据源拒绝建立连接,服务器发送消息:“连接过多”

排查

看报错很明显就是参数不支持,点击convertAndSend方法,可以看到第四个参数是MessagePostProcessor类型,我们传递的类型不对当然报错了

image.png

  • 我们在看一下MessagePostProcessor是啥

image.png

这个函数是一个函数式接口,用于处理消息。其中,postProcessMessage(Message var1) 是一个必需的方法,用于对消息进行处理。另外,还提供了两个默认方法 postProcessMessage(Message message, Correlation correlation) 和 postProcessMessage(Message message, Correlation correlation, String exchange, String routingKey),用于在处理消息时提供额外的参数,但最终都会调用 postProcessMessage(Message var1) 方法进行实际的消息处理。

解决

  1. 生产者第四个参数new MessagePostProcessor接口重写postProcessMessage方法

image.png

  1. 消费者使用Message接收数据

image.png

测试

image.png

可以看到用户id已经拿到了,说明用户信息传递成功

优化

监听器逻辑优化

  1. 为了避免在多个Listener都加同样的setUserId的方法,因为无论哪个listener接收,都需要经过消息转换器,因此在启动类里面里重写消息转化器的fromMessage方法。 image.png

2.其实本模块内有十个甚至上百个监听器,里面的set逻辑都不用写了,还是很方便的

image.png

优化消息转换器

  • 现在我在生产者和消费者的启动类上都写了消息转换器,意味着消息咱们使用的JSON消息转换器 需要在每个模块的启动类里面都定义一个方法并且注入到spring容器当中才能使用,假设微服务有十个模块 都需要,难不成咱们写十遍吗?太繁琐了
  • 咱们可以把这个bean放在一个全局模块当中,这个全局模块配置文件里面把定义的方法注入到spring容器里面就可以,需要使用的模块引入这个全局模块依赖坐标就行了。
  1. 咱们把逻辑放在一个公共模块的配置文件里面

image.png

image.png

  1. 我的公共模块资源里面有一个spring.factories文件

image.png

image.png

意味着Spring Boot在启动时会扫描并激活这些配置类(MyBatisConfig、JsonConfig、MvcConfig)。如果这些配置类中包含@Bean注解的方法,那么这些方法将会被调用,它们的返回值会被注册到Spring容器中作为一个Bean,从而可以被其他组件依赖注入和使用。

  1. 需要使用的服务只要导入了common这个公共模块的依赖即可,相当于也就有了公共模块里面的bean

image.png

  1. 记得公共模块引入如下依赖

image.png

总结

生产者使用MessagePostProcessor在消息发送前设置消息属性头,消费者使用Message参数接收即可

  • 编写有误还请大佬指正,万分感谢。