Personal notes of Spring Boot from 0 to learn 8 - Message RabbitMQ

1. Brief introduction

In most applications, message service middleware can be used to improve system asynchronous communication and expand decoupling capabilities

  • Two important concepts in message services:
    message broker and destination. When the message sender sends a message, it will be taken over by the message agent, which guarantees that the message is delivered to the specified destination.
  • Message queues mainly have two forms of destinations:
    queue: point-to-point message communication (point-to-point)
    topic: publish/subscribe message communication

Two, installation

Open the virtual machine, run Linux, open SmarTTY, enter docker pull rabbitmq:3-management, and download
Insert picture description here
docker run -d -p 5672:5672 -p 15672:15672 --name myrabbitmq d55229deb03e

  • -d run in the background
  • It has two more ports, so just -p twice
  • --Name is myrabbitmq
  • The back pile is the ID of my rabbitmq, checked with docker images

Insert picture description here
Then enter in the browser http://192.168.0.102:15672/, of course, this IP is my SmarTTY connected to Linux, what is my own, see the docker I wrote before

Go in, login account password, the default is guest
Insert picture description here

Three, RabbitMQ

The producer publishes the message to the Exchange, the message finally arrives in the queue and is received by the consumer, and the Binding determines which queue the exchange's message should be sent to.
When Exchange distributes messages, there are differences according to different distribution strategies. There are currently four types: direct, fanout, topic, and headers .

1. Topic Exchanger

Insert picture description here
The topic switch distributes the routing key attribute of the message through pattern matching, and matches the routing key with a pattern. At this time, the queue needs to be bound to a pattern. It divides the string of routing key and binding key into words, which are separated by dots. It also recognizes two wildcard characters: the symbol "#" and the symbol "*". #Match 0 or more words, *Match one word.

2. Test it first

Insert picture description here
Diagram of the video tutorial

Follow the video tutorial to do the test, I don’t know why this is happening. . . Do a few exchanges, and then bind the queue,

3. Create 3exchange

Insert picture description here
The main
ones are these two boxes. That Durability: option, Duiable means persistence. After opening it next time, the exchange is still there, and the other one means it disappears after closing.
Insert picture description here

4. Add 4 queues

Insert picture description here
Insert picture description here

5. Binding queues to all 3 exchanges

Insert picture description here
Choose which one to tie, click in
Insert picture description here

  • But ah, it’s a bit different in exchange.topic, because exchange.topic is not bound to all, the route name needs to be changed, as explained later

See the picture at the beginning, exchange.direct and exchange.fanout are bound to the 4 queues, exchange.topic is atguigu.#bound (atguigu as the head) and *.newsbound (the end of news)
Insert picture description here
exchange.direct and exchange.fanout are both bound Into this

Then, exchange.topic:
Insert picture description here

  • what does this mean? Said later

6. Test

