1. 引入jar包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.发送端
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
/**
* 消息生产者
*/
public class MyDelayProducer {
/*
生产者输出消息到Queue1,并且这个消息是设置有有效时间的,比如60s。
消息会在Queue1中等待60s,如果没有消费者收掉的话,它就是被转发到Queue2,
Queue2有消费者,收到,处理延迟任务。
具体实现步骤如下:
第一步, 首先需要创建2个队列。Queue1和Queue2。
Queue1是一个消息缓冲队列,在这个队列里面实现消息的过期转发,
设置 Dead letter exchange ,当消息在这个队列中expire后,使用设置的路由发送。
Dead letter exchange 的exchange需要事先创建好,就是一个普通的exchange。
由于我们还需要向Queue1发送消息,那么还需要创建一个exchange,
并且和Queue1绑定。
*/
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory cf = new ConnectionFactory();
Connection conn = cf.newConnection();
Channel channel = conn.createChannel();
// 创建 exchange和queue
// 创建两个路由,
//一个向缓冲队列 queue_delay_begin 发送信息,信息过期时转到第二个路由,再发送给执行队列 queue_delay_done
channel.exchangeDeclare("exchange_delay_begin", "direct"/*路由类型*/, true/*是否持久化*/); //向Queue1发消息的路由
channel.exchangeDeclare("exchange_delay_done", "direct", true); //向Queue2发消息的路由
Map<String, Object> param = new HashMap<String, Object>();
//消息过期时转发到路由 exchange_delay_done
param.put("x-dead-letter-exchange", "exchange_delay_done");
// 创建缓冲队列 queue_delay_begin
channel.queueDeclare("queue_delay_begin", true/*是否持久化*/,
false/*是否排他*/, false/*是否自动删除*/, param);
//创建任务执行队列Queue2
channel.queueDeclare("queue_delay_done", true, false, false, null);
//将队列与路由进行绑定
channel.queueBind("queue_delay_begin", "exchange_delay_begin", "delay"/*路由关键字*/);
channel.queueBind("queue_delay_done", "exchange_delay_done", "delay");
// 延迟发送
AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
builder.expiration("3000");//设置消息TTL(消息生存时间)
builder.deliveryMode(2);//设置消息持久化
AMQP.BasicProperties properties = builder.build();
String message = "延迟信息:"+LocalDateTime.now();
channel.basicPublish("exchange_delay_begin","delay",properties,message.getBytes());
channel.close();
conn.close();
}
}
/*
队列按照顺序出去,如果第二个已经到期,但第一个不到期,第二个也不会出去,
当第一个到期出去是,第二个马上出去
*/
2.接收端
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.concurrent.TimeoutException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.ConsumerCancelledException;
import com.rabbitmq.client.DefaultConsumer;
import com.rabbitmq.client.Envelope;
import com.rabbitmq.client.ShutdownSignalException;
/**
* 消费者
*/
public class MyDelayConsumer {
public static void main(String[] args) throws IOException, TimeoutException, ShutdownSignalException, ConsumerCancelledException, InterruptedException {
ConnectionFactory cf = new ConnectionFactory();
Connection conn = cf.newConnection();
Channel channel = conn.createChannel();
//创建消费者,并接受消息
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String msg = new String(body, "UTF-8");
System.out.println("接收消息:"+ LocalDateTime.now());
System.out.println(msg);
System.out.println("路由:"+envelope.getExchange());
System.out.println("routingKey: "+ envelope.getRoutingKey());
long deliveryTag = envelope.getDeliveryTag();
System.out.println("deliveryTag: "+deliveryTag);
}
};
channel.basicConsume("queue_delay_done", true, consumer);
}
}