Before, we recorded the native java code using rabbitmq. It is very simple, similar to the native jdbc code. The connection object is extracted as a tool class. The producer and consumer obtain the connection object through the tool class, and then obtain the channel object. Register the exchange or queue, etc., send and receive messages.
In enterprise development, we mostly use the spring framework to integrate other technologies. Springboot is more convenient to provide a variety of starters to quickly add dependencies, complete the integration, and use it out of the box.
- Add dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
- Writing configuration
Configuration information includes ip, port, virtual host, user name and password, and is consistent with the configuration information required by the native java code.
spring:
application:
name: spirngboot-rabbitmq
rabbitmq:
host: 192.168.20.128
port: 5672
virtual-host: /vh
username: wuwl
password: 123456
- Writing and testing
This article focuses on the first five commonly used models, integrating rabbitmq on the basis of the spirngboot framework and testing it.
(1) Hello World model
This is a simple direct connection model. The producer sends the message directly to the message queue, and the consumer gets it directly after binding the message queue, one to one.
spring-boot-starter-amqp
A org.springframework.amqp.rabbit.core.RabbitTemplate
class is provided for us to facilitate our use rabbitmq
, and it can be injected automatically.
Producer test class:
@SpringBootTest(classes = RabbitmqDemoApplication.class)
@RunWith(SpringRunner.class)
public class RabbitmqDemoApplicationTests {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void testHelloQueues(){
rabbitTemplate.convertAndSend("hello","hello world");
}
}
The producer sends a message to the queue named hello, but in the absence of a consumer, the producer has no meaning. In addition, convertAndSend
the first parameter of the method does not mean the message queue, but routingKey
, we find the originally defined interface based on the source code and see the following:
/**
* Convert a Java object to an Amqp {@link Message} and send it to a default exchange
* with a specific routing key.
*
* @param routingKey the routing key
* @param message a message to send
* @throws AmqpException if there is a problem
*/
void convertAndSend(String routingKey, Object message) throws AmqpException;
The second parameter is the Object
type, which means that any type of object can be passed. This method converts the object into a Amqp
message and sends it to a default exchange, and routingKey
is the content of the first parameter, without mentioning the message queue information. However, we can analyze that, here routingKey
and queues
should be the same name.
Consumer category:
@Component
@RabbitListener(queuesToDeclare = @Queue("hello"))
public class HelloQueuesConsumer {
@RabbitHandler
public void consume(String msg){
System.out.println("消费消息:" + msg + " " + System.currentTimeMillis());
}
}
The above code is equivalent to:
@Component
public class HelloQueuesConsumer {
@RabbitListener(queuesToDeclare = @Queue("hello"))
public void consume(String msg){
System.out.println("消费消息:" + msg + " " + System.currentTimeMillis());
}
}
- @RabbitListener can be marked on the class, it needs to be used with @RabbitHandler annotation
- @RabbitListener is marked on the class to indicate that when a message is received, it will be handed over to the @RabbitHandler method for processing, which method is used for processing, according to the parameter type after MessageConverter conversion
Start the test method directly, that is, the producer, you can see that the
consumer has received the information in the message queue and printed it.
(2) Work queues model
Producer test method, the class is consistent with the first model
@Test
public void testWorkQueues(){
for (int i = 0; i < 20; i++) {
rabbitTemplate.convertAndSend("work","work index " + i);
}
}
Consumer category:
@Component
public class WorkQueuesConsumer {
@RabbitListener(queuesToDeclare = @Queue("work"))
public void consume1(String msg){
System.out.println("consumer1消费消息:" + msg);
}
@RabbitListener(queuesToDeclare = @Queue("work"))
public void consume2(String msg){
System.out.println("consumer2消费消息:" + msg);
}
}
Start the producer test method:
Consumer 1 and Consumer 2 evenly distribute the message tasks in the queue. Even if the execution efficiency of the two is inconsistent, they are equally distributed.
(3) Publish/Subscribe model
Producer test method:
for (int i = 0; i < 20; i++) {
rabbitTemplate.convertAndSend("amq.fanout","","fanout msg " + i);
}
Consumer category:
@Component
public class FanoutQueuesConsumer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(
value = "amq.fanout",
type = "fanout"))})
public void consume1(String msg) {
System.out.println("consumer1消费消息:" + msg);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(
value = "amq.fanout",
type = "fanout"))})
public void consume2(String msg) {
System.out.println("consumer2消费消息:" + msg);
}
}
Note the switch information here
Start the producer test method:
Only part of the print information is pasted here. Two consumers get the same message. The producer sends the message to the exchange, which is sent to all temporary message queues registered to the exchange, and then the consumer Get the messages in the queue.
(4) Routing model
Producer test method:
@Test
public void testDirectQueues(){
rabbitTemplate.convertAndSend("amq.direct","info","routingKey is info");
rabbitTemplate.convertAndSend("amq.direct","warn","routingKey is warn");
rabbitTemplate.convertAndSend("amq.direct","error","routingKey is error");
}
Routing has also become a fanout model, and the corresponding switch type is direct
Consumer category:
@Component
public class DirectQueuesConsumer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(
value = "amq.direct",
type = "direct"),
key = {
"info", "warn", "error"})})
public void consume1(String msg) {
System.out.println("consumer1消费消息:" + msg);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(
value = "amq.direct",
type = "direct"),
key = "error")})
public void consume2(String msg) {
System.out.println("consumer2消费消息:" + msg);
}
}
Start the producer test class:
Consumer one is configured with three types of routingKey, so all three types of messages can be received, and consumer two can only receive messages of error type.
(5) Topic model
Producer test method:
@Test
public void testTopicQueues(){
rabbitTemplate.convertAndSend("amq.topic","file.info","routingKey is info");
rabbitTemplate.convertAndSend("amq.topic","file.warn","routingKey is warn");
rabbitTemplate.convertAndSend("amq.topic","file.error","routingKey is error");
}
Consumer category:
@Component
public class TopicQueuesConsumer {
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(
value = "amq.topic",
type = "topic"),
key = {
"#"})})
public void consume1(String msg) {
System.out.println("consumer1消费消息:" + msg);
}
@RabbitListener(bindings = {
@QueueBinding(value = @Queue,
exchange = @Exchange(
value = "amq.topic",
type = "topic"),
key = "*.error")})
public void consume2(String msg) {
System.out.println("consumer2消费消息:" + msg);
}
}
Start the producer test method:
Consumer 1 is configured routingKey
to #
accept any type of message, which *
represents a word, and Consumer 2 can accept messages with any word added .error
as routingKey
.