1.基础使用
1.1在pom.xml文件中引入依赖
<!--AMQP依赖,包含RabbitMQ-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
1.2.在 配置文件中编写mq相关信息
spring:
rabbitmq:
host: 39.98.46.7 #ip
port: 5673 #端口号
virtual-host: /test #虚拟机名称
username: guest #用户名
password: guest #密码
1.3.使用客户端发送消息
向队列hello.queue1发送消息"hello,amqp!"(需要先将通道与队列绑定)
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void testSendMessage2Queue() {
String queueName = "hello.queue1";
String msg = "hello, amqp!";
rabbitTemplate.convertAndSend(queueName, msg);
}
1.4.使用客户端接收信息
注解@RabbitListener能过同事监听多个队列,传入时使用数组即可。
@Component
public class MqListener {
@RabbitListener(queues = "hello.queue1")
public void listenHelloQueue1(String msg){
System.out.println("监听到消息+【"+msg+"】");
}
}
2.work模型
- 多个消费者绑定到一个队列,可以加快消息处理速度
- 同一条消息只会被一个消费者处理
- 通过设置prefetch来控制消费者预取的消息数量,处理完一条再处理下一条,实现能者多劳
添加两个方法同时监听同一个队列,设置队列一每秒处理50条,队列二每秒处理5条
@RabbitListener(queues = "work.queue")
public void listenWorkQueue1(String msg) throws InterruptedException {
System.out.println("消费者1 收到了 work.queue的消息:【" + msg +"】");
Thread.sleep(20);
}
//
@RabbitListener(queues = "work.queue")
public void listenWorkQueue2(String msg) throws InterruptedException {
System.err.println("消费者2 收到了 work.queue的消息...... :【" + msg +"】");
Thread.sleep(200);
}
结果发现两队列处理速度不一样,但是依旧以轮询的方式处理消息
解决方法
在pom.xml文件中添加配置,使得只有处理完一个消息才能获取下一条消息
spring:
rabbitmq:
listener:
simple:
prefetch: 1 #每次只能获取一条消息,处理完才能获取下一条消息
3.交换机
3.1Fanout交换机
Fanout Exchange会将接收到的消息广播到每一个跟其绑定的queue,所以也叫广播模式。
3.2Direct交换机
DirectExchange会将接收到的消息根据规则路由到指定的Queue,因此称为定向路由
- 每一个Queue都与Exchange设置一个BindingKey
- 发布者发送消息时,指定消息的Routingkey
- Exchange将消息路由到BindingKey与消息RoutingKey一致的队列
3.3Topic交换机
TopicExchange与DirectExchange类似,区别在于routingKey可以是多个单词的列表,并且以.分割。
Queue与Exchange指定BindingKey时可以使用通配符:
- #:指定0个或多个单词
- *:指定一个单词
4.声明队列与交换机
SpringAMQP提供了几个类,用来声明队列、交换机及其绑定关系:
- Queue:用于声明队列,可以用工厂类QueueBuilder构建
- Exchange:用于声明交换机,可以用工厂类ExchangeBuilder构建
- Binding:用于声明队列和交换机的绑定关系,可以使用工厂类BindingBuilder构建
方式一:基于bean
//声明交换机
@Bean
public FanoutExchange fanoutExchange(){
return new FanoutExchange("hmall.fanout");
}
//声明队列1
@Bean
public Queue fanoutQueue1(){
return new Queue("fanout.queue1");
}
//声明队列2
@Bean
public Queue fanoutQueue2(){
return new Queue("fanout.queue2");
}
//将队列1与交换机绑定
@Bean
public Binding BindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange){
return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
}
//将队列2与交换机绑定
@Bean
public Binding BindingQueue2(){
return BindingBuilder.bind(fanoutQueue2()).to(fanoutExchange());
}
方式二:基于注解
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(name = "hmall.fanout"),
value = @Queue(name = "fanout.queue1")))
public void listenFanoutQueue1(String msg){
System.out.println("fanout1收到消息:"+msg);
}
@RabbitListener(bindings = @QueueBinding(exchange = @Exchange(name = "hmall.fanout"),
value = @Queue(name = "fanout.queue2")))
public void listenFanoutQueue2(String msg){
System.out.println("fanout2收到消息:"+msg);
}