应用侧

经过学习发现传递的都是字符串对象,但是微服务里可不会只有字符串才对,常用的我直接传个实体类dto,就像是redis一样嘛,那么MQ是否也支持呢?

在common里创建一个消息对象类,若想要能传输这种实体类,那么类必须要实例化

  1. package com.zhaoxy.study.common;
  2. import lombok.Data;
  3. import java.io.Serializable;
  4. /**
  5. * 以对象的方式来传输消息
  6. */
  7. @Data
  8. public class MsgObj implements Serializable {
  9. private String id;
  10. private String name;
  11. }

如果这个实体类没有实例化,那么会报错,因为对象无法转换成二进制对象。

消费者只需要把参数类型改成对应对象就可以了:

  1. package com.zhaoxy.mqconsumer;
  2. import com.zhaoxy.study.common.Constant1;
  3. import com.zhaoxy.study.common.MsgObj;
  4. import org.springframework.amqp.rabbit.annotation.Queue;
  5. import org.springframework.amqp.rabbit.annotation.RabbitListener;
  6. import org.springframework.stereotype.Component;
  7. @Component
  8. public class MqConsumerListener {
  9. @RabbitListener(queuesToDeclare = @Queue(Constant1.queueName))
  10. public void listener(MsgObj obj){
  11. System.out.println("接收到了生产者的消息:" + obj);
  12. }
  13. }

生产者也是同理:

  1. package com.zhaoxy.mqprod;
  2. import com.zhaoxy.study.common.Constant1;
  3. import com.zhaoxy.study.common.MsgObj;
  4. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  5. import org.springframework.stereotype.Component;
  6. import javax.annotation.PostConstruct;
  7. import javax.annotation.Resource;
  8. import java.util.UUID;
  9. @Component
  10. public class MqProdService {
  11. @Resource
  12. private RabbitTemplate rabbitTemplate;
  13. /**
  14. * 消息生产者,用途就是每次项目启动后都生成一次消息。
  15. *
  16. * 一遍两遍三四遍,五遍六遍七八遍,
  17. * 九遍十遍十一遍,学习完毕全不见。
  18. */
  19. @PostConstruct
  20. public void prodMessage(){
  21. // 模式1,给指定队列发送一个uuid
  22. for (int i = 0; i < 5; i++) {
  23. MsgObj msgObj = new MsgObj();
  24. msgObj.setId(UUID.randomUUID().toString());
  25. msgObj.setName("name-"+i);
  26. rabbitTemplate.convertAndSend(Constant1.queueName, msgObj);
  27. }
  28. }
  29. }

然后先重启消费者,再启动生产者,查看控制台输出情况:
image.png

服务侧

在MQ的控制台查看队列里的消息,如果没有做处理的话,拿到的就是经过base64加密后的字符串:
image.png

这种数据我们并无法知晓内容,得在common模块中增加config类,使得各module都使用统一的序列化方式:

  1. package com.zhaoxy.study.common;
  2. import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
  3. import org.springframework.amqp.support.converter.MessageConverter;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration
  7. public class MqConfig {
  8. // 消息转换配置
  9. @Bean
  10. public MessageConverter jsonMessageConverter(){
  11. return new Jackson2JsonMessageConverter();
  12. }
  13. }

但是这样有一个问题,就是这种的配置并不会真的生效,因为consumer和prod引入依赖后,并不会加载到它里面的config配置,想要让它生效,就需要用到另一个特殊但是极为常用的技术。

就是spring.factories文件,在springboot应用中被广泛流传,为什么引入一个依赖后只需要配置好服务地址就能生效?就是因为在引入包里就有spring.factories文件,使得配置的类得以在项目启动中被加载执行。

做法很简单,在common模块下的resources文件夹内,先新建一个【META-INF】文件夹,再下一层新建【spring.factories】文件。
image.png

在文件里需要写上核心内容:

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhaoxy.study.common.MqConfig

如果有多个,那么就把各个类以英文逗号相隔,如下:

  1. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  2. com.zhaoxy.study.common.MqConfig,
  3. com.zhaoxy.study.common.MqConfig,
  4. # 等等~~~~~

然后只重启生产者服务即可,不启动consumer是为了避免消息消费了看不到了,启动后查看控制台里,获取消息看看结果如何:
image.png