1)`exchange.direct

For example, when we exchange.directsend an atguigu request in China, only the atguigu queue can accept it, because the exchange uses direct and the route name is atguigu . The name of the route is specified to send information. Other queues have different names and cannot be received.

  • If the type is direct, specify who to send to
    Insert picture description here
    Insert picture description here

2)exchange.fanout

The type is fanoutthat no matter what is specified, the queue in exchange.fanout will receive it. For example, send a request in exchange.fanout
Insert picture description here
Insert picture description here

  • Only atguigu’s ready is 2 because the above example is atguigu request

3)exchange.topic

Sending in exchange.topic hello.news, it seems that this does not exist, but look carefully
Insert picture description here
because the topictype is used, so the technology can be fuzzy matching. (This should be understood as binding, because the queue is written at the beginning, and then the exchange has some binding with each queue) Then the atguigu.news queue accepts *.news and can accept it. The gulixueyuan.news queue accepts *.news and can also accept it.

Insert picture description here
Insert picture description here

Four, project testing

Insert picture description here

1. Configuration

application.yml:

spring:
  rabbitmq:
    host: 192.168.0.102
    username: guest
    password: guest

2. Send a message

Can be automatically imported with @Autowired

@SpringBootTest
class SpringBootAmqpApplicationTests {
    
    

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
    
    
//        rabbitTemplate.send(String exchange, String routeKey, Message var3)
//        Message(byte[] body, MessageProperties messageProperties)  Message为一个数组和一个头消息

//        convertAndSend(String var1, String var2, Object var3)
//        其中,Object var3默认为消息体,会自动序列化发送过去的
        Map<String,Object> map = new HashMap<>();
        map.put("msg","这是一个信息");
        rabbitTemplate.convertAndSend("exchange.direct","atguigu.news",map);

    }
  • send(String exchange, String routeKey, Message var3): Exchange name, route name, and message. The message consists of message content and message header
  • convertAndSend(String var1, String var2, Object var3), The send is too troublesome, there is this method, Object var3 will be automatically converted to serialization to send messages

Insert picture description here
Insert picture description here

3. Accept the message

    @Test
    public void test(){
    
    
        Message receive = rabbitTemplate.receive("atguigu.news");
        System.out.println(receive);
    }

(Body:’{msg=这是一个信息}’ MessageProperties [headers={}, contentType=application/x-java-serialized-object, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=true, receivedExchange=exchange.direct, receivedRoutingKey=atguigu.news, deliveryTag=1, messageCount=0])

Insert picture description here

4. The sent message becomes JSON type

As you can see, both sending and receiving are serialized and deserialized. It is better to convert to JSON, just add a configuration class.

@Configuration
public class MyAMQPConfig {
    
    

	@Bean
    public MessageConverter messageConverter(){
    
    
//        把消息转化为JSON格式
        return new Jackson2JsonMessageConverter();
    }
}

Send
Insert picture description here
again and accept again

class org.springframework.amqp.core.Message
(Body:’{“msg”:“这是一个信息”}’ MessageProperties [headers={ ContentTypeId=java.lang.Object, KeyTypeId=java.lang.Object, TypeId=java.util.HashMap}, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=true, receivedExchange=exchange.direct, receivedRoutingKey=atguigu.news, deliveryTag=1, messageCount=0])

This exchange.directis how it is sent to , and the same is true for other types of exchanges.

5. Automatically accept messages

In order to show better, we create a class with the toString method written in it,

public class Person {
    
    
    String name;
    int age;
    //xxx
}

Create a Service layer to automatically receive messages from a certain queue

@Service
public class PersonService {
    
    

    @RabbitListener(queues = "atguigu.news")
    public void receive(Person person){
    
    
        System.out.println("收到消息"+person);
    }
}

  • @RabbitListener: You can put multiple queues to automatically accept the things in the queue. If the parameter is used, write Person, that is, if the sent JSON is Person, it can be received, if not, it is the Message type

Turn on the annotation of automatically accepting messages in the main program

@EnableRabbit
@SpringBootApplication
public class SpringBootAmqpApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(SpringBootAmqpApplication.class, args);
    }

}

  • @EnableRabbit: Turn on the comment of automatically accepting messages

Test class


@SpringBootTest
class SpringBootAmqpApplicationTests {
    
    

    @Autowired
    RabbitTemplate rabbitTemplate;

    @Test
    void contextLoads() {
    
    
        rabbitTemplate.convertAndSend("exchange.direct","atguigu.news",new Person("小强",22));

    }

A message of a custom class is sent here

Received the message Person{name='Xiaoqiang', age=22}

Because it accepts how to output something, it is written by the service layer

6. If it is automatically accepted as Message type

A method of the service layer

    @RabbitListener(queues = "atguigu")
    public void receive2(Message message){
    
    
        System.out.println(message.getBody());
        System.out.println(message.getMessageProperties());
    }

Still send the Person object, but the queue is atguigu, and the above also accepts atguigu, but the acceptance type is Message

    @Test
    void contextLoads() {
    
    
        rabbitTemplate.convertAndSend("exchange.direct","atguigu",new Person("小强",22));

    }

[B@5e012317
MessageProperties [headers={ TypeId=com.qiang.Bean.Person}, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=exchange.direct, receivedRoutingKey=atguigu, deliveryTag=1, consumerTag=amq.ctag-Ws2bRFLJ6Y3d7JXvrKVCTQ, consumerQueue=atguigu]

Five, code replaces interface operations

The creation of exchange, queue, and binding that we did before can all be implemented in Java.
Continue to do it in the test class

@Test
public void create(){
    
    

    amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange"));

    amqpAdmin.declareQueue(new Queue("amqpadmin.queue",true));

    amqpAdmin.declareBinding(new Binding("amqpadmin.queue",Binding.DestinationType.QUEUE,"amqpadmin.exchange","amqp.test",null));

}
  • DirectExchange: There is at most this container DirectExchange(String name, boolean durable, boolean autoDelete, Map<String, Object> arguments), but there is also a container, just write the first one. Durable is whether it is persistent, and whether boolean autoDelete is automatically deleted, Map does not know. . .
  • Queuethe same
  • BindingBinding(String destination, Binding.DestinationType destinationType, String exchange, String routingKey, @Nullable Map<String, Object> arguments)
    • destination: destination, which queue to bind to
    • Binding.DestinationType destinationType: Just follow along. . .
    • exchange: which exchange
    • routingKey: What is the routing name?
    • @Nullable Map: I don't know. . . .

The code so far: spring-boot-AMQP

Guess you like

Origin blog.csdn.net/yi742891270/article/details/107767914