1. Download and start rabbitmq
docker pull hub.c.163.com/library/rabbitmq:3-management docker run -d -p 5672:5672 -p 15672:15672 --name mymq hub.c.163.com/library/rabbitmq:3-management #web access path ip:15672 #User name: guest password: Guest
2. Introduce dependency into the project of springboot
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
configuration information
spring: rabbitmq: host: 192.168.1.1 port: 5672 username: guest password: guest virtual-host: / publisher-confirms: true listener: simple: retry: enabled: true # Allow message consumption to fail retries max-attempts: 3 # Message consumption up to 3 times initial-interval: 1000 # Message multiple consumption interval 1 second default-requeue-rejected: false # Set to false, the message will be discarded or republished to the dead letter queue
3. Write configuration information of dead letter queue
import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; /** * Configuration of dead letter queue * * <p>The dead letter queue is actually, * When our business queue fails to handle (such as throwing exceptions and reaching the upper limit of retry), * It will resend the message to another Exchange(Dead Letter Exchanges), * The Exchange is then redirected to another queue according to the routingKey, * Reprocess the message in this queue. </p> */ @Configuration public class RabbitDeadLetterConfig { public static final String DEAD_LETTER_EXCHANGE = "TEXT_DLE"; public static final String DEAD_LETTER_TEST_ROUTING_KEY = "TEST_RK_DL"; public static final String DEAD_LETTER_REDIRECT_ROUTING_KEY = "TEXT_RK_RJ"; public static final String DEAD_LETTER_QUEUE = "TEXT_QUEUE_DLR"; public static final String REDIRECT_QUEUE = "TEXT_QUEUE_RJ"; /** * Switch defining dead letter queue * @return */ @Bean public Exchange deadLetterExchange() { return ExchangeBuilder.directExchange(DEAD_LETTER_EXCHANGE).durable(true).build(); } /** * Define dead letter queue * @return */ @Bean public Queue deadLetterQueue() { Map<String, Object> map = new HashMap<>(2); map.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE); // Exception thrown by dead letter queue routingKey of redirection queue map.put("x-dead-letter-routing-key", DEAD_LETTER_REDIRECT_ROUTING_KEY); return QueueBuilder.durable(DEAD_LETTER_QUEUE).withArguments(map).build(); } @Bean public Queue rejectQueue() { return new Queue(REDIRECT_QUEUE, true); } /** * Bind dead letter queue to dead letter switch * @return */ @Bean public Binding deadLetterBinding() { return new Binding(DEAD_LETTER_QUEUE, Binding.DestinationType.QUEUE, DEAD_LETTER_EXCHANGE, DEAD_LETTER_TEST_ROUTING_KEY, null); } /** * Bind redirection queue to Exchange of dead letter queue through routingKey * @return */ @Bean public Binding redirectBinding() { return new Binding(REDIRECT_QUEUE, Binding.DestinationType.QUEUE, DEAD_LETTER_EXCHANGE, DEAD_LETTER_REDIRECT_ROUTING_KEY, null); } }
4. The sender who wrote the message
import com.carter.car.rabbitmq.config.RabbitDeadLetterConfig; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class DeadLetterSender { @Autowired private RabbitTemplate rabbitTemplate; public void send(String msg) { rabbitTemplate.convertAndSend( RabbitDeadLetterConfig.DEAD_LETTER_EXCHANGE, RabbitDeadLetterConfig.DEAD_LETTER_TEST_ROUTING_KEY, msg ); } }
5. Message consumers writing dead letter queue
import com.carter.car.rabbitmq.config.RabbitDeadLetterConfig; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.messaging.handler.annotation.Payload; import org.springframework.stereotype.Component; /** * Dead letter queue consumer */ @Component @RabbitListener(queues = RabbitDeadLetterConfig.DEAD_LETTER_QUEUE) public class DeadLetterConsumer { @RabbitHandler public void handler(@Payload String msg) { System.out.println("DeadLetterConsumer receive msg:" + msg); throw new RuntimeException("i am a error."); } }
6. Write message consumers of redirection queue
import com.carter.car.rabbitmq.config.RabbitDeadLetterConfig; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; /** * Redirect queue consumer */ @Component @RabbitListener(queues = RabbitDeadLetterConfig.REDIRECT_QUEUE) public class RedirectQueueConsumer { @RabbitHandler public void handler(String msg) { System.out.println("RedirectQueueConsumer receive msg:" + msg); } }
7. Write test class
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest @RunWith(SpringRunner.class) public class DeadLetterTest { @Autowired private DeadLetterSender deadLetterSender; @Test public void testSend() { deadLetterSender.send("hello world!"); } }
8. Start the springboot project, and then run the test to send the message.
Reference resources:
Cancel the order 30 minutes after dead letter queue
Dead letter queue application scenario