springboot integrates RabbitMQ messaging middleware

Keywords: Java RabbitMQ Spring Boot

Springboot integrates RabbitMQ

Learning reference website

Installing RabbitMQ

1. Install Erlang language pack

https://www.erlang.org/downloads [official website download address]

2. Install rabbitMq

https://www.rabbitmq.com/download.html

The installation path cannot have Chinese, otherwise the path cannot be found

3. Restart rabbitmq program

net stop RabbitMQ && net start RabbitMQ

The login account and password of the page are guest

Service port: 5672
Interface port: 15672

4. Problems encountered while configuring custom serialization:

solve
rabbitmq cannot set messageconverter. An error is reported when setting Jackson2JsonMessageConverter. The problem is solved.

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageConverter' defined in class path resource [com/cyberbim/modbusdriver/config/MyAMQPconfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.amqp.support.converter.MessageConverter]: Factory method 'messageConverter' threw exception; nested exception is java.lang.NoClassDefFoundError: com/fasterxml/jackson/databind/ObjectMapper

This error is the lack of dependency

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.3</version>
</dependency>

Just add this!

5. Understand the process of pushing and receiving a message


The yellow circle is the message push service, which pushes the message to the middle box, that is, the rabbitMq server, and then processes the data into the column through various relationships such as switches and queues in the server. Finally, the consumers in the blue circle on the right get the corresponding monitored message.

There are three types of switches in common use. Because consumers obtain information from the queue and the queue is bound to the switch (general), the corresponding message push / receive modes also include the following:

Direct Exchange direct attached switch

The direct connected switch delivers the message to the corresponding queue according to the routing key carried by the message.

Generally, a queue is bound to a direct connected switch, and a routing key is given at the same time.
Then, when a message carries a route value of X and the message is sent to the switch through the producer, the switch will find a queue with a binding value of X according to the route value X.

Fanout Exchange fan switch

Fan switch, this switch has no routing key concept, even if you bind the routing key, it is ignored. After receiving the message, the switch will directly forward it to all queues bound to it.

Topic Exchange theme switch

In fact, the flow of the theme switch is similar to that of the direct connection switch, but its feature is that there are rules between its routing keys and binding keys.
Briefly introduce the following rules:

*(asterisk) used to indicate a word (must appear)
*#(pound sign) used to represent any number (zero or more) of words

The generic binding key is bound to the queue, for example

The binding key of queue Q1 is. TT. The binding key of queue Q2 is TT#
If the routing key carried by a message is A.TT.B, queue Q1 will receive it;
If the routing key carried by a message is TT.AA.BB, queue Q2 will receive it;

The theme switch is very powerful. Why is it so inflated?
When the binding key of a queue is "#" (pound sign), the queue will ignore the message routing key and receive all messages.
When the two special characters * (asterisk) and # (pound sign) do not appear in the binding key, the subject switch has the behavior of the direct connected switch.
Therefore, the theme switch realizes the functions of fan-shaped switch and direct connected switch.

Integrated use of RabbitMq

1. Add consolidation dependency

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

2. Configure application.properties

#Basic configuration of rabitmq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest

#Configure the virtual host path of rabbitmq
spring.rabbitmq.virtual-host=/

3. Create switches and queues based on API

One switch and two queues were created.

  //   1. Integrate rabbitmq and springboot API custom components based on API
    @Test
    public void test() {

//        1. Define the switch machine of fanout type
        amqpAdmin.declareExchange(new FanoutExchange("fanout_exchange"));

//        2. Define two default persistence queues to process email and sms respectively
        amqpAdmin.declareQueue(new Queue("fanout_queue_email"));
        amqpAdmin.declareQueue(new Queue("fanout_queue_sms"));

//        3. Bind the queue to the switch respectively
        amqpAdmin.declareBinding(new Binding("fanout_queue_email", Binding.DestinationType.QUEUE, "fanout_exchange", "", null));
        amqpAdmin.declareBinding(new Binding("fanout_queue_sms", Binding.DestinationType.QUEUE, "fanout_exchange", "", null));
    }

Run this test class and find that the rabbitMq page is added successfully.

Add information to the message queue.

  //   2. Inject information into the message converter
    //   If you start directly in this way, an error will be reported because the stored information is not serialized and the converter does not support it. You can use the jdk's own serialization interface or customize the serialization configuration class
    @Test
    public void testUser() {
        User user = new User();
        user.setName("codeL");
        user.setAge("22");
       // Convert and send=============================

        /*api based*/
        rabbitTemplate.convertAndSend("fanout_exchange", "", user);}

Run this test class and find an error

Because there is no serialization, we need to configure a serialization to be added to the configuration class of rabbitMq.

package com.codel.rabbitmq.config;

import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Rabbitmq configuration based on configuration class
 *
 * @author codel
 * @date 2021/09/22
 */
@Configuration
public class RabbitMqConfig {
    //    Custom message converter serialization
    @Bean
    public MessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }
 }

Once the configuration is complete, restart

