SpringBoot整合RabbitMQ官方地址:https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-amqp
org.springframework.boot
spring-boot-starter-amqp
spring:
application:
name: springboot-rabbitmq
rabbitmq:
host: 192.168.184.138
port: 5672
username: admin
password: 123456
virtual-host: /
publisher-confirm-type: correlated #必须配置这个才会确认回调
publisher-returns: true
listener:
type: simple
simple:
acknowledge-mode: manual #手动确认
prefetch: 1 #限制每次发送一条数据。
concurrency: 3 #同一个队列启动几个消费者
max-concurrency: 3 #启动消费者最大数量
#重试策略相关配置
retry:
enabled: true #是否支持重试
max-attempts: 5
stateless: false
#时间策略乘数因子
multiplier: 1.0
initial-interval: 1000ms
max-interval: 10000ms
default-requeue-rejected: true
完整配置查看:https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/html/common-application-properties.html
package com.rabbitmq.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.util.HashMap;
import java.util.Map;
/**
* @Package: com.rabbitmq.config
* @ClassName: :RabbitMQConfig
* @Description: rabbitmq
* @Author: Coding-Farmer
* @Date: 2019/11/15 14:19
*/
@Configuration
public class RabbitMQConfig {
private static Logger log = LoggerFactory.getLogger(RabbitMQConfig.class);
@Autowired
private CachingConnectionFactory connectionFactory;
//目标转换器,需要哪种类型的转换器就创建哪种类型的转换器
@Bean
public DirectExchange exchangeHello(){
Map eArguments = new HashMap<>();
//备份交换器参数
eArguments.put("alternate-exchange", "exchange.ae");
return new DirectExchange("exchange.hello",true,false,eArguments);
}
//备份转换器
@Bean
public FanoutExchange exchangeAE(){
return new FanoutExchange("exchange.ae",true,false,null);
}
//死信转换器
@Bean
public TopicExchange exchangeDLX(){
return new TopicExchange("exchange.dlx",true,false,null);
}
//目标对列
@Bean
public Queue queueHello() {
Map args = new HashMap<>();
//声明死信交换器
args.put("x-dead-letter-exchange", "exchange.dlx");
//声明死信路由键
args.put("x-dead-letter-routing-key", "dlx.test" );
//声明队列消息过期时间 5000ms
args.put("x-message-ttl", 5000);
return new Queue("queue.hello",true,false,false,args);
}
//备份对列
@Bean
public Queue queueAE() {
return new Queue("queue.ae",true,false,false,null);
}
//死信对列
@Bean
public Queue queueDLX() {
return new Queue("queue.dlx",true,false,false,null);
}
//绑定目标对列
@Bean
public Binding bindingExchangeDirect(@Qualifier("queueHello")Queue queueHello, @Qualifier("exchangeHello") DirectExchange exchangeHello){
return BindingBuilder.bind(queueHello).to(exchangeHello).with("helloKey");
}
//绑定备份对列
@Bean
public Binding bindingExchangeAE(@Qualifier("queueAE")Queue queueAE, @Qualifier("exchangeAE") FanoutExchange exchangeAE){
return BindingBuilder.bind(queueAE).to(exchangeAE);
}
//绑定死信对列
@Bean
public Binding bindingExchangeDLX(@Qualifier("queueDLX")Queue queueAE, @Qualifier("exchangeDLX") TopicExchange exchangeDLX){
return BindingBuilder.bind(queueAE).to(exchangeDLX).with("dlx.*");
}
/**
* 如果需要在生产者需要消息发送后的回调,
* 需要对rabbitTemplate设置ConfirmCallback对象,
* 由于不同的生产者需要对应不同的ConfirmCallback,
* 如果rabbitTemplate设置为单例bean,
* 则所有的rabbitTemplate实际的ConfirmCallback为最后一次申明的ConfirmCallback。
* @return
*/
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
return template;
}
}
package com.rabbitmq.producer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Date;
import java.util.UUID;
@Controller
public class HelloSender implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnCallback{
private static Logger log = LoggerFactory.getLogger(HelloSender.class);
private RabbitTemplate rabbitTemplate;
//构造方法注入
@Autowired
public HelloSender(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
//这是是设置回调能收到发送到响应
rabbitTemplate.setConfirmCallback(this);
//如果设置备份队列则不起作用
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(this);
}
@RequestMapping("/send")
@ResponseBody
public void send() {
CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
String sendMsg = "hello1 " + new Date();
System.out.println("Sender : " + sendMsg);
//convertAndSend(exchange:交换机名称,routingKey:路由关键字,object:发送的消息内容,correlationData:消息ID)
rabbitTemplate.convertAndSend("exchange.hello","helloKey", sendMsg,correlationId);
}
//回调确认
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if(ack){
log.info("消息发送成功:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
}else{
log.info("消息发送失败:correlationData({}),ack({}),cause({})",correlationData,ack,cause);
}
}
//消息发送到转换器的时候没有对列,配置了备份对列该回调则不生效
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.info("消息丢失:exchange({}),route({}),replyCode({}),replyText({}),message:{}",exchange,routingKey,replyCode,replyText,message);
}
}
package com.rabbitmq.consumer;
import com.rabbitmq.client.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class HelloConsumer {
private static Logger log = LoggerFactory.getLogger(HelloConsumer.class);
@RabbitHandler
@RabbitListener(queues = "queue.hello")
public void process(Message message, Channel channel) throws IOException {
log.info("receive: " + new String(message.getBody())+"《线程名:》"+Thread.currentThread().getName()+"《线程id:》"+Thread.currentThread().getId());
channel.basicAck(message.getMessageProperties().getDeliveryTag(), true);
}
}