1.maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.SpringBoot配置
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=/
3.RabbitMQ配置
3.1 ConnectionFactory:发布确认
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses(addresses + ":" + port);
connectionFactory.setUsername(username);
connectionFactory.setPassword(password);
connectionFactory.setVirtualHost(virtualHost);
connectionFactory.setPublisherConfirms(publisherConfirms);
return connectionFactory;
}
3.2 RabbitTemplate:失败通知,发布确认回调
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setMandatory(true);
template.setConfirmCallback(confirmCallback());
template.setReturnCallback(returnCallback());
return template;
}
3.3 声明交换器与队列
@Bean
public Queue queueEmailMessage() {
return new Queue(RmConst.QUEUE_TOPIC_EMAIL);
}
@Bean
public Queue queueUserMessages() {
return new Queue(RmConst.QUEUE_TOPIC_USER);
}
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(RmConst.EXCHANGE_TOPIC);
}
3.4 队列与交换器绑定
@Bean
public Binding bindingEmailExchangeMessage() {
return BindingBuilder.bind(queueEmailMessage()).to(topicExchange()).with("sb.*.email");
}
@Bean
public Binding bindingUserExchangeMessages() {
return BindingBuilder.bind(queueUserMessages()).to(topicExchange()).with("sb.*.user");
}
3.5 SimpleMessageListenerContainer:队列绑定消费者,手动确认
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(userQueue());
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(userReceiver);
return container;
}
3.6 生产者失败通知与发布确认回调
@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);
}
};
}
3.7 完整配置
package com.zava.config;
import com.zava.constant.RmConst;
import com.zava.hello.UserReceiver;
import org.springframework.amqp.core.*;
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.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@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);
connectionFactory.setPublisherConfirms(publisherConfirms);
return connectionFactory;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
return new RabbitAdmin(connectionFactory);
}
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setMandatory(true);
template.setConfirmCallback(confirmCallback());
template.setReturnCallback(returnCallback());
return template;
}
@Bean
public Queue userQueue() {
return new Queue(RmConst.QUEUE_USER);
}
@Bean
public Queue helloQueue() {
return new Queue(RmConst.QUEUE_HELLO);
}
@Bean
public Queue queueEmailMessage() {
return new Queue(RmConst.QUEUE_TOPIC_EMAIL);
}
@Bean
public Queue queueUserMessages() {
return new Queue(RmConst.QUEUE_TOPIC_USER);
}
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(RmConst.EXCHANGE_TOPIC);
}
@Bean
public Binding bindingEmailExchangeMessage() {
return BindingBuilder.bind(queueEmailMessage()).to(topicExchange()).with("sb.*.email");
}
@Bean
public Binding bindingUserExchangeMessages() {
return BindingBuilder.bind(queueUserMessages()).to(topicExchange()).with("sb.*.user");
}
@Bean
public Queue AMessage() {
return new Queue("sb.fanout.A");
}
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange(RmConst.EXCHANGE_FANOUT);
}
@Bean
public Binding bindingExchangeA(Queue AMessage, FanoutExchange fanoutExchange) {
return BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(userQueue());
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(userReceiver);
return container;
}
@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);
}
};
}
}
4.发送消息
package com.zava.fanout;
import com.zava.constant.RmConst;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class FanoutSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg) {
String sendMsg = msg +"---"+ System.currentTimeMillis();;
System.out.println("FanoutSender : " + sendMsg);
this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_FANOUT, "",sendMsg);
}
}
package com.zava.topic;
import com.zava.constant.RmConst;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class TopicSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send() {
String msg1 = "I am email mesaage msg======";
System.out.println("TopicSender send the 1st : " + msg1);
this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_TOPIC, RmConst.RK_EMAIL, msg1);
String msg2 = "I am user mesaages msg########";
System.out.println("TopicSender send the 2nd : " + msg2);
this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_TOPIC, RmConst.RK_USER, msg2);
String msg3 = "I am error mesaages msg";
System.out.println("TopicSender send the 3rd : " + msg3);
this.rabbitTemplate.convertAndSend(RmConst.EXCHANGE_TOPIC, "errorkey", msg3);
}
}
package com.zava.hello;
import com.zava.constant.RmConst;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class DefaultSender {
@Autowired
private RabbitTemplate rabbitTemplate;
public void send(String msg) {
String sendMsg = msg +"---"+ System.currentTimeMillis();;
System.out.println("Sender : " + sendMsg);
this.rabbitTemplate.convertAndSend(RmConst.QUEUE_HELLO, sendMsg);
this.rabbitTemplate.convertAndSend(RmConst.QUEUE_USER, sendMsg);
}
}
package com.zava.controller;
import com.zava.fanout.FanoutSender;
import com.zava.hello.DefaultSender;
import com.zava.topic.TopicSender;
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;
@RestController
@RequestMapping("/rabbit")
public class RabbitTest {
@Autowired
private DefaultSender defaultSender;
@Autowired
private TopicSender topicSender;
@Autowired
private FanoutSender fanoutSender;
@GetMapping("/hello")
public void hello() {
defaultSender.send("hellomsg!");
}
@GetMapping("/topicTest")
public void topicTest() {
topicSender.send();
}
@GetMapping("/fanoutTest")
public void fanoutTest() {
fanoutSender.send("hellomsg:OK");
}
}
package com.zava.constant;
public class RmConst {
public final static String QUEUE_HELLO = "sb.hello";
public final static String QUEUE_USER = "sb.user";
public final static String QUEUE_TOPIC_EMAIL = "sb.info.email";
public final static String QUEUE_TOPIC_USER = "sb.info.user";
public final static String RK_EMAIL = "sb.info.email";
public final static String RK_USER = "sb.info.user";
public final static String EXCHANGE_TOPIC = "sb.exchange";
public final static String EXCHANGE_FANOUT = "sb.fanout.exchange";
}
5.消费消息
5.1 第一种方式:RabbitListener + RabbitHandler
package com.zava.fanout;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
@RabbitListener(queues = "sb.fanout.A")
public class FanoutReceiver {
@RabbitHandler
public void process(String hello) {
System.out.println("FanoutReceiver : " + hello);
}
}
5.2 第二种方式:RabbitMQ配置进行绑定 + ChannelAwareMessageListener
@Bean
public SimpleMessageListenerContainer messageContainer() {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory());
container.setQueues(userQueue());
container.setAcknowledgeMode(AcknowledgeMode.MANUAL);
container.setMessageListener(userReceiver);
return container;
}
- 实现ChannelAwareMessageListener监听消息
package com.zava.hello;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;
@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);
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重新派发");
e.printStackTrace();
}
}
}