preface
RabbiMQ introduction
First, use scenarios
RabbitMQ is a message-oriented middleware, so its primary role is as a message buffer, enabling asynchronous and decoupled applications. RabbitMQ is a type of messaging middleware that implements AMQP (Advanced Message Queuing Protocol). It originated in the financial system and is used to store and forward messages in distributed systems. RabbitMQ has excellent usability, scalability, and high availability. RabbitMQ is primarily implemented for bidirectional decoupling between systems. When producers churn out data and consumers can’t consume it quickly, you need an intermediate layer. Save this data. AMQP (Advanced Message Queuing Protocol) is an open standard of application-layer protocols designed for message-oriented middleware. Message-oriented middleware is primarily used for decoupling between components so that the sender of a message does not need to be aware of the message consumer and vice versa. The main characteristics of AMQP are message orientation, queue, routing (including point-to-point and publish/subscribe), reliability, and security. See RabbitMQ’s official guide for detailed concepts
Ii. Related concepts
When we talk about queued services, we usually have three concepts: sender, queue and receiver. RabbitMQ abstracts this basic concept further by adding an Exchange between the sender and queue. In this way, there is no direct contact between the sender and the queue. Instead, the sender sends the message to the exchange, which in turn sends the message to the queue according to the scheduling policy.
There are four important concepts: virtual host, switch, queue, and binding.
- Virtual host V-host: A virtual host holds a set of switches, queues, and bindings. Why multiple virtual hosts? Quite simply, RabbitMQ allows users to control permissions only at the granularity of the virtual host. Therefore, if you want to deny group A access to group B’s switches/queues/bindings, you must create A virtual host for both group A and group B. Each RabbitMQ server has a default virtual host.
- Switch: Exchange forwards messages, but it does not store them. If the Exchange does not Queue bind to the Exchange, it simply discards messages sent by Producer. Here’s an important concept: routing keys. When the message arrives at the switch, the interaction will forward it to the corresponding queue, which queue will be forwarded according to the route key.
- Bind: That is, the switch needs to bind to queues, as shown in the figure above
Exchange
The switch receives messages and forwards them to the bound queue. The switch does not store messages. If the ACK mode is enabled, the switch returns an error if it cannot find the queue. There are four types of switches: Direct, Topic, Headers and Fanout
- Direct: The behavior of the Direct type is “match first, then deliver “. When a routingkey is set at binding time, messages that match the Routingkey will be sent to the binding queue by the exchange.
- Topic: Forwarding messages according to rules (most flexible)
- Headers: switch for which the header attribute type is set
- Fanout: Forwards messages to all bound queues
Direct Exchange
Direct Exchange is the default switch mode for RabbitMQ and is the simplest mode to find queues based on key full text matching.
The first X-Q1 has a binding key named orange; X-q2 has two binding keys named black and green. When the routing key in the message corresponds to the binding key, then we know which queue the message is going to.
Ps: Why are there two binding keys for X to Q2: black and green? – This is mainly because there may be Q3 again, and Q3 accepts only black’s information, while Q2 accepts not only black’s information but also Green’s information.
Topic Exchange
Messages are forwarded to queues based on wildcards. On such switches, the binding between queues and switches defines a routing mode, and the switch can forward messages only if the wildcards match the routing mode and the routing key.
- * (asterisk) can replace a word.
- # (hash) can replace zero or more words.
Headers Exchange
Headers also matches by rule, and headers is a type of custom matching rule, as opposed to direct and topic, which use a routing_key. When a queue is bound to an exchange, a set of key-value pair rules are set, and a message contains a set of key-value pairs (headers attributes). When one or all of these key-value pairs match, the message is posted to the corresponding queue.
Fanout Exchange
The message broadcast model, which is our publish subscribe model. Fanout Exchange message broadcast mode, regardless of routing key or routing mode, sends messages to all queues bound to it, and is ignored if routing_key is configured.
Message to confirm
How does a message consumer notify Rabbit of a successful message consumption?
Each Message must be acknowledged (acknowledged). This can be done manually or automatically. The automatic ACK will acknowledge the Message immediately after it is sent to the consumer, but the Message may be lost. The consumer failed to process the message, so the message is lost. If the message has been processed, but the following code throws an exception, the consumer business logic will roll back if you use Spring to manage it, This also causes actual message loss. If a service is manually acknowledged, the consumer invokes ACK, nack, reject to confirm the message. Manual confirmation can be performed after a service fails. RabbitMQ will not send any more data to RabbitMQ, because RabbitMQ considers the service to be limited in its processing capacity. The ACK mechanism can also limit the flow of packets, such as sleeping for a few seconds when a message is received.
- Acknowledgemode. NONE: Automatic acknowledgment
- Acknowledgemode. AUTO: Acknowledged as applicable
- Acknowledgemode. MANUAL: Indicates MANUAL acknowledgment
The RabbitMQ SpringBoot integration
- To configure poM, add spring-boot-starter-AMQP support. Springboot is based on version 2.1.4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Configure the yaml file 1 for Springboot.
1. `server:` 2. `servlet:` 3. `context-path:/rabbitmq` 4. `port:9004` 5. `spring:` 6. `application:` 7. `name: rabbitmq` 8. `rabbitmq:` 9. `host: localhost` 10. `virtual-host:/crawl` 11. `username: xxxx` 12. `password: 'port:5672' For example, 'publisher-returns:true' 16. '# confirm message sending correctly' 17. 'publisher-Confirm :true' 18. 'Template:' 19 20. 'enabled:true' 21. 'initial-interval:2s' 22.' Listener: '23.' Simple: '24 None '25.' acknowledge-mode: manual 'Copy the code
In addition we also need to configure an ACK confirmation callback configuration, by implementing RabbitTemplate. ConfirmCallback interface, the message is sent to the Broker triggered after the callback, which is only to confirm whether it is right to Exchange.
import
lombok.extern.slf4j.Slf4j;
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
javax.annotation.PostConstruct;
/ * *
*
@author lijianqing
*
@version
1.0
*
@ClassName
RabbitTemplateConfirmCallback
*
@date
2019/4/23
12:55
* /
@Component
@Slf4j
public
class
RabbitTemplateConfirmCallback
implements
RabbitTemplate.ConfirmCallback
{
@Autowired
private
RabbitTemplate rabbitTemplate;
@PostConstruct
public
void
init()
{
/ / specified ConfirmCallback
-
`rabbitTemplate.setConfirmCallback(this); `Copy the code
}
@Override
public
void
confirm(CorrelationData correlationData,
boolean ack,
String cause)
{
-
Log.info (" message unique identifier: {}, confirm result: {}, failure cause: {}", correlationData, ACK, cause); `Copy the code
}
}
A message returns on failure, such as a routing step to a queue, or a callback is triggered if the west Osi message is successfully sent to the exchange but there is no matching queue
import
lombok.extern.slf4j.Slf4j;
import
org.springframework.amqp.core.Message;
import
org.springframework.amqp.rabbit.core.RabbitTemplate;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Component;
import
javax.annotation.PostConstruct;
/ * *
*
@author lijianqing
*
@version
1.0
*
@ClassName
RabbitTemplateReturnCallback
*
@date
2019/4/23
12:55
* /
@Component
@Slf4j
public
class
RabbitTemplateReturnCallback
implements
RabbitTemplate.ReturnCallback
{
@Autowired
private
RabbitTemplate rabbitTemplate;
@PostConstruct
public
void
init()
{
/ / specified ReturnCallback
-
`rabbitTemplate.setReturnCallback(this); `Copy the code
-
`rabbitTemplate.setMandatory(true); `Copy the code
}
@Override
public
void
returnedMessage(Message message,
int replyCode,
String replyText,
String exchange,
String routingKey)
{
-
Log.info (" message body message: "+ message); `Copy the code
-
Log.info (" Message body message: "+ replyCode); `Copy the code
-
'log.info(" Description: "+ replyText); `Copy the code
-
'log.info(" exchange used for messages: "+ exchange); `Copy the code
-
'log.info(" Routing: "+ routingKey); `Copy the code
}
}
Start simple – simple queues
The diagram below:
“P” is our producer, “C” is our consumer. The middle box is a queue – RabbitMQ represents the message buffer reserved for consumers.
Add SimpleConfig to create the queue we want to put
/ * *
* Queue direct drop
*
@author lijianqing
*
@version
1.0
*
@ClassName
SimpleConfig
*
@date
2019/4/26
Then it
* /
@Configuration
public
class
SimpleConfig
{
@Bean
public
Queue
simpleQueue()
{
return
new
Queue("simple");
}
}
Create message sender and message receiver respectively:
- Message sender
import
lombok.extern.slf4j.Slf4j;
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
zero.springboot.study.rabbitmq.model.User;
import
java.util.UUID;
/ * *
*
@author lijianqing
*
@version
1.0
*
@ClassName
HelloSender
*
@date
2019/4/23
when
* /
@Component
@Slf4j
public
class
HelloSender
{
@Autowired
private
RabbitTemplate rabbitTemplate;
public
void
send()
{
User user =
new
User();
-
` user. Elegantly-named setName (" green "); `Copy the code
-
`user.setPass("111111"); `Copy the code
// Send a message to the Hello queue
-
Log.info (" Send message: {}", user); `Copy the code
-
`rabbitTemplate.convertAndSend("hello", user,` `new` `CorrelationData(UUID.randomUUID().toString())); `Copy the code
String msg =
"hello qing";
-
Log.info (" send message: {}", MSG); `Copy the code
-
`rabbitTemplate.convertAndSend("simple", msg); `Copy the code
}
}
- Message receiver
import
com.rabbitmq.client.Channel;
import
lombok.extern.slf4j.Slf4j;
import
org.springframework.amqp.rabbit.annotation.RabbitHandler;
import
org.springframework.amqp.rabbit.annotation.RabbitListener;
import
org.springframework.amqp.support.AmqpHeaders;
import
org.springframework.messaging.handler.annotation.Header;
import
org.springframework.stereotype.Component;
import
zero.springboot.study.rabbitmq.model.User;
import
java.io.IOException;
/ * *
* Listen on the Hello queue
*
*
@author lijianqing
*
@version
1.0
*
@ClassName
HelloReceiver
*
@date
2019/4/23
11:42
* /
@Component
@Slf4j
@RabbitListener(queues =
"simple")
public
class
HelloReceiver
{
@RabbitHandler
public
void
processUser(User user,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
Log.info (" Received message: {}", user); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
@RabbitHandler
public
void
processString(String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
Log.info (" Received message: {}", message); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
}
This implements the pattern of simple messages being sent to a specified queue. Let’s write a test class
Direct Exchange mode
Configure our Direct Exchange switch and create a queue bound to the switch using routing keys
import
org.springframework.amqp.core.Binding;
import
org.springframework.amqp.core.BindingBuilder;
import
org.springframework.amqp.core.DirectExchange;
import
org.springframework.amqp.core.Queue;
import
org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
/ * *
*
*
@author lijianqing
*
@version
1.0
*
@ClassName
DirectConfig
*
@date
2019/4/23
11:15
* /
@Configuration
public
class
DirectConfig
{
// Queue name
public
static
final
String QUEUE_NAME =
"direct_name";
// Switch name
public
static
final
String EXCHANGE =
"zero-exchange";
// Routing key name
public
static
final
String ROUTING_KEY =
"routingKey";
@Bean
public
Queue
blueQueue()
{
return
new
Queue(QUEUE_NAME,
true);
}
@Bean
public
DirectExchange
defaultExchange()
{
return
new
DirectExchange(EXCHANGE);
}
@Bean
public
Binding
bindingBlue()
{
return
BindingBuilder.bind(blueQueue()).to(defaultExchange()).with(ROUTING_KEY);
}
}
Next we create producers and consumers
- producers
import
lombok.extern.slf4j.Slf4j;
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
zero.springboot.study.rabbitmq.config.DirectConfig;
import
zero.springboot.study.rabbitmq.model.User;
import
java.util.UUID;
/ * *
*
@author lijianqing
*
@version
1.0
*
@ClassName
HelloSender
*
@date
2019/4/23
when
* /
@Component
@Slf4j
public
class
DirectSender
{
@Autowired
private
RabbitTemplate rabbitTemplate;
public
void
send()
{
User user =
new
User();
-
` user. Elegantly-named setName (" green "); `Copy the code
-
`user.setPass("111111"); `Copy the code
// Send a message to the Hello queue
-
Log.info ("DirectReceiver sends messages: {}", user); `Copy the code
-
`rabbitTemplate.convertAndSend(DirectConfig.EXCHANGE,` `DirectConfig.ROUTING_KEY, user,` `new` `CorrelationData(UUID.randomUUID().toString())); `Copy the code
String msg =
"hello qing";
-
'log.info("DirectReceiver sends messages: {}", MSG); `Copy the code
-
`rabbitTemplate.convertAndSend(DirectConfig.EXCHANGE,` `DirectConfig.ROUTING_KEY, msg); `Copy the code
}
}
- consumers
/ * *
*
*
@author lijianqing
*
@version
1.0
*
@ClassName
HelloReceiver
*
@date
2019/4/23
11:42
* /
@Component
@Slf4j
@RabbitListener(queues =
"direct_name")
public
class
DirectReceiver
{
@RabbitHandler
public
void
processUser(User user,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
'log.info("DirectReceiver receives message: {}", user); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
@RabbitHandler
public
void
processString(String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
Log.info (" Received message: {}", message); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
}
Third, Topic Exchange mode
Create queues and switches. The queue is bound to the switch by routing matching rules
import
org.springframework.amqp.core.Binding;
import
org.springframework.amqp.core.BindingBuilder;
import
org.springframework.amqp.core.Queue;
import
org.springframework.amqp.core.TopicExchange;
import
org.springframework.beans.factory.annotation.Qualifier;
import
org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
/ * *
* queueMessages match topic.#, queueMessage matches only "topic.message".
*
*
@author lijianqing
*
@version
1.0
*
@ClassName
TopicRabbitConfig
*
@date
2019/4/23
15:03
* /
@Configuration
public
class
TopicRabbitConfig
{
final
static
String message =
"topic.message";
final
static
String messages =
"topic.messages";
@Bean
public
Queue
queueMessage()
{
return
new
Queue(TopicRabbitConfig.message);
}
@Bean
public
Queue
queueMessages()
{
return
new
Queue(TopicRabbitConfig.messages);
}
@Bean
TopicExchange
exchange()
{
return
new
TopicExchange("topicExchange");
}
@Bean
Binding
bindingExchangeMessage(@Qualifier("queueMessage")
Queue queueMessage,
TopicExchange exchange)
{
return
BindingBuilder.bind(queueMessage).to(exchange).with("topic.message");
}
@Bean
Binding
bindingExchangeMessages(@Qualifier("queueMessages")
Queue queueMessages,
TopicExchange exchange)
{
return
BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
}
}
- Creating a producer
import
lombok.extern.slf4j.Slf4j;
import
org.springframework.amqp.rabbit.core.RabbitTemplate;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.stereotype.Component;
/ * *
*
@author lijianqing
*
@version
1.0
*
@ClassName
TopicSender
*
@date
2019/4/23
he
* /
@Component
@Slf4j
public
class
TopicSender
{
@Autowired
private
RabbitTemplate rabbitTemplate;
/ * *
* Match topic.message, both queues will receive it
* /
public
void
send1()
{
String context =
"hi, i am message 1";
-
Log.info (" Subject send: {}", context); `Copy the code
-
`rabbitTemplate.convertAndSend("topicExchange",` `"topic.message", context); `Copy the code
}
/ * *
* matching topic. The messages
* /
public
void
send2()
{
String context =
"hi, i am messages 2";
-
Log.info (" Subject send: {}", context); `Copy the code
-
`rabbitTemplate.convertAndSend("topicExchange",` `"topic.messages", context); `Copy the code
}
}
- Create consumers. Here we create two separate queues of consumers
@Component
@RabbitListener(queues =
"topic.message")
@Slf4j
public
class
TopicReceiver
{
@RabbitHandler
public
void
process(String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
`log.info("topic.message Receiver1 {}: ", message); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
}
Second consumer
@Component
@RabbitListener(queues =
"topic.messages")
@Slf4j
public
class
TopicReceiver2
{
@RabbitHandler
public
void
process(String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
`log.info("topic.messages Receiver2 : {}", message); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
}
4. Fanout mode
Publish, subscribe. All queues bound to the switch receive messages, and any characters of the routing key specified by the sender are ignored
Configure switches and queues
@Configuration
public
class
FanoutRabbitConfig
{
@Bean
public
Queue
AMessage()
{
return
new
Queue("fanout.A");
}
@Bean
public
Queue
BMessage()
{
return
new
Queue("fanout.B");
}
@Bean
public
Queue
CMessage()
{
return
new
Queue("fanout.C");
}
@Bean
FanoutExchange
fanoutExchange()
{
return
new
FanoutExchange("fanoutExchange");
}
@Bean
Binding
bindingExchangeA(Queue
AMessage,
FanoutExchange fanoutExchange)
{
return
BindingBuilder.bind(AMessage).to(fanoutExchange);
}
@Bean
Binding
bindingExchangeB(Queue
BMessage,
FanoutExchange fanoutExchange)
{
return
BindingBuilder.bind(BMessage).to(fanoutExchange);
}
@Bean
Binding
bindingExchangeC(Queue
CMessage,
FanoutExchange fanoutExchange)
{
return
BindingBuilder.bind(CMessage).to(fanoutExchange);
}
}
- Creating a sender
@Component
@Slf4j
public
class
FanoutSender
{
@Autowired
private
RabbitTemplate rabbitTemplate;
public
void
send()
{
String context =
"hi, fanout msg ";
-
`rabbitTemplate.convertAndSend("fanoutExchange",` `null, context); `Copy the code
}
}
- Create queue A, B, C consumers
@Component
@RabbitListener(queues =
"fanout.A")
@Slf4j
public
class
FanoutReceiverA
{
@RabbitHandler
public
void
process(String message,
Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG)
long tag)
{
-
`log.info("fanout Receiver A : {}"` `, message); `Copy the code
/ / ACK manually
try
{
// // message acknowledgement, which means that consumers acknowledge receipt of the current message and semantically indicate that consumers have successfully processed the current message.
-
`channel.basicAck(tag,` `false); `Copy the code
The second parameter indicates whether to reject multiple messages at a time. The third parameter indicates whether to rejoin the current message
// channel.basicNack(deliveryTag, false, false);
// Indicates that the consumer rejects the current message. The second parameter indicates whether the current message is re-enqueued
// channel.basicReject(deliveryTag,false);
}
catch
(IOException e)
{
-
`e.printStackTrace(); `Copy the code
}
}
}
The rest of B and C will not be repeated.
Unit testing
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;
import
zero.springboot.study.rabbitmq.direct.DirectSender;
import
zero.springboot.study.rabbitmq.fanout.FanoutSender;
import
zero.springboot.study.rabbitmq.simple.HelloSender;
import
zero.springboot.study.rabbitmq.topic.TopicSender;
@RunWith(SpringRunner.class)
@SpringBootTest(classes =
RabbitmqApplication.class)
public
class
RabbitmqApplicationTests
{
@Autowired
private
DirectSender directSender;
@Autowired
private
TopicSender topicSender;
@Autowired
private
FanoutSender fanoutSender;
@Autowired
private
HelloSender helloSender;
@Test
public
void
testDirect()
{
-
`directSender.send(); `Copy the code
}
@Test
public
void
topic1()
{
-
`topicSender.send1(); `Copy the code
}
@Test
public
void
topic2()
{
-
`topicSender.send2(); `Copy the code
}
@Test
public
void
testFanout()
{
-
`fanoutSender.send(); `Copy the code
}
@Test
public
void
testSimple()
{
-
`helloSender.send(); `Copy the code
}
}