SpringBoot配置步骤:
一、pom.xml导入RabbitMQ
<!-- Sringboot 引入 rabbitMQ -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
二、application.properties
配置Rabbit MQ相关参数
spring.application.name=springboot-rabbitmq
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
#发送方确认
spring.rabbitmq.publisher-confirms=true
#虚拟主机
spring.rabbitmq.virtual-host=/
三、RabbitMQ配置类
@Configuration
public class RabbitConfig {
@Value("${spring.rabbitmq.host}")
private String addresses;
@Value("${spring.rabbitmq.port}")
private String port;
@Value("${spring.rabbitmq.username}")
private String username;
@Value("${spring.rabbitmq.password}")
private String password;
@Value("${spring.rabbitmq.virtual-host}")
private String virtualHost;
@Value("${spring.rabbitmq.publisher-confirms}")
private boolean publisherConfirms;
@Autowired
private UserReceiver userReceiver;
//连接工厂
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses(addresses+":"+port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
/** 如果要进行消息回调,则这里必须要设置为true */
connectionFactory.setPublisherConfirms(publisherConfirms);
return connectionFactory;
}
//RabbitAdmin封装了对RabbitMQ的管理操作
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
return new RabbitAdmin(connectionFactory);
}
@Bean
public RabbitTemplate newRabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
//失败通知
template.setMandatory(true);
//失败回调
template.setReturnCallback(returnCallback());
//发送方确认
template.setConfirmCallback(confirmCallback());
return template;
}
//在RabbitMQ中,当声明一个队列时,会自动绑定一个direct的交换器,路由键为队列名称
@Bean
public Queue helloQueue() {
return new Queue(RmConst.QUEUE_HELLO);
}
@Bean
public Queue userQueue() {
return new Queue(RmConst.QUEUE_USER);
}
/*****不使用默认,自定义交换器的类型,以及路由键 start*****/
//声明两个队列
@Bean
public Queue queueEmailMessage() {
return new Queue(RmConst.QUEUE_TOPIC_EMAIL);
}
@Bean
public Queue queueUserMessages() {
return new Queue(RmConst.QUEUE_TOPIC_USER);
}
//声明Topic交换器
//TopicExchange就是Topic交换器,DirectExchange就是Direct交换器
@Bean
public TopicExchange exchange() {
return new TopicExchange(RmConst.EXCHANGE_TOPIC);
}
//将两个队列分别和Topic交换器进行绑定
@Bean
public Binding bindingEmailExchangeMessage() {
return BindingBuilder
.bind(queueEmailMessage())
.to(exchange())
.with("sb.*.email");
}
@Bean
public Binding bindingUserExchangeMessages() {
return BindingBuilder
.bind(queueUserMessages())
.to(exchange())
.with("sb.*.user");
}
/*****不使用默认,自定义交换器的类型,以及路由键 end*****/
/*****不使用默认,自定义Fanout交换器以及路由键 start*****/
@Bean
public Queue AMessage() {
return new Queue("sb.fanout.A");
}
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange(RmConst.EXCHANGE_FANOUT);
}
@Bean
Binding bindingExchangeA(Queue AMessage,FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
/*****不使用默认,自定义Fanout交换器以及路由键 end*****/
/*****监听userQueue队列,设置手动应答,指定消费者 start*****/
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container
= new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(userQueue());
//手动应答
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
//指定消费者
container.setMessageListener(userReceiver);
return container;
}
/*****监听userQueue队列,设置手动应答,指定消费者 end*****/
//===============发送方确认==========
@Bean
public RabbitTemplate.ConfirmCallback confirmCallback(){
return new RabbitTemplate.ConfirmCallback(){
@Override
public void confirm(CorrelationData correlationData,
boolean ack, String cause) {
if (ack) {
System.out.println("发送者确认发送给mq成功");
} else {
//处理失败的消息
System.out.println("发送者发送给mq失败,考虑重发:"+cause);
}
}
};
}
//失败通知
@Bean
public RabbitTemplate.ReturnCallback returnCallback(){
return new RabbitTemplate.ReturnCallback(){
@Override
public void returnedMessage(Message message,
int replyCode,
String replyText,
String exchange,
String routingKey) {
System.out.println("无法路由的消息,需要考虑另外处理。");
System.out.println("Returned replyText:"+replyText);
System.out.println("Returned exchange:"+exchange);
System.out.println("Returned routingKey:"+routingKey);
String msgJson = new String(message.getBody());
System.out.println("Returned Message:"+msgJson);
}
};
}
}
四、普通方式发送消息(失败通知)
在RabbitMQ配置类的RabbitTemplate中已添加
//失败通知
template.setMandatory(true);
生产者demo
@Component
public class DefaultSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg) {
String sendMsg = msg +"---"+ System.currentTimeMillis();;
this.rabbitTemplate.convertAndSend(RmConst.QUEUE_HELLO, sendMsg);
}
}
消费者demo
@Component
@RabbitListener(queues = "sb.hello")
public class HelloReceiver {
@RabbitHandler
public void process(String hello) {
System.out.println("HelloReceiver : " + hello);
}
}
通过@RabbitListener监听队列
通过@RabbitHandler对消息进行消费
五、发送方确认---手动应答
在RabbitMQ配置类已设置监听,并设置手动应答
生产者demo
@Component
public class DefaultSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg) {
String sendMsg = msg +"---"+ System.currentTimeMillis();;
this.rabbitTemplate.convertAndSend(RmConst.QUEUE_USER, sendMsg);
}
}
消费者demo
@Component
public class UserReceiver implements ChannelAwareMessageListener {
@Override
public void onMessage(Message message, Channel channel) throws Exception {
try {
String msg = new String(message.getBody());
System.out.println("UserReceiver>>>>>>>接收到消息:"+msg);
try {
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
System.out.println("UserReceiver>>>>>>消息已消费");
} catch (Exception e) {
System.out.println(e.getMessage());
channel.basicNack(message.getMessageProperties().
getDeliveryTag(),
false,true);
System.out.println("UserReceiver>>>>>>拒绝消息,要求Mq重新派发");
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
由于在RabbitMQ配置类中我们设置了监听UserQueued,这里无需使用@RabbitListener注解
通过实现ChannelAwareMessageListener监听器的方法onMessage
当处理失败,可以拒绝消息
六、Fanout交换器
生产者demo
@Component
public class FanoutSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg) {
String sendMsg = msg +"---"+ System.currentTimeMillis();
//Fanout交换器无需路由键
this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_FANOUT, "",sendMsg);
}
}
消费者demo
@Component
@RabbitListener(queues = "sb.fanout.A")
public class FanoutReceiver {
@RabbitHandler
public void process(String hello) {
System.out.println("FanoutReceiver : " + hello);
}
}