Configure consumer

package com.codel.rabbitmq.service;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

@Service
public class RabbitMqService {

    /*Listen to the queue named fanout through annotations_ queue_ Email message*/

    @RabbitListener(queues = "fanout_queue_email")
    public void psubConsumerEmail(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("API Message received by mailbox service:" + s);
    }

    @RabbitListener(queues = "fanout_queue_sms")
    public void psubConsumerSms(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("API Method: message received from short message service:" + s);
    }}
    

When you restart the project, you will find that consumers will automatically get data from the message queue.

4. Method based on configuration class

Configure new switches and queues in the RabbitMqConfig configuration class

 /*      2.This is to configure the middleware based on the configuration class,
        That is, define the switch and message queue and bind them by configuring the class
*/

    //    1. Define fan out switch of fan out type
    @Bean
    public Exchange fanout_exchange2() {
        return ExchangeBuilder.fanoutExchange("fanout_exchange2").build();
    }

    //2. Define two message queues
    @Bean
    public Queue fanout_queue1() {
        return new Queue("fanout_queue1");
    }

    @Bean
    public Queue fanout_queue2() {
        return new Queue("fanout_queue2");
    }

    //    3. Bind the two message queues to the switch
    @Bean
    public Binding binding1() {
//        routing is empty because there is no route
        return BindingBuilder.bind(fanout_queue1()).to(fanout_exchange2()).with("").noargs();
    }

    @Bean
    public Binding binding2() {
        return BindingBuilder.bind(fanout_queue2()).to(fanout_exchange2()).with("").noargs();
    }

Add test data user in the test class and transfer the data to fanout_exchange2 is in the exchange.

 //Add a configuration class to create test data for the switch
        User user2 = new User();
        user2.setName("codeL2");
        user2.setAge("223"
         /*Configuration based classes*/
        rabbitTemplate.convertAndSend("fanout_exchange2", "", user2);
//

After running rabbitmq in the background, it is found that the switch, queue and data page are passed in.

Then create a consumer and take out the data in the queue

  //    Testing: configuration class based approach
    @RabbitListener(queues = "fanout_queue1")
    public void psubConsumerEmail2(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("Configuration class=Received message from mailbox service of:" + s);
    }

    @RabbitListener(queues = "fanout_queue2")
    public void psubConsumerSms2(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("Configuration class=Message received by short message service:" + s);
    }

Then restart the application. The results are as follows:

5. Annotation based construction

Configure switches and queues in the RabbitMqService class

 /* 3. Create components based on annotations*/
    @RabbitListener(bindings = @QueueBinding(value = @Queue("fanout_queue3"), exchange = @Exchange(value = "fanout_exchange3", type = "fanout")))
    public void psubConsumerEmailAno(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("annotation==Create component mailbox service receiving information:" + s);

    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue("fanout_queue4"), exchange = @Exchange(value = "fanout_exchange3", type = "fanout")))
    public void psubConsumerSmsAno(Message message) {
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("annotation==Create component information service and receive information:" + s);
    }

Add test data user in the test class and transfer the data to fanout_exchange3 is in the exchange.

//Create test data based on annotations
        User user3 = new User();
        user3.setName("codeL3");
        user3.setAge("2233");
          /* Annotation based */
        rabbitTemplate.convertAndSend("fanout_exchange3", "", user3);

The result is the same as above.

6.routing mode

        routing Mode, the routing key cannot be empty
  User user4 = new User();
        user4.setName("codeL4");
        user4.setAge("22334");

//        Routing mode consumer
       rabbitTemplate.convertAndSend("routing_exchange1", "error_routing_key1", user4);
//
//

7.topics wildcard mode

Configure switches and queues in Wildcard mode and custom rules

  //    ==================================topics wildcard mode
    @RabbitListener(bindings = @QueueBinding(value = @Queue("topic_queue_email"), exchange = @Exchange(value = "topic_exchange1", type = "topic"), key = "info.#.email.#"))

    public void topicConsumerEmail(String message) {
        System.out.println("topics=Receive mailbox subscription demand processing information:" + message);

    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue("topic_queue_sms"), exchange = @Exchange(value = "topic_exchange1", type = "topic"), key = "info.#.sms.#"))

    public void topicConsumerSms(String message) {
        System.out.println("topics=Received SMS subscription demand processing information:" + message);

    }

Messages that deliver data to specified switches and queues and producers.

//        //topics wildcard mode
//        1. Only send mail subscription user information
        rabbitTemplate.convertAndSend("topic_exchange1", "info.email", "topics send email message");
//        2. Only subscribed to SMS messages
        rabbitTemplate.convertAndSend("topic_exchange1", "info.sms", "topics send  sms message");
        
//        To comment out the above two, the following cancellation information can be successfully output
//          3. Both subscribed
      rabbitTemplate.convertAndSend("topic_exchange1", "info.email.sms", "topics send email and sms message");

    }

Posted by Rykin on Wed, 22 Sep 2021 07:25:18 -0700