Simple integration of Springboot + ActiveMQ

message queue

Not surprisingly, there are many comrades who need to use the message queue before they have studied it thoroughly (such as me), but at least after studying a series of rhetoric on Wikipedia and Baidu Encyclopedia, I almost have an understanding, so I won’t go into details here. I believe that those who can come here basically have their own understanding of message queues.

How to understand message queue

How to understand? You have eaten at McDonald’s. It can be compared to the producer who orders the food. The speed of your order is faster than the speed of delivery. Therefore, when many people order the food, the news of the order will enter the system. This point The list of completed meals can be understood as a message queue, and the caterer is equivalent to a consumer, who reads a piece of order information from the menu, and then completes the order according to the demand. This order information disappears, which can be compared to consumers from A message is consumed in the queue, which should be the same reason.

horizontal comparison

I have accurately queried ActiveMQ, and I don’t have much interest in doing horizontal comparisons. Just like when I read the "Guide to Buying Huawei Mobile Phones", if I insist on a horizontal comparison of Huawei, Samsung, Apple, Nokia, and PHS, I will only feel that you are embarrassed. . If you want to know the difference between different technologies of message queuing, please move to: >>> cnblog is here for fun: MQ selection <<<

accomplish

For the project, I did not use the existing project to create a new Springboot basic program.
My project structure is as follows for easy understanding:
insert image description here

Install activeMQ

I am using a Linux server here. If you are a Windows server, there is good news that this blogger has launched an in-depth cooperation with Baidu. If you have any questions, you can go directly to Baidu, hahaha. >>> ActiveMQ under Windows <<<

Under Linux:

# 下载源码安装包
wget https://ftp.tsukuba.wide.ad.jp/software/apache//activemq/5.16.3/apache-activemq-5.16.3-bin.tar.gz
# 解压
tar -xzvf apache-activemq-5.16.3-bin.tar.gz
# 启动
cd ./apache-activemq-5.16.3/bin
./activemq start

You can understand other activemq commands by yourself. If you are a cloud server and need to connect remotely, the activemq service is allowed by default, but the background web management interface is not available. You need to find conf/jetty.xml before starting, and put 127.0 in it .0.1 is changed to 0.0.0.0, the location is about line 120:
insert image description here
then the browser accesses, the port of the background management system does not recognize 8161, the API port is 61616, here access 127.0.0.1:8161, you need to enter the default user name and password admin/admin , followed by self-modification, and then click manage activemq broker to enter the management interface:
insert image description here

insert image description here
The installation is now complete.

package import

It is necessary to import related packages in pom, here imports the related springboot starter dependency packages:

<!--    activeMQ起步依赖    -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!--    activeMQ连接池    -->
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-pool</artifactId>
    <version>5.15.0</version>
</dependency>

Because it is a web program requirement, the web startup dependency also needs to be imported, and some other packages can be imported according to your own needs.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>RELEASE</version>
    <scope>compile</scope>
</dependency>

Message queue configuration

Then configure the MQ in the configuration file. Personal preference is to use the yaml configuration file.

server: 
    port: 8898
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616 
    user: admin
    password: admin
    non-blocking-redelivery: false # 是否在回滚回滚消息之前停止消息传递。这意味着当启用此命令时,消息顺序不会被保留。
    send-timeout: 0 # 等待消息发送响应的时间。设置为0等待永远。
    in-memory: true
    queue-name: examQueue  # queue队列的名称
    topic-name: examTopic  # topic队列的名称
    pool:
      enabled: true # 启用连接池
      max-connections: 100 # 最大连接数
      idle-timeout: 30000 # 空闲的连接过期时间,默认为30秒

In the above configuration, queue-name and topic-name are not the attributes in the default configuration item in the activeMQ startup dependency, but for convenience, a custom MQ configuration is established, and these two attributes are defined in it, which are used to represent The names of the two queues can be left undefined. They can be hard-coded or global static variables, depending on the requirements.

Next is the activeMQ configuration class, which defines listeners in two modes:

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.jms.core.JmsMessagingTemplate;
import javax.jms.ConnectionFactory;
import javax.jms.Queue;
import javax.jms.Topic;

@Configuration
//@ConfigurationProperties(prefix = "spring.activemq")
public class MQConfig {
    
    
    @Value("${spring.activemq.broker-url}")
    private String brokerUrl;

    @Value("${spring.activemq.user}")
    private String username;

    @Value("${spring.activemq.password}")
    private String password;
	
    @Value("${spring.activemq.queue-name}")
    private String queueName;

    @Value("${spring.activemq.topic-name}")
    private String topicName;

    @Bean(name = "queue")
    public Queue queue() {
    
    
        return new ActiveMQQueue(queueName);
    }

    @Bean(name = "topic")
    public Topic topic() {
    
    
        return new ActiveMQTopic(topicName);
    }

    @Bean
    public ConnectionFactory connectionFactory(){
    
    
        return new ActiveMQConnectionFactory(username, password, brokerUrl);
    }

    @Bean
    public JmsMessagingTemplate jmsMessageTemplate(){
    
    
        return new JmsMessagingTemplate(connectionFactory());
    }

    // 在Queue模式中,对消息的监听需要对containerFactory进行配置
    @Bean("queueListener")
    public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(ConnectionFactory connectionFactory){
    
    
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(false);
        return factory;
    }

    //在Topic模式中,对消息的监听需要对containerFactory进行配置
    @Bean("topicListener")
    public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(ConnectionFactory connectionFactory){
    
    
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true);
        return factory;
    }
}

producer

Then there is the producer. The producer is mainly used to generate messages (send messages). Here are the producer message sending interfaces in two modes:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jms.Destination;
import javax.jms.Queue;
import javax.jms.Topic;

@RestController
@RequestMapping("/mq")
public class ProducerController {
    
    
    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    @PostMapping("/queue/send")
    public String sendQueue(@RequestBody String str) {
    
    
        this.sendMessage(this.queue, str);
        return "success";
    }

    @PostMapping("/topic/send")
    public String sendTopic(@RequestBody String str) {
    
    
        this.sendMessage(this.topic, str);
        return "success";
    }

    // 发送消息,destination是发送到的队列,message是待发送的消息
    private void sendMessage(Destination destination, final String message){
    
    
        jmsMessagingTemplate.convertAndSend(destination, message);
    }

}

consumer

Then there is the consumer. After the producer sends the message to the queue, because of the existence of the listener, the consumer can listen to the new message, and then consume the message from a specific queue to complete the work:

queue consumer:

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class QueueConsumerListener {
    
    
    //queue模式的消费者
    @JmsListener(destination="${spring.activemq.queue-name}", containerFactory="queueListener")
    public void readActiveQueue(String message) throws InterruptedException {
    
    
        Thread.sleep(3000); //模拟时间复杂度较高的工作
        System.out.println("queue接受到:" + message);
    }
}

topic consumer:

package com.javafeng.mqdemo.consumer;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class TopicConsumerListener {
    
    
    //topic模式的消费者
    @JmsListener(destination="${spring.activemq.topic-name}", containerFactory="topicListener")
    public void readActiveQueue(String message) {
    
    
        Thread.sleep(3000); //模拟时间复杂度较高的工作
        System.out.println("topic接受到:" + message);
    }
}

other configuration

It needs to be in the entry program, allow custom configuration, and start the message queue. I also configured the basic package location of the scanning component here:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.jms.annotation.EnableJms;

@SpringBootApplication(scanBasePackages = {
    
    "com.javafeng.mqdemo"})
@EnableConfigurationProperties // 允许自定义配置,也就是让MQConfig生效
@EnableJms //启动消息队列
public class MqdemoApplication {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(MqdemoApplication.class, args);
    }
}

test

Running the project, it can be concluded from the above that the access path of the message produced by the queue producer is /mq/queue/send, and the access path of the topic producer is /mq/topic/send. Next, we will test: topic is the same, here
insert image description here
insert image description here
I I won't repeat it any more, and I'll finish spreading flowers.

References and citations:

Blog Garden-Fengzhiyuxie-SpringBoot integrates ActiveMq:
https://www.cnblogs.com/yufeng218/p/11509486.html

Guess you like

Origin blog.csdn.net/u012751272/article/details/119923733