maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>1.5.2.RELEASE</version>
</dependency>
application.yml
spring:
rabbitmq:
listener:
simple:
acknowledge-mode: manual
retry:
enabled: true
RabbitMq配置类
import com.yaoch.common.utils.DateUtil;
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.listener.api.ChannelAwareMessageListener;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitMqConfig {
private final static String HOST = "47.104.129.104";
private final static Integer PORT = 5672;
private final static String USER_NAME = "hong";
private final static String PASSWORD = "hong";
public final static String DIRECT_EXCHANGE = "directExchange";
public final static String FANOUT_EXCHANGE = "fanoutExchange";
public final static String FIRST_QUEUE = "queue1";
public final static String SECOND_QUEUE = "queue2";
public final static String DEAD_QUEUE = "deadQueue";
public final static String FIRST_ROUTE = "first-route";
public final static String DEAD_ROUTE = "dead-route";
@Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
cachingConnectionFactory.setHost(HOST);
cachingConnectionFactory.setPort(PORT);
cachingConnectionFactory.setUsername(USER_NAME);
cachingConnectionFactory.setPassword(PASSWORD);
cachingConnectionFactory.setVirtualHost("hong");
cachingConnectionFactory.setConnectionTimeout(10000);
cachingConnectionFactory.setCloseTimeout(10000);
cachingConnectionFactory.setPublisherConfirms(true);
cachingConnectionFactory.setPublisherReturns(true);
return cachingConnectionFactory;
}
@Bean
public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory){
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory);
rabbitAdmin.setAutoStartup(true);
return new RabbitAdmin(connectionFactory);
}
@Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
return rabbitTemplate;
}
@Bean
public DirectExchange directExchange() {
return new DirectExchange(DIRECT_EXCHANGE,true,false);
}
@Bean
public FanoutExchange fanoutExchange() {
return new FanoutExchange(FANOUT_EXCHANGE);
}
@Bean
public Queue queue() {
return new Queue(FIRST_QUEUE,true,false,false);
}
@Bean
public Queue queue2() {
return new Queue(SECOND_QUEUE);
}
@Bean
public Queue deadQueue(){
Map<String, Object> args = new HashMap<>(8);
args.put("x-dead-letter-exchange", DIRECT_EXCHANGE);
args.put("x-dead-letter-routing-key", FIRST_ROUTE);
args.put("x-message-ttl", 10000);
args.put("x-max-length", 5);
return new Queue(DEAD_QUEUE,true,false,false,args);
}
@Bean
public Binding binding() {
return BindingBuilder.bind(queue()).to(directExchange()).with(FIRST_ROUTE);
}
@Bean
public Binding binding2() {
return BindingBuilder.bind(queue2()).to(directExchange()).with(FIRST_ROUTE);
}
@Bean
public Binding bindingDead(){
return BindingBuilder.bind(deadQueue()).to(directExchange()).with(DEAD_ROUTE);
}
@Bean
public SimpleMessageListenerContainer simpleMessageListenerContainer(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer simpleMessageListenerContainer = new SimpleMessageListenerContainer();
simpleMessageListenerContainer.setConnectionFactory(connectionFactory);
simpleMessageListenerContainer.setMessageConverter(new Jackson2JsonMessageConverter());
simpleMessageListenerContainer.setConcurrentConsumers(1);
simpleMessageListenerContainer.setMaxConcurrentConsumers(5);
simpleMessageListenerContainer.setQueueNames(RabbitMqConfig.FIRST_QUEUE);
simpleMessageListenerContainer.setAcknowledgeMode(AcknowledgeMode.MANUAL);
simpleMessageListenerContainer.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {
System.out.println(DateUtil.dateFormat(new Date(),"yyyy-MM-dd HH:mm:ss")+">>>>使用SimpleMessageListenerContainer进行Ack信息【"+message.getMessageProperties().getDeliveryTag()
+"】" + new String(message.getBody()));
channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
});
return simpleMessageListenerContainer;
}
}
生产者
package com.yaoch.rabbitmq;
import com.yaoch.common.utils.DateUtil;
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.Component;
import java.util.Date;
import java.util.UUID;
@Component
public class MsgProducer implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
public RabbitTemplate rabbitTemplate;
@Autowired
public MsgProducer(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback(this);
}
public void sendMsg(String msg) {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend(RabbitMqConfig.DIRECT_EXCHANGE, RabbitMqConfig.DEAD_ROUTE
, "【deadQueue】" + msg, message -> {
message.getMessageProperties().setDelay(5 * 1000);
return message;
}, correlationData);
}
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println(DateUtil.dateFormat(new Date(),"yyyy-MM-dd HH:mm:ss")+">>>>生产者消息确认回调:" + correlationData.getId());
if (!ack) {
System.out.println("生产者消息发送失败:" + cause);
}
}
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("消息主体 message : " + message);
System.out.println("消息回复: " + replyCode);
System.out.println("描述:" + replyText);
System.out.println("消息使用的交换器 exchange : " + exchange);
System.out.println("消息使用的路由键 routing : " + routingKey);
}
}
消费者1
package com.yaoch.rabbitmq;
import com.rabbitmq.client.Channel;
import com.yaoch.common.utils.DateUtil;
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;
import java.util.Date;
@Component
public class MsgConsumer {
@RabbitListener(queues = RabbitMqConfig.FIRST_QUEUE)
@RabbitHandler
public void process(Message message, Channel channel) throws IOException {
System.out.println(DateUtil.dateFormat(new Date(),"yyyy-MM-dd HH:mm:ss")+">>>>消费者1进行NAck【"+message.getMessageProperties().getDeliveryTag()+"】:"+new String(message.getBody()));
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
}
@RabbitListener(queues = RabbitMqConfig.DEAD_QUEUE)
@RabbitHandler
public void dealDeadMsg(Message message,Channel channel) throws Exception{
System.out.println(DateUtil.dateFormat(new Date(),"yyyy-MM-dd HH:mm:ss")+">>>>死信队列接收信息:【"+message.getMessageProperties().getDeliveryTag()+"】:"+new String(message.getBody()));
channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
}
}
消费者2
package com.yaoch.rabbitmq;
import com.rabbitmq.client.Channel;
import com.yaoch.common.utils.DateUtil;
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.util.Date;
/**
* 消费者2
* 手动ACK
* @author 肥美的洪洪哥
*/
@Component
public class MsgConsumer2 {
@RabbitListener(queues = RabbitMqConfig.FIRST_QUEUE)
@RabbitHandler
public void process(Message message, Channel channel) throws Exception {
System.out.println(DateUtil.dateFormat(new Date(),"yyyy-MM-dd HH:mm:ss")+">>>>消费者2进行Ack【" + message.getMessageProperties().getDeliveryTag() + "】:" + new String(message.getBody()));
//参数1:消息的id 参数2:是否批量将一次性ACK所有小于deliveryTag的消息。
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
//channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
}
}