-**官方原文:**
-
-In this setup, we can see the direct exchange X with two queues bound to it. The first queue is bound with binding key orange, and the second has two bindings, one with binding key black and the other one with green.
-
-In such a setup a message published to the exchange with a routing key orange will be routed to queue Q1. Messages with a routing key of black or green will go to Q2. All other messages will be discarded.
-
-
-
-**3. topic**:将消息路由到BindingKey和RountingKey 相匹配的队列中,匹配规则约定:
-
-- RountingKey 和 BindingKey 均为一个点“.”分隔得字符串,被点号分隔得每一段独立的字符串称为一个单词。
-- BindingKey 中可以存在两种特殊的字符串“#”和“*”,其中“\*”用于匹配一个单词,“\#”用于匹配零个或者多个单词。
- - \* (star) can substitute for exactly one word.
- - \# (hash) can substitute for zero or more words.
-
-
-官网原文对这一模式的说明比较清晰,摘抄如下:
-
-We created three bindings: Q1 is bound with binding key "*.orange.*" and Q2 with "*.*.rabbit" and "lazy.#".
-
-These bindings can be summarised as:
-
-- Q1 is interested in all the orange animals.
-- Q2 wants to hear everything about rabbits, and everything about lazy animals.
-
-A message with a routing key set to "quick.orange.rabbit" will be delivered to both queues. Message "lazy.orange.elephant" also will go to both of them. On the other hand "quick.orange.fox" will only go to the first queue, and "lazy.brown.fox" only to the second. "lazy.pink.rabbit" will be delivered to the second queue only once, even though it matches two bindings. "quick.brown.fox" doesn't match any binding so it will be discarded.
-
-What happens if we break our contract and send a message with one or four words, like "orange" or "quick.orange.male.rabbit"? Well, these messages won't match any bindings and will be lost.
-
-On the other hand "lazy.orange.male.rabbit", even though it has four words, will match the last binding and will be delivered to the second queue.
-
-**4. headers**
-
-headers类型的交换器不依赖路由键的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。(不常用)
-
-#### 2.1.5 RabbitMQ运转流程
-
-**生产者发送消息过程**:
-
-1. 生产者连接到RabbitMQ Broker, 建立一个连接(Connection), 开启一个信道(Channel);
-2. 生产者声明一个交换器,并设置相关属性;
-3. 生产者声明一个队列并设置相关属性;
-4. 生产者通过路由键将交换器与队列绑定起来;
-5. 生产者发送消息至RabbitMQ Broker ,其中包含路由键、交换器等信息;
-6. 相应的交换器根据接收到的路由键查找相应的匹配队列;
-7. 如果找到,则将从生产者发送过来的消息存入相应的队列中;
-8. 如果没有找到,则根据生产者配置的属性选择丢弃还是回退给生产者;
-9. 关闭信道;
-10. 关闭连接。
-
-**消费者接收消息的过程**:
-
-1. 消费者连接到RabbitMQ Broker, 建立一个连接(Connection), 开启一个信道(Channel);
-2. 消费者向RabbitMQ Broker请求消费相应队列中的消息,可能会设置相应的回调函数;
-3. 等待RabbitMQ Broker回应并投递相应对列中的消息,消费者接收消息;
-4. 消费者确认(ack)接收到的消息;
-5. RabbitMQ从队列中删除相应已经被确认的消息;
-6. 关闭信道;
-7. 关闭连接。
-
-## 第三章 客户端开发向导
-
-### 3.1 连接RabbitMQ
-
-```java
-// 1. 给定参数连接
-ConnectionFactory factory = new ConnectionFactory();
-factory.setHost(IP_ADDRESS);
-factory.setPort(PORT);
-factory.setVirtualHost("/");
-factory.setUsername(USER_NAME);
-factory.setPassword(PASSWORD);
-Connection connection = factory.newConnection();
-
-// 2.url 连接
-ConnectionFactory factory new ConnectionFactory();
-factory.setUri( "amqp://userName:password@ipAddress:portNumber/virtualHost");
-Connection conn = factory.newConnection();
-```
-
-**注**:Connection 可以 用来创建多个 Channel 实例,但是 Channel 实例不能在线程问共享,应用程序应该为每一个线程开辟一个 Channel 。
-
-### 3.2 使用交换器和队列
-
-```java
-// 创建一个 type="direct"、持久化的、非自动删除的交换器
-channel.exchangeDeclare(EXCHANGE_NAME,"direct",true,false,null);
-// 创建一个持久化、非排他的、非自动删除的队列
-channel.queueDeclare(QUEUE_NAME,true,false,false,null);
-// 将交换器与队列通过路由键绑定
-channel.queueBind(QUEUE_NAME,EXCHANGE_NAME,ROUTING_KEY);
-```
-
-#### 3.2.1 exchangDeclare 方法详解
-
-**1.声明交换器**
-
-```java
-/**
-* Declare an exchange.
-
-* @param exchange the name of the exchange
- 交换器的名称
-
-* @param type the exchange type
- 交换器的类型,fanout,direct,topic 等
-
-* @param durable true if we are declaring a durable exchange (the exchange will survive a server restart)
- 设置是否持久化,持久化可以将交换器存盘,在服务器重启的时候不会丢失相关的信息
-
-* @param autoDelete true if the server should delete the exchange when it is no longer in use
- 是否自动删除,自删除的前提是至少有一个队列或者交换器与这交换器绑定,之后所有与这个交换器绑定的队列或者交换器都与此解绑后删除,一般都设置为fase
-
-* @param internal true if the exchange is internal, i.e. can't be directly
- internal是否内置,如果设置 为true,则表示是内置的交换器,客户端程序无法直接发送消息到这个交换器中,只能通过交换器路由到交换器的方式
-
-* @param arguments other properties (construction arguments) for the exchange
- arguments:其它一些结构化参数比如:alternate-exchange
-
-* @return a declaration-confirm method to indicate the exchange was successfully declared
-* @throws java.io.IOException if an error is encountered
- */
-Exchange.DeclareOk exchangeDeclare(String exchange,
- String type,
- boolean durable,
- boolean autoDelete,
- boolean internal,
- Map arguments) throws IOException;
-```
-
-**2.检测交换器是否存在**
-
-```java
-/**
-* Declare an exchange passively; that is, check if the named exchange exists.
-* @param name check the existence of an exchange named this
-* @throws IOException the server will raise a 404 channel exception if the named exchange does not exist.
-它主要用来检测相应的交换器是否存在。如果存在则正常返回:如果不存在则抛出异常 : 404 channel exception。
-*/
-Exchange.DeclareOk exchangeDeclarePassive(String name) throws IOException;
-```
-
-**3. 删除交换器**
-
-```java
-/**
-* Delete an exchange
-* @param exchange the name of the exchange
-* @param ifUnused true to indicate that the exchange is only to be deleted if it is unuse
- ifUnused 用来设置是否在交换器没有被使用的情况下删除 。 如果 isUnused 设置为 true,则只有在此交换器没有被使用的情况下才会被删除;如果设置 false,则无论如何这个交换器都要被删除。
-* @return a deletion-confirm method to indicate the exchange was successfully deleted
-* @throws java.io.IOException if an error is encountered
-*/
-Exchange.DeleteOk exchangeDelete(String exchange, boolean ifUnused) throws IOException;
-```
-
-#### 3.2.2 queneDeclare方法详解
-
-queneDeclare只有两个重载方法:
-
-不带任何参数的 queueDeclare 方法默认创建一个由 RabbitMQ 命名的(类似这种amq.gen-LhQzlgv3GhDOv8PIDabOXA 名称,这种队列也称之为匿名队列〉、排他的、自动删除的、非持久化的队列。
-
-```java
-/**
-* Declare a queue
-* @param queue the name of the queue
- 队列的名称。
-* @param durable true if we are declaring a durable queue (the queue will survive a server restart)
- 是否持久化
-* @param exclusive true if we are declaring an exclusive queue (restricted to this connection)
-* @param autoDelete true if we are declaring an autodelete queue (server will delete it when no longer in use)
- 是否自动删除 自动删除的前提是:至少有一个消费者连接到这个队列,之后所有与这个队列连接的消费者都断开时,才会自动删除。
-* @param arguments other properties (construction arguments) for the queue
-* @return a declaration-confirm method to indicate the queue was successfully declared
-* @throws java.io.IOException if an error is encountered
-*/
-Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete,
- Map arguments) throws IOException;
-```
-
-exclusive : 设置是否排他。为 true 则设置队列为排他的。如果一个队列被声明为排他队列,该队列仅对首次声明它的连接可见,并在连接断开时自动删除。这里需要注意三点:
-
-- 排他队列是基于连接( Connection) 可见的,同一个连接的不同信道 (Channel)是可以同时访问同一连接创建的排他队列;
-- "首次"是指如果一个连接己经声明了 一个排他队列,其他连接是不允许建立同名的排他队列的,这个与普通队列不同;
-- 即使该队列是持久化的,一旦连接关闭或者客户端退出,该排他队列都会被自动删除,这种队列适用于一个客户端同时发送和读取消息的应用场景。
-
-注:
-
-生产者和消费者都能够使用 queueDeclare 来声明一个队列,但是如果消费者在同一个信道上订阅了另一个队列,就无法再声明队列了。必须先取消订阅,然后将信道直为"传输" 模式,之后才能声明队列。
-
-**清空队列内容**:
-
-```java
-Queue.PurgeOk queuePurge(String queue) throws IOException;
-```
-
-#### 3.2.3 queueBind方法详解
-
-**用于交换器与队列的绑定**
-
-```java
-# 绑定
-Queue.BindOk queueBind(String queue, String exchange, String routingKey, Map arguments) throws IOException;
-
-# 解绑
-Queue.UnbindOk queueUnbind(String queue, String exchange, String routingKey, Map arguments) throws IOException;
-```
-
-#### 3.2.4 exchangeBind方法详解
-
-**用于交换器与交换器的绑定**
-
-```java
-Exchange.BindOk exchangeBind(String destination, String source, String routingKey, Map arguments) throws IOException;
-```
-
-生产者发送消息至交换器 source 中,交换器 source 根据路由键找到与其匹配的另一个交换器 destination , 井把消息转发到 destination 中 , 进而存储在 destination 绑定 的队列 queue 中 。
-
-### 3.3 发送消息(basicPublish)
-
-补充:Java 8 对接口做了进一步的增强。
-
-- **a.** 在接口中可以添加使用 default 关键字修饰的非抽象方法。即:默认方法(或扩展方法)
-- **b.** 接口里可以声明静态方法,并且可以实现。
-
-```java
-void basicPublish(String exchange, String routingKey, boolean mandatory, boolean immediate, BasicProperties props, byte[] body) throws IOException;
-```
-
-- exchange: 交换器的名称,指明消息需要发送到哪个交换器中 。 **如果设置为空字符串,则消息会被发送到 RabbitMQ 默认的交换器中**;
-- props : 消息的基本属性集;
-- byte [] body : 消息体 ( payload ) ,真正需要发送的消息 。
-
-```java
-// 发送一条持久化的消息
-channel.basicPublish(EXCHANGE_NAME,ROUTING_KEY,MessageProperties.PERSISTENT_TEXT_PLAIN,message.getBytes());
-
-// 发送一条特殊配置的消息
-channel.basicPublish(EXCHANGE_NAME,ROUTING_KEY,
- new AMQP.BasicProperties.Builder()
- .contentType("text/plain")
- .deliveryMode(2)
- .priority(1)
- .headers(new HashMap())
- .expiration("6000")
- .build(),
- message.getBytes());
-```
-
-### 3.4 消费消息
-
-#### 3.4.1 推模式
-
-在推模式中,可以通过持续订阅的方式来消费消息。接收消息一般通过实现**Consumer**接口或者继承**DefaultConsumer**类来实现。当调用与Consumer相关的API方法时,不同的订阅采用不同的消费者标签(consumerTag)来区分彼此,在同一个Channel中的消费者也需要通过唯一的消费者标签以作区分。
-
-```java
-channel.basicConsume(QUEUE_NAME,false,"myConsumerTag",new DefaultConsumer(channel) {
- // 客户端接收后处理消息
- @Override
- public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
- System.out.println("rev message:"+new String(body));
- String routingKey = envelope.getRoutingKey();
- String contentType = properties.getContentType();
- long deliveryTag = envelope.getDeliveryTag();
- // 确认收到消息
- channel.basicAck(envelope.getDeliveryTag(),false);
- // 或者拒绝消息 一次只能拒绝一条
- channel.basicReject(deliveryTag,true);
- // 一次拒绝多条
- channel.basicNack(deliveryTag,true,true);
- }
- });
-
-```
-
-```java
-String basicConsume(String queue, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map arguments, Consumer callback) throws IOException;
-```
-
-- queue : 队列的名称:
-- autoAck : 设置是否自动确认。建议设成 false ,即不自动确认:
-- consumerTag: 消费者标签,用来区分多个消费者:
-- noLocal : 设置为 true 则表示不能将同一个 Connection中生产者发送的消息传送给这个 Connection 中的消费者:
-- exclusive : 设置是否排他 :
-- arguments : 设置消费者的其他参数:
-- callback : 设置消费者的回调函数。用来处理 RabbitMQ 推送过来的消息,比如DefaultConsumer , 使用时需要客户端重写 (override) 其中的方法。
-
-**注**:
-
-每个 Channel 都拥有自己独立的线程。最常用的做法是一个 Channel 对应一个消费者,也就是意味着消费者彼此之间没有任何关联。当然也可以在一个 Channel 中维持多个消费者,但是要注意一个问题,如果 Channel 中的一个消费者一直在运行,那么其他消费者的 callback会被"耽搁"。
-
-#### 3.4.2 拉模式
-
-通过channel.basicGet方法可以单挑获取信息。
-
-```java
-GetResponse response = channel.basicGet(QUEUE_NAME, false);
-System.out.println(new String(response.getBody()));
-channel.basicAck(response.getEnvelope().getDeliveryTag(),false);
-```
-
-**注**:
-
-Basic . Consume 将信道 (Channel) 直为接收模式,直到取消队列的订阅为止。在接收模式期间, RabbitMQ 会不断地推送消息给消费者,当然推送消息的个数还是会受到 Basic.Qos的限制.如果只想从队列获得单条消息而不是持续订阅,建议还是使用Basic.Get 进行消费.
-
-### 3.5 消费端的确认与拒绝
-
-**1.确认**
-
-为了保证消息从队列可靠地达到消费者, RabbitMQ 提供了消息确认机制( messageacknowledgement) 。 消费者在订阅队列时,可以指定 aut oAck 参数:
-
-**当 autoAck 等于 false时, RabbitMQ 会等待消费者显式地回复确认信号后才从内存(或者磁盘)中移去消息(实质上是先打上删除标记,之后再删除) 。**
-
-**当 autoAck 等于 true 时, RabbitMQ 会自动把发送出去的消息置为确认,然后从内存(或者磁盘)中删除,而不管消费者是否真正地消费到了这些消息 。**
-
-采用消息确认机制后,只要设置 autoAck 参数为 false,消费者就有足够的时间处理消息(任务) ,不用担心处理消息过程中消费者进程挂掉后消息丢失的问题 , 因为 RabbitMQ 会一直等待持有消息直到消费者显式调用 Basic.Ack 命令为止 。
-当 autoAck 参数置为 false ,对于 RabbitMQ 服务端而言 ,队列中的消息分成了两个部分 :一部分是等待投递给消费者的消息:一部分是己经投递给消费者,但是还没有收到消费者确认信号的消息。 如果 RabbitMQ 一直没有收到消费者的确认信号,并且消费此消息的消费者己经断开连接,则 RabbitMQ 会安排该消息重新进入队列,等待投递给下一个消费者,当然也有可能还是原来的那个消费者。
-
-RabbitMQ 不会为未确认的消息设置过期时间,它判断此消息是否需要重新投递给消费者的唯一依据是消费该消息的消费者连接是否己经断开,这么设计的原因是 RabbitMQ 允许消费者消费一条消息的时间可以很久很久。
-
-**2.拒绝**
-
-```java
-// 一次拒绝一条
-void basicReject(long deliveryTag, boolean requeue) throws IOException;
-
-// 一次拒绝多条
- void basicNack(long deliveryTag, boolean multiple, boolean requeue)
- throws IOException;
-```
-
-其中 deliveryTag 可以看作消息的编号 。如果 requeue 参数设置为 true ,则 RabbitMQ 会重新将这条消息存入队列,以便可以发送给下一个订阅的消费者;如果 requeue 参数设置为 false,则 RabbitMQ立即会把消息从队列中移除,而不会把它发送给新的消费者。
-
-multiple 参数设置为 false 则表示拒绝编号为 deliveryTag的这 一条消息,这时候 basicNack 和basicReject 方法一样; multiple 参数设置为 true 则表示拒绝 deliveryTag 编号之前所有未被当前消费者确认的消息。
-
-**3.重入队列**
-
-```java
-Basic.RecoverOk basicRecover() throws IOException;
-Basic.RecoverOk basicRecover(boolean requeue) throws IOException;
-```
-
-这个 channel.basicRecover 方法用来请求 RabbitMQ 重新发送还未被确认的消息 。 如果 requeue 参数设置为 true ,则未被确认的消息会被重新加入到队列中,这样对于同一条消息来说,可能会被分配给与之前不同的消费者。如果 requeue 参数设置为 false,那么同一条消息会被分配给与之前相同的消费者。默认情况下,如果不设置 requeue 这个参数,相当channel.basicRecover(true) ,即 requeue 默认为 true。
-
-### 3.6 关闭连接
-
-在应用程序使用完之后,需要关闭连接,释放资源:
-channel.close();
-conn.close() ;
-
-## 第四章 RabbitMQ进阶
-
-### 4.1 消息何去何从
-
-mandatory 和 immediate 是 channel.basicPublish 方法中的两个参数,它们都有**当消息传递过程中不可达目的地时将消息返回给生产者的功能**。 RabbitMQ 提供的备份交换器(Altemate Exchange) 用以将未能被交换器路由的消息(没有绑定队列或者没有匹配的绑定〉存储起来,而不用返回给客户端。
-
-#### 4.1.1 mandatory 参数
-
-当 mandatory 参数设为 true 时,**交换器无法根据自身的类型和路由键找到一个符合条件的队列**,那么 RabbitMQ 会调用 Basic.Return 命令将消息返回给生产者 。
-
-当 mandatory 参数设置为 false 时,出现上述情形,则消息直接被丢弃 。
-
-那么生产者如何获取到没有被正确路由到合适队列的消息呢? **可以通过调用channel . addReturnListener 来添加 ReturnListener 监昕器实现**。
-
-```java
-channel.addReturnListener(new ReturnListener() {
- public void handleReturn(int replyCode, String replyText, String exchange, String routingKey, AMQP.BasicProperties properties, byte[] body) throws IOException {
- System.out.println("Basic.Return返回的结果是:"+message);
- }
- });
-```
-
-#### 4.1.2 immedidate 参数
-
-当 immediate 参数设为 true 时,如果交换器在**将消息路由到队列时发现队列上并不存在任何消费者**,那么这条消息将不会存入队列中。当与路由键匹配的所有队列都没有消费者时 ,该消息会通过 Basic . Return 返回至生产者。
-
-**RabbitMQ 3 .0 版本因为性能开始去掉了对 imrnediate 参数的支持**
-
-#### 4.1.3 备份交换器
-
-备份交换器,可以将未被路由的消息存储在 RabbitMQ 中,再在需要的时候去处理这些消息。
-
-可以通过在声明交换器(调用 channel.exchangeDeclare 方法)的时候添加**alternate-exchange** 参数来实现
-
-```java
-// 声明备份交换器 最好将type类型设置为 fanout
-channel.exchangeDeclare( "myAe " , "fanout" , true, false , null) ;
-
-// 声明正常交换器 并设置备份交换器为myAe
-Map args = new HashMap();
-args.put("a1ternate-exchange" , "myAe");
-channel.exchangeDeclare( "normalExchange" , "direct" , true , false , args);
-
-// 声明队列并和交换器绑定
-channel.queueDeclare( "norma1Queue " , true , false , false , null);
-channel.queueBind( " norma1Queue " , " normalExchange" , " norma1Key");
-channel.queueDeclare( "unroutedQueue " , true , false , false , null);
-channel.queueBind( "unroutedQueue ", "myAe ", "");
-```
-
-**特殊情况**:
-
-- 如果设置的备份交换器不存在,客户端和 RabbitMQ 服务端都不会有异常出现,此时消息会丢失。
-- 如果备份交换器没有绑定任何队列,客户端和 RabbitMQ 服务端都不会有异常出现,此时消息会丢失。
-- 如果备份交换器没有任何匹配的队列,客户端和 RabbitMQ 服务端都不会有异常出现,此时消息会丢失。
-- 如果备份交换器和 mandatory 参数一起使用,那么 mandatory 参数无效。
-
-### 4.2 过期时间(TTL)
-
-#### 4.2.1设置消息的TTL
-
-- 第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。
-- 第二种方法是对消息本身进行单独设置,每条消息的 TTL 可以不同。
-- 两种方法一起使用,则消息的 TTL 以两者之间较小的那个数值为准。
-- 消息在队列中的生存时司 一旦超过设置 的 TTL 值时,就会变成"死信" (Dead Message) ,消费者将无法再收到该消息(这点不是绝对的 ,可以参考 4.3 节) 。
-
-**1.通过队列属性设置消息 TTL 的方法是在 channel.queueDeclare 方法中加入 x-message-ttl 参数实现的,这个参数的单位是毫秒。**
-
-```java
-Map argss = new HashMap();
-argss.put("x-message-ttl " , 6000);
-channel.queueDeclare(queueName , durable , exclusive , autoDelete , argss) ;
-```
-
-**2.针对每条消息设置 TTL 的方法是在 channel.basicPublish 方法中加入 expiration 的属性参数,单位为毫秒。**
-
-采用这种方法设置,一旦消息过期,就会从队列中抹去 。
-
-注:如果不设置 TTL.则表示此消息不会过期 ;如果将 TTL 设置为 0,则表示除非此时可以直接将消息投递到消费者,否则该消息会被立即丢弃。
-
-```java
-AMQP.BasicProperties.Builder builder = new AMQP.BasicProperties.Builder();
-builder.deliveryMode(2); // 持久化消息
-builder.expiration( " 60000 " );// 设置 TTL=60000ms
-AMQP.BasicProperties properties = builder . build() ;
-channel.basicPublish(exchangeName, routingKey, mandatory, properties,"ttlTestMessage".getBytes());
-```
-
-#### 4.2.2 设置队列的TTL
-
-通过 channel . queueDeclare 方法中的 x - expires 参数可以控制队列被自动删除前处于未使用状态的时间。未使用的意思是队列上没有任何的消费者,队列也没有被重新声明,并且在过期时间段 内也未调用过 Basic.Get 命令。 RabbitMQ 会确保在过期时间到达后将队列删除,但是不保障删除的动作有多及时 。在RabbitMQ 重启后 , 持久化的队列的过期时间会被重新计算。
-
-**用于表示过期时间的 x-expires 参数以毫秒为单位 , 井且服从和 x-message-ttl 一样的约束条件,不过不能设置为 0。比如该参数设置为 1000 ,则表示该队列如果在 1 秒钟之内未使用则会被删除。**
-
-```java
-Map args =new HashMap() ;
-args.put( "x-expires" , 1800000);
-channel.queueDeclare("myqueue " , false , false , false , args) ;
-```
-
-### 4.3 死信队列DLX
-
-当有队列中存在死信时,RabbitMQ 就会自动地将这个消息重新发布到设置的 DLX 上去 。
-
-**消息变成死信一般是由于以下几种情况**:
-
-- 消息被拒绝 (Basic.Reject/Basic.Nack) ,井且设置 requeue 参数为 false;
-- 消息过期;
-- 队列达到最大长度。
-
-**通过在 channel.queueDeclare 方法中设置 x-dead-letter-exchange 参数来为这个队列添加 DLX**
-
-```java
- //创建 DLX: dlx_exchange
- channel.exchangeDeclare("dlx_exchange " , "direct ");
- Map args = new HashMap();
- args.put("x-dead-letter-exchange" , " dlx_exchange ");
- //也可以为这个 DLX 指定路由键,如果没有特殊指定,则使用原队列的路由键:
- args.put("x-dead-letter-routing-key" , "dlx-routing-key");
- //为队列 myqueue 添加 DLX
- channel.queueDeclare("myqueue" , false , false , false , args);
-```
-
-```java
- // 声明用于DXL队列的交换器
- channel.exchangeDeclare("exchange.dlx", "direct", true);
- // 声明正常交换器
- channel.exchangeDeclare("exchange.normal ", "fanout ", true);
- // 为正常队列绑定DXL交换器
- Map args = new HashMap();
- args.put("x-message - ttl ", 10000);
- args.put("x-dead-letter-exchange ", "exchange.dlx"); //DXL队列与DXL交换器的原路由键
- args.put("x-dead-letter-routing-key", " routingkey");
- channel.queueDeclare(" queue.norma1 ", true, false, false, args);
- // 正常队列与正常交换器绑定
- channel.queueBind("queue.normal", "exchange.normal", "");
- // 声明DXL队列
- channel.queueDeclare(" queue.d1x ", true, false, false, null);
- // DXL队列与信DXL交换器绑定
- channel.queueBind("queue.dlx ", "exchange.dlx ", "routingkey");
- // 发送一条信息 10s超时后成为死信
- channel.basicPublish("exchange.normal", " rk",
- MessageProperties.PERSISTENT_TEXT_PLAIN, "message".getBytes());
-```
-
-### 4.4 延迟队列
-
-利用死信队列来实现:
-
-