这里以两个项目为例,一个消息的生产者,一个消息的消费者,接着上篇单项目的讲。
目录结构:
rabbitmq作为消息生产者,发送消息。rabbitmqreceiver消息的接收者,消费消息。
发送字符串的时候在两个项目之间是没问题的,大家可以自己测试。
发送端代码:
public void run(String... args) throws Exception {
User user=new User();
for (int i = 0; i < 10; i++) {
user.setUserName("庞坤");
user.setAge(i);
user.setAddress("上海市徐汇区漕河泾开发区");
rabbitTemplate.convertAndSend("my-rabbitmq", user);
System.out.println("消息发送了"+(i+1)+"次");
}
System.out.println("发送结束");
}
接收端的代码(两边一样):
@RabbitListener(queues="my-rabbitmq")
public void receive(User user){
System.out.println("我收到的消息是:"+user);
System.out.println("Address:"+user.getAddress());
System.out.println("UserName:"+user.getUserName());
System.out.println("Age:"+user.getAge());
}
rabbitmq的log:
消息发送了1次
消息发送了2次
消息发送了3次
消息发送了4次
消息发送了5次
消息发送了6次
消息发送了7次
消息发送了8次
消息发送了9次
消息发送了10次
发送结束
我收到的消息是:com.rhett.rabbitmq.User@32356124
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:1
我收到的消息是:com.rhett.rabbitmq.User@49630975
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:3
我收到的消息是:com.rhett.rabbitmq.User@325be57c
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:5
我收到的消息是:com.rhett.rabbitmq.User@2ad5fd18
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:7
我收到的消息是:com.rhett.rabbitmq.User@33f08527
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:8
从这里可以看到消息的发送和消费是异步的,消息生成后不会等待被消费使用。所以大家可以充分利用这点来使用mq。
rabbitmqreceive的log如下图:
这里是部份错误日志,没消费一条消息都会报错。
从上面的log可以看出rabbitmqreceive的User对象无法接收rabbitmq传过来的User对象,而是在找寻rabbitmq下的user。
等下再说解决方案,这里先看HashMap的传送。
发送端代码:
public void run(String... args) throws Exception {
HashMap<String,Object> hm=new HashMap<String,Object>();
for (int i = 0; i < 10; i++) {
hm.put("userName", "庞坤");
hm.put("age", i+1);
hm.put("address", "上海市徐汇区漕河泾开发区");
rabbitTemplate.convertAndSend("my-rabbitmq", hm);
System.out.println("消息发送了"+(i+1)+"次");
}
System.out.println("发送结束");
}
接收端的代码(两边一样):
@RabbitListener(queues="my-rabbitmq")
public void receive(HashMap<String,Object> hm){
System.out.println("我收到的消息是:"+hm);
}
rabbitmq的log:
消息发送了1次
消息发送了2次
消息发送了3次
消息发送了4次
消息发送了5次
消息发送了6次
消息发送了7次
消息发送了8次
消息发送了9次
消息发送了10次
发送结束
2017-04-08 22:15:07.014 INFO 651 --- [ main] com.rhett.rabbitmq.RabbitmqApplication : Started RabbitmqApplication in 5.118 seconds (JVM running for 5.587)
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=2}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=3}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=5}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=7}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=9}
rabbitmqreceive的log:
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=1}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=4}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=6}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=8}
我收到的消息是:{address=上海市徐汇区漕河泾开发区, userName=庞坤, age=10}
此时rabbitmqreceive中的接收方法是可以正常执行的,传送String字符串的时候也是ok的。
现在再来看传送User对象在同项目中成功,在其他项目中失败的原因。
还是这张图,其中消息队列中的user对象明确指定,应用的是com.rhett.rabbitmq.user,虽然rabbitmqreceive中定义了同样的User类,但是却无法接收队列中的数据。所以,接收的对象一定要是com.rhett.rabbitmq.user这里的类生成的对象。(具体其它原因大家自己考虑,这里是我个人的观点,只是从表面上分析)
从这点入手,1、另写一个pojo专门用来存放产生消息的对象;2、将rabbitmq整个项目引入到rabbitmqreceive中。
这里我采用第二种方式,pom中的代码如下:
<!--引入rabbitmq -->
<dependency>
<groupId>com.rhett</groupId>
<artifactId>rabbitmq</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
继续使用user作为消息的传送对象,查看rabbitmqreceive中的log:
我收到的消息是:com.rhett.rabbitmq.User@6a45940b
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:0
我收到的消息是:com.rhett.rabbitmq.User@4f4ee63d
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:3
我收到的消息是:com.rhett.rabbitmq.User@21940478
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:4
我收到的消息是:com.rhett.rabbitmq.User@5e2659c8
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:6
我收到的消息是:com.rhett.rabbitmq.User@18857bcb
Address:上海市徐汇区漕河泾开发区
UserName:庞坤
Age:8
此时可以看出在rabbitmqreceive中也可以正常的消费user对象的消息了。
除了引入同一个类包来实现对象的消费外,还可以用Json来实现,发送的时候把user对象转为Json字符串,接收的时候用字符串来接收,然后转成相应的对象,不需要引用com.rhett.rabbitmq.user。这种方法我试过,是可以的,以后把代码补上来。
以下是补充的一个方法:
今天早上起来后想到一个新方法,就是两个项目中需要传递的对象包的目录级别命名一致,问过一些人都说没问题,下面给出具体实现:
现在user类的路径在两个项目中都是com.rhett.user。所以解析的都时候对象的映射都是一样的,完全可以正常在两个项目中使用。这时候两个项目的启动类都要调换位置,因为spring boot的启动类是要放到最外层的,要不然没发识别上一层的类注解。
如果需要使用这个类的项目是多个,还想要使用类直接传递,最好还是把类作为一个pojo来引入比较好。
由于本人刚接触mq,水平有限,暂时还不能从本质上来解决问题,如果哪位大神看到,还请留下建言。如果各位看到有不对的地方还请指正,感谢!!!

本文介绍在SpringBoot中如何实现RabbitMQ的多项目集成,通过实例展示了消息生产者和消费者之间的交互。在不同项目间传递字符串没有问题,但当尝试传递自定义对象时遇到问题,由于类路径不一致导致消费失败。解决方案包括让对象类包路径一致或转换为JSON字符串。作者分享了自己的实践和思考。

4873

被折叠的 条评论
为什么被折叠?



