之前我们记录了原生java代码使用rabbitmq的方法,很简单,类似于原生jdbc代码一样,将连接对象抽离出来作为工具类,生产者和消费者通过工具类获取连接对象,进而获取通道对象,再注册交换机或者是队列等,发送消息与接收消息。
在企业开发中,我们更多的是使用spring框架来整合其它技术,springboot更是方便的提供了各种starter来快速添加依赖,完成整合,开箱即用。
1.添加依赖
org.springframework.boot spring-boot-starter-amqp
2.编写配置
配置信息包括ip,端口,虚拟主机,用户名和密码,和原生java代码所需的配置信息一致。
spring: application: name: spirngboot-rabbitmq rabbitmq: host: 192.168.20.128 port: 5672 virtual-host: /vh username: wuwl password: 123456
3.编写并测试
本文主要针对前五种常用模型,在spirngboot框架的基础上整合rabbitmq并进行测试使用。
(1) Hello World模型
这是一种简单的直连模型,生产者将消息直接发送至消息队列,消费者绑定消息队列后直接获取,一对一。spring-boot-starter-amqp
为我们提供了一个org.springframework.amqp.rabbit.core.RabbitTemplate
类来方便我们使用rabbitmq
,自动注入即可。
生产者测试类:
@SpringBootTest(classes = RabbitmqDemoApplication.class) @RunWith(SpringRunner.class) public class RabbitmqDemoApplicationTests { @Autowired private RabbitTemplate rabbitTemplate; @Test public void testHelloQueues(){ rabbitTemplate.convertAndSend("hello","hello world"); } }
生产者向名为hello的队列发送消息,但是,在没有消费者的情况下,生产者没有任何意义。另外,convertAndSend
方法的第一个参数并不是消息队列的意思,而是routingKey
,我们根据源码找到最初定义的接口可以看到以下内容:
/** * Convert a Java object to an Amqp {@link Message} and send it to a default exchange * with a specific routing key. * * @param routingKey the routing key * @param message a message to send * @throws AmqpException if there is a problem */ void convertAndSend(String routingKey, Object message) throws AmqpException;
第二个参数为Object
类型,也就是说可以传递任意类型的对象,该方法将对象转换成一个Amqp
消息并发送到一个默认的交换机,并且routingKey
为第一个参数的内容,没有提到消息队列的信息,但我们可以分析到,这里的routingKey
与queues
应该是同名的。
消费者类:
@Component @RabbitListener(queuesToDeclare = @Queue("hello")) public class HelloQueuesConsumer { @RabbitHandler public void consume(String msg){ System.out.println("消费消息:" + msg + " " + System.currentTimeMillis()); } }
上面的代码等同于:
@Component public class HelloQueuesConsumer { @RabbitListener(queuesToDeclare = @Queue("hello")) public void consume(String msg){ System.out.println("消费消息:" + msg + " " + System.currentTimeMillis()); } }
@RabbitListener 可以标注在类上面,需配合 @RabbitHandler 注解一起使用
@RabbitListener 标注在类上面表示当有收到消息的时候,就交给 @RabbitHandler 的方法处理,具体使用哪个方法处理,根据 MessageConverter 转换后的参数类型
直接启动测试方法,也就是生产者,可以看到:
消费者有接收到消息队列中的信息并打印。
(2) work queues模型
生产者测试方法,类与第一个模型一致
@Test public void testWorkQueues(){ for (int i = 0; i < 20; i++) { rabbitTemplate.convertAndSend("work","work index " + i); } }
消费者类:
@Component public class WorkQueuesConsumer { @RabbitListener(queuesToDeclare = @Queue("work")) public void consume1(String msg){ System.out.println("consumer1消费消息:" + msg); } @RabbitListener(queuesToDeclare = @Queue("work")) public void consume2(String msg){ System.out.println("consumer2消费消息:" + msg); } }
启动生产者测试方法:
消费者一与消费者二均匀分配了队列中的消息任务,即使两者执行效率不一致,也同样是均匀分配。
(3) Publish/Subscribe模型
生产者测试方法:
for (int i = 0; i < 20; i++) { rabbitTemplate.convertAndSend("amq.fanout","","fanout msg " + i); }
消费者类:
@Component public class FanoutQueuesConsumer { @RabbitListener(bindings = { @QueueBinding(value = @Queue, exchange = @Exchange( value = "amq.fanout", type = "fanout"))}) public void consume1(String msg) { System.out.println("consumer1消费消息:" + msg); } @RabbitListener(bindings = { @QueueBinding(value = @Queue, exchange = @Exchange( value = "amq.fanout", type = "fanout"))}) public void consume2(String msg) { System.out.println("consumer2消费消息:" + msg); } }
注意此处的交换机信息
启动生产者测试方法:
此处只粘贴了部分打印信息,两个消费者获得了相同的消息,生产者将消息发送至交换机,由交换机发送至已注册到交换机的所有临时消息队列,进而消费者获取队列中的消息。
(4) Routing模型
生产者测试方法:
@Test public void testDirectQueues(){ rabbitTemplate.convertAndSend("amq.direct","info","routingKey is info"); rabbitTemplate.convertAndSend("amq.direct","warn","routingKey is warn"); rabbitTemplate.convertAndSend("amq.direct","error","routingKey is error"); }
routing也成为fanout模型,对应的交换机类型为direct
消费者类:
@Component public class DirectQueuesConsumer { @RabbitListener(bindings = { @QueueBinding(value = @Queue, exchange = @Exchange( value = "amq.direct", type = "direct"), key = {"info", "warn", "error"})}) public void consume1(String msg) { System.out.println("consumer1消费消息:" + msg); } @RabbitListener(bindings = { @QueueBinding(value = @Queue, exchange = @Exchange( value = "amq.direct", type = "direct"), key = "error")}) public void consume2(String msg) { System.out.println("consumer2消费消息:" + msg); } }
启动生产者测试类:
消费者一配置了三种类型的routingKey,所以三种类型的消息都能够接收到,消费者二只能接受到error类型的消息。
(5) Topic模型
生产者测试方法:
@Test public void testTopicQueues(){ rabbitTemplate.convertAndSend("amq.topic","file.info","routingKey is info"); rabbitTemplate.convertAndSend("amq.topic","file.warn","routingKey is warn"); rabbitTemplate.convertAndSend("amq.topic","file.error","routingKey is error"); }
消费者类:
@Component public class TopicQueuesConsumer { @RabbitListener(bindings = { @QueueBinding(value = @Queue, exchange = @Exchange( value = "amq.topic", type = "topic"), key = {"#"})}) public void consume1(String msg) { System.out.println("consumer1消费消息:" + msg); } @RabbitListener(bindings = { @QueueBinding(value = @Queue, exchange = @Exchange( value = "amq.topic", type = "topic"), key = "*.error")}) public void consume2(String msg) { System.out.println("consumer2消费消息:" + msg); } }
启动生产者测试方法:
消费者一配置的routingKey
为#
,可以接受任意类型的消息,*
好代表一个单词,消费者二可以接受任意单词加上.error
为routingKey
的消息。
到此这篇关于springBoot整合rabbitmq并测试五种常用模型的文章就介绍到这了,更多相关springBoot整合rabbitmq内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!