Detailed explanation of SpringBoot integration ActiveMQ examples

In the process of project development, we often encounter similar business scenarios: users apply for cash withdrawal, the background performs accounting processing, sends cash withdrawal SMS, and calls bank payment channels.

image

In this process, it is time-consuming to call the three-party channel (text message or bank channel), and the accounting processing may also be processed by a special accounting system. Then, in order to improve concurrency and corresponding speed, the following three operations can be processed asynchronously. This uses the message queue.

Message queuing middleware is an important component in a distributed system. It mainly solves the problems of application coupling, asynchronous messaging, traffic cutting, etc. It achieves high performance, high availability, scalability and eventual consistency architecture, which is indispensable for large distributed systems. Middleware.

The more common message queues on the market are: ActiveMQ, RabbitMQ, ZeroMQ, Kafka, MetaMQ, RocketMQ.

ActiveMQ is specifically integrated in the Spring Boot starter, so in this article we will talk about the integration of ActiveMQ.

JMS specification

JMS is the Java Message Service (Java Message Service) application program interface. It is a message-oriented middleware (MOM) API in the Java platform, used to send messages between two applications or in a distributed system for asynchronous Communication. Java Message Service is an API that has nothing to do with a specific platform, and most MOM providers support JMS.

The message mechanism of JMS has two models, one is the form of queue (Point to Point—) messages sent can only be consumed by one consumer; the other is the subscription (Topic) mode, which can be subscribed by multiple subscribers. Both will receive the same message.

ActiveMQ is one of the implementations of JMS.

ActiveMQ introduction

ActiveMQ is an open source implementation of a message middleware based on the JMS (Java Message Servie) specification. The design goal of ActiveMQ is to provide a standard, message-oriented, application-integrated message communication middleware that can span multiple languages ​​and multiple systems. .

It provides high availability, excellent performance, scalability, stability and security for messaging in enterprise applications.

ActiveMQ implements the JMS specification and provides a lot of additional features on top of it. ActiveMQ supports message sending in two modes: queue and subscription.

The data transmission process of AcitveMQ is as follows:

image

Two types of ActiveMQ messaging:

(1) Point-to-point transmission, that is, one producer corresponds to one consumer, and the producer pushes data to break. The data is stored in a queue of break, and when the consumer receives the data in the queue.

(2) Transmission based on the publish/subscribe model, that is, according to the subscription topic to receive the corresponding data, a producer can push data to multiple consumers, which is similar to the implementation of the MQTT protocol.

The two types of message delivery are different. Point-to-point transmission consumers can receive the data pushed by the producer before the connection, while consumers based on the publish/subscribe mode of transmission can only receive the data pushed by the producer after the connection.

Spring Boot integrates ActiveMQ

Spring Boot specifically provides spring-boot-starter-activemq for ActiveMQ to support ActiveMQ's automatic integration configuration in Spring Boot. On this basis, we can easily integrate and use.

Create a project and introduce dependencies

Create a standard Spring Boot project and introduce the following dependencies in the project:

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

If you don't need web or other related processing at this time, just introduce the dependency. If you use pool, you need to add the following dependencies to the pom:

<dependency>
     <groupId>org.apache.activemq</groupId>
     <artifactId>activemq-pool</artifactId>
</dependency>

Configuration file

Add the following configuration in application.properties:

# 基于内存的ActiveMQ
spring.activemq.in-memory=true
# 不使用连接池,如果使用连接池还需在pom中添加activemq-pool的依赖
spring.activemq.pool.enabled=false

# 独立安装的ActiveMQ
#spring.activemq.broker-url=tcp://127.0.0.1:61616
#spring.activemq.user=admin
#spring.activemq.password=admin

There are two sets of configurations in the above configuration. Spring Boot supports ActiveMQ based on memory and ActiveMQ based on independent installation. The memory-based form of normal requests is used for the convenience of testing, and the form based on independent installation is really used in the production environment. In order to explain the functions and facilitate testing, the memory-based form is adopted here.

Queue mode example

First, let's implement the implementation based on the queue (Queue) form. Two classes ActiveMQQueue and JmsMessagingTemplate need to be used here. The former is implemented by ActiveMQ's interface to javax.jms.Queue. The latter provides Spring with a tool class for sending messages, which is combined with Queue to send messages.

JmsMessagingTemplate has been instantiated by default, just use it directly. ActiveMQQueue requires us to instantiate and pass in the name of the message queue.

@Configuration
public class MyMqConfig {

	@Bean
	public Queue queue() {
		return new ActiveMQQueue("sms.queue");
	}
}

The very conventional instantiation operations in Spring Boot will not be repeated. When the ActiveMQQueue is instantiated, our queue is created, and the corresponding producers and consumers are created below.

The corresponding code for the producer is as follows:

@Component
public class Producer {

	@Resource
	private JmsMessagingTemplate jmsMessagingTemplate;

	@Resource
	private Queue queue;

	public void sendMsg(String msg) {
		System.out.println("发送消息内容 :" + msg);
		this.jmsMessagingTemplate.convertAndSend(this.queue, msg);
	}

}

JmsMessagingTemplate and Queue are used here. As mentioned above, these two classes have been initialized. The configuration for consumers is as follows:

@Component
public class Consumer {

	@JmsListener(destination = "sms.queue")
	public void receiveMsg(String text) {
		System.out.println("接收到消息 : "+text);
	}
}

Spring provides annotated listener endpoints: use @JmsListener. Use the annotated method of the @JmsListener managed bean to subscribe to it. In Java 8, @JmsListener is a repeatable annotation that can associate multiple JMS destinations to the same method. In Java 6 and 7, you can use the @JmsListeners annotation.

The destination specifies the name of the monitored message queue as "sms.queue". The execution of this method will be triggered when a message is sent in the queue sms.queue, and text is the message content.

The above completed the queue initialization, producer and consumer code writing, the following unit test to verify whether the message can be sent and processed correctly.

@RunWith(SpringRunner.class)
@SpringBootTest
public class ActiveMqTests {

	@Autowired
	private Producer producer;

	@Test
	public void sendSimpleQueueMessage() {
		this.producer.sendMsg("提现200.00元");
	}
}

Perform unit test, you will find the following information is printed in the log:

发送消息内容 :提现200.00元
接收到消息 : 提现200.00元

Explain that the message can be sent and received normally. If it is based on the memory model, the "javax.jms.JMSException: peer (vm://localhost#1) stopped." exception log will be printed when the unit test is executed. This is an Info level error and a bug of ActiveMQ.

Subscription model example

Messages sent by broadcast can be received by multiple consumers. Here we add broadcast messages on the original basis.

First of all, when Spring Boot integrates ActiveMQ, only one of queue or broadcast is supported by default, which is specified by the configuration item spring.jms.pub-sub-domain. True is broadcast mode, false is queue mode, and queue mode is supported by default.

To use the broadcast mode at this time, you need to add the following configuration to the configuration file:

spring.jms.pub-sub-domain=true

It should be noted that the queue mode cannot work normally at this time.

Then add in MyMqConfig:

@Bean
public Topic topic() {
	return new ActiveMQTopic("sms.topic");
}

ActiveMQTopic is created here, and the name of the topic is specified as sms.topic.

The following code is added to Producer:

@Resource
private Topic topic;

public void sendTopic(String msg) {
	System.out.println("发送Topic消息内容 :"+msg);
	this.jmsMessagingTemplate.convertAndSend(this.topic, msg);
}

In order to demonstrate multiple broadcast receivers, add two consumers in Comsumer:

@JmsListener(destination = "sms.topic")
public void receiveTopic1(String text) {
	System.out.println("receiveTopic1接收到Topic消息 : " + text);
}

@JmsListener(destination = "sms.topic")
public void receiveTopic2(String text) {
	System.out.println("receiveTopic2接收到Topic消息 : " + text);
}

The following tests are added to the unit test class:

@Test
public void sendSimpleTopicMessage() {
	this.producer.sendTopic("提现200.00元");
}

At this point, execute the unit test, you can see the following log information:

发送Topic消息内容 :提现200.00元
receiveTopic2接收到Topic消息 : 提现200.00元
receiveTopic1接收到Topic消息 : 提现200.00元

The message was sent successfully.

Support two forms at the same time

In the above example, either the queue mode or the broadcast mode is supported. If you need to support both in the production environment, then you need to customize the JmsListenerContainerFactory instance. Of course, if Spring Boot's default configuration cannot meet your needs, you can also customize this class. This is just one of the scenarios.

Basic configuration and usage steps: Create a custom JmsListenerContainerFactory instance through DefaultJmsListenerContainerFactory, and reference it through the containerFactory attribute in the @JmsListener annotation.

Add the following configuration to the MyMqConfig configuration class:

@Bean("queueListenerFactory")
public JmsListenerContainerFactory<?> queueListenerFactory(ConnectionFactory connectionFactory) {
	DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
	factory.setConnectionFactory(connectionFactory);
	factory.setPubSubDomain(false);
	return factory;
}

@Bean("topicListenerFactory")
public JmsListenerContainerFactory<?> topicListenerFactory(ConnectionFactory connectionFactory) {
	DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
	factory.setConnectionFactory(connectionFactory);
	//设置为发布订阅方式, 默认情况下使用的生产消费者方式
	factory.setPubSubDomain(true);
	return factory;
}

Here are instantiated factory classes based on queues and subscriptions. Then add the containerFactory attribute to the corresponding consumer method. The sample code is as follows:

@JmsListener(destination = "sms.queue", containerFactory = "queueListenerFactory")
public void receiveMsg(String text) {
	System.out.println("接收到消息 : " + text);
}

@JmsListener(destination = "sms.topic", containerFactory = "topicListenerFactory")
public void receiveTopic1(String text) {
	System.out.println("receiveTopic1接收到Topic消息 : " + text);
}

The two types of messages were executed separately, and they were both normal and mutually beneficial. At the same time, the item spring.jms.pub-sub-domain in the configuration file is also invalid at this time.

something else

1. The port number of activeMq is 61616;

2. To use topic, you need to configure spring.jms.pub-sub-domain=true;

3. If there is no consumer in the queue, the information will be stored in the queue;

4. When the sent message is an object, the object needs to be serialized; when the consumer receives the object information, it needs to use ObjectMessage for conversion;

5. Using the containerFactory property in the JmsListener annotation, you can configure the spring.jms.pub-sub property to receive queque and topic at the same time;

6. The queue is a peer-to-peer model; tipic is a publish-subscribe model;

7. The name of the message queue (sms.queue and sms.topic) in the example can be set as configuration properties as needed;

Source address: https://github.com/secbr/springboot-learn/tree/master/springboot-activemq
link to the original text: " SpringBoot integrated ActiveMQ example detailed "

Reference article:

https://www.cnblogs.com/xiguadadage/p/11217604.html

https://blog.csdn.net/bihansheng2010/article/details/87190645

Fine SpringBoot 2.x video tutorial

"Spring Boot 2.x Video Tutorial Family Bucket" , a boutique Spring Boot 2.x video tutorial, to create the most complete set of Spring Boot 2.x video tutorials.


New Vision of Procedure

The public account " New Vision of Program ", a platform that allows you to simultaneously improve your soft power and hard technology, providing massive amounts of data

WeChat Official Account: New Vision of Program

Guess you like

Origin blog.csdn.net/wo541075754/article/details/108068496