前言
該示例使用的SpringBoot版本是2.2.2
添加依賴
引入amqp的依賴就行,AMQP即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,爲面向消息的中間件設計。RabbitMQ就是對該協議的一種實現。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
編寫配置
package com.example.demo.config;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Binding.DestinationType;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.Queue;
@Configuration
public class RabbitMQConfig implements InitializingBean {
/**
* RabbitMQ的地址
*/
@Value("${rabbit.addresses}")
private String addresses;
/**
* RabbitMQ的登錄名
*/
@Value("${rabbit.username}")
private String username;
/**
* RabbitMQ的登錄密碼
*/
@Value("${rabbit.password}")
private String password;
/**
* 虛擬消息服務器
*/
@Value("${rabbit.virtualhost}")
private String virtualHost;
@Value("${rabbit.queue1.name}")
private String queue1Name;
@Value("${rabbit.queue2.name}")
private String queue2Name;
@Value("${rabbit.exchange2.name}")
private String exchange2Name;
@Value("${rabbit.bindingKey2}")
private String bindingKey2;
/**
* 通過這種方式可以申明一個隊列,
* 該隊列使用跟隊列名相同的bindingKey綁定了RabbitMQ默認的交換器
* @return 隊列
*/
@Bean
public Queue queue1() {
return new Queue(queue1Name);
}
/**
* 創建連接工廠
* @return 連接工廠
*/
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
/*
addresses的格式爲192.168.7.82:5672,192.168.7.81:5672,多個地址之間用","隔開
也可以用host和port來指定RabbitMQ地址
cachingConnectionFactory.setHost("192.168.7.82");
cachingConnectionFactory.setPort(5672);
*/
cachingConnectionFactory.setAddresses(addresses);
cachingConnectionFactory.setUsername(username);
cachingConnectionFactory.setPassword(password);
cachingConnectionFactory.setVirtualHost(virtualHost);
return cachingConnectionFactory;
}
/**
* 配置消費者容器工廠
* @return 消費者容器工廠
*/
@Bean
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory();
listenerContainerFactory.setConnectionFactory(connectionFactory());
//手動ack
listenerContainerFactory.setAcknowledgeMode(AcknowledgeMode.MANUAL);
return listenerContainerFactory;
}
/**
* RabbitMQ的template,通過該類可以收發消息
* @return RabbitTemplate
*/
@Bean
public RabbitTemplate rabbitTemplate() {
return new RabbitTemplate(connectionFactory());
}
/**
* 消息中間件的管理控制檯。可以聲明隊列、交換器,以及綁定隊列和交換器
* @return AmqpAdmin
*/
@Bean
public AmqpAdmin amqpAdmin() {
return new RabbitAdmin(connectionFactory());
}
@Override
public void afterPropertiesSet() throws Exception {
AmqpAdmin amqpAdmin = amqpAdmin();
//聲明一個隊列
amqpAdmin.declareQueue(new Queue(queue2Name));
//聲明一個交換器
amqpAdmin.declareExchange(new DirectExchange(exchange2Name));
//綁定交換器和隊列
Binding binding = new Binding(queue2Name, DestinationType.QUEUE, exchange2Name, bindingKey2, null);
amqpAdmin.declareBinding(binding);
}
}
application.yml
server:
port: 8080
rabbit:
addresses: 192.168.7.82:5672
username: admin
password: 123456
virtualhost: /
queue1:
name: testQueue1
exchange2:
name: testExchange2
queue2:
name: testQueue2
bindingKey2: testBinding2
queue3:
name: testQueue3
exchange3:
name: testExchange3
bindingKey3: testBinding3
編寫生產者
package com.example.demo.mq;
import java.io.UnsupportedEncodingException;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* RabbitMQ生產者
* @author LiHao
*/
@Component
public class RabbitMQProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 發送字符串消息到默認的交換器
* @param routingKey 路由鍵(這裏爲了測試方便將路由鍵當做參數)
* @param msg 消息
*/
public void send(String routingKey, String msg) {
this.rabbitTemplate.convertAndSend(routingKey, msg);
}
/**
* 發送字符串消息到指定的交換器
* @param exchange 交換器名稱
* @param routingKey 路由鍵
* @param msg 消息
*/
public void send1(String exchange, String routingKey, String msg) {
this.rabbitTemplate.convertAndSend(exchange, routingKey, msg);
}
/**
* 發送字節數組消息到指定交換器
* @param exchange 交換器名稱
* @param routingKey 路由鍵
* @param msg 消息
* @throws UnsupportedEncodingException
*/
public void sendByte(String exchange, String routingKey, String msg) throws UnsupportedEncodingException {
this.rabbitTemplate.convertAndSend(exchange, routingKey, msg.getBytes("utf-8"));
}
}
編寫消費者
package com.example.demo.mq;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
/**
* RabbitMQ消費者
* @author LiHao
*
*/
@Component
public class RabbitMQConsumer {
/**
* 自動ack可以這樣接收消息
* @param msg
*/
@RabbitListener(queues = "${rabbit.queue1.name}")
@RabbitHandler
public void receive1(String msg) {
System.out.println("消費者從隊列1接收到的消息:" + msg);
}
@RabbitListener(queues = "${rabbit.queue2.name}")
@RabbitHandler
public void receive2(String msg, Channel channel, Message message) {
System.out.println("消費者從隊列2接收到的消息:" + msg);
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
//確認收到消息,RabbitMQ將刪除該消息
channel.basicAck(deliveryTag, false);
} catch (IOException ex) {
ex.printStackTrace();
}
}
/**
* 使用@QueueBinding組合註解可以聲明隊列、交換器,並綁定隊列和交換器
* @param msg
* @param channel
* @param message
*/
@RabbitListener(bindings = {
@QueueBinding(value = @Queue(value = "${rabbit.queue3.name}"),
exchange = @Exchange(value = "${rabbit.exchange3.name}"),
key = "${rabbit.bindingKey3}")
})
@RabbitHandler
public void receive3(byte[] msg, Channel channel, Message message) {
try {
String str = new String(msg, "utf-8");
System.out.println("消費者從隊列3接收到的消息:" + str);
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
long deliveryTag = message.getMessageProperties().getDeliveryTag();
try {
channel.basicAck(deliveryTag, false);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
編寫測試類
package com.example.demo.controller;
import java.io.UnsupportedEncodingException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.mq.RabbitMQProducer;
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private RabbitMQProducer rabbitMQProducer;
@GetMapping("/mq/str")
public String test(String exchange, String routingKey, String msg) {
if (exchange != null) {
rabbitMQProducer.send1(exchange, routingKey, msg);
} else {
rabbitMQProducer.send(routingKey, msg);
}
return "ok";
}
@GetMapping("/mq/byte")
public String test1(String exchange, String msg, String routingKey) {
try {
rabbitMQProducer.sendByte(exchange, routingKey, msg);
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
return "ok";
}
}