Less nonsense, more dry goods:
integration
- Create an initialization project for springboot
Slightly (this can be done) - pom.xml is introduced as follows:
Note: I use 5.15.11 here, so the imported package should also be the latest 5.15.11
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> <version>2.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> <version>5.15.11</version> </dependency>
- application.yml is configured as follows:
spring: activemq: # mq communication address broker-url: tcp://39.96.70.45:61616 # Whether memory mode is enabled (that is, MQ is not installed, and an MQ instance is started at the same time when the project is started) in-memory: false pool: # Whether to open the connection pool? The connection pool using ActiveMQ needs to introduce ActiveMQ pool dependency # When true, the required a bean of type 'org.springframework.jms.core.JmsMessagingTemplate' that could not be found. Exception will be reported. At the end of the article, there is a solution. enabled: false # Idle connection expiration time, default is 30 seconds idle-timeout: 30000 # Connection pool maximum connections max-connections: 10
- The startup class is annotated as follows:
@Enable JMS: declare support for JMS annotations
@EnableJms @SpringCloudApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication .class, args); } }
- Establish activeMQ configuration class ActiveMqConfig.java
package com.jifang.netty.config; import org.apache.activemq.command.ActiveMQQueue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.jms.Queue; /** * ActiveMq To configure * * @author wangdy * @date 2020/2/7 15:15 */ @Configuration public class ActiveMqConfig { /** * Define the queue for messages */ @Bean public Queue queue() { return new ActiveMQQueue("chat-queue"); } }
- Production and sending messages
package com.jifang.netty.service.impl; import cn.hutool.json.JSONUtil; import com.jifang.netty.enums.MsgActionTypeEnum; import com.jifang.netty.enums.MsgTypeEnum; import com.jifang.netty.service.MessageService; import com.jifang.netty.service.MqMessageService; import com.jifang.netty.utils.JsonUtil; import com.jifang.netty.vo.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Service; import javax.jms.Queue; /** * @author wangdy * @date 2020/2/7 15:21 */ @Service public class MqMessageServiceImpl implements MqMessageService { @Autowired private Queue queue; @Autowired private JmsMessagingTemplate jmsMessagingTemplate; @Autowired private MessageService messageService; /** send message */ @Override public void sendMessage(String message) { // Method 1: add a message to the message queue jmsMessagingTemplate.convertAndSend(queue, message); // Method 2: in this way, you do not need to create a queue manually. The system will create a queue named testQueue by itself // jmsMessagingTemplate.convertAndSend("testQueue", message); } /** Consumer News */ @Override @JmsListener(destination = "chat-queue")// Use JmsListener to configure the queues consumers listen to, where message is the received message public void handleMessage(String message) { System.out.println("Received successfully: message" + message); } }
pit
The above setting pool.enabled=true will result in an error. By looking at the source code, it is found that because the version of springboot here uses 2.1.x, the default is @ conditionalonclass ({jmspoolconnectionfactory. Class, pooledobject. Class}). The source code is as follows:
JmsPoolConnectionFactory
@Configuration @ConditionalOnMissingBean(ConnectionFactory.class) class ActiveMQConnectionFactoryConfiguration { @Configuration @ConditionalOnClass(CachingConnectionFactory.class) @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "false", matchIfMissing = true) static class SimpleConnectionFactoryConfiguration { private final JmsProperties jmsProperties; private final ActiveMQProperties properties; private final List<ActiveMQConnectionFactoryCustomizer> connectionFactoryCustomizers; SimpleConnectionFactoryConfiguration(JmsProperties jmsProperties, ActiveMQProperties properties, ObjectProvider<ActiveMQConnectionFactoryCustomizer> connectionFactoryCustomizers) { this.jmsProperties = jmsProperties; this.properties = properties; this.connectionFactoryCustomizers = connectionFactoryCustomizers .orderedStream().collect(Collectors.toList()); } @Bean @ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "true", matchIfMissing = true) public CachingConnectionFactory cachingJmsConnectionFactory() { JmsProperties.Cache cacheProperties = this.jmsProperties.getCache(); CachingConnectionFactory connectionFactory = new CachingConnectionFactory( createConnectionFactory()); connectionFactory.setCacheConsumers(cacheProperties.isConsumers()); connectionFactory.setCacheProducers(cacheProperties.isProducers()); connectionFactory.setSessionCacheSize(cacheProperties.getSessionCacheSize()); return connectionFactory; } @Bean @ConditionalOnProperty(prefix = "spring.jms.cache", name = "enabled", havingValue = "false") public ActiveMQConnectionFactory jmsConnectionFactory() { return createConnectionFactory(); } private ActiveMQConnectionFactory createConnectionFactory() { return new ActiveMQConnectionFactoryFactory(this.properties, this.connectionFactoryCustomizers) .createConnectionFactory(ActiveMQConnectionFactory.class); } } // Note: import org.messaginghub.pooled.jms.JmsPoolConnectionFactory is used here; @Configuration @ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class }) static class PooledConnectionFactoryConfiguration { @Bean(destroyMethod = "stop") @ConditionalOnProperty(prefix = "spring.activemq.pool", name = "enabled", havingValue = "true", matchIfMissing = false) public JmsPoolConnectionFactory pooledJmsConnectionFactory( ActiveMQProperties properties, ObjectProvider<ActiveMQConnectionFactoryCustomizer> factoryCustomizers) { ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactoryFactory( properties, factoryCustomizers.orderedStream().collect(Collectors.toList())) .createConnectionFactory(ActiveMQConnectionFactory.class); return new JmsPoolConnectionFactoryFactory(properties.getPool()) .createPooledConnectionFactory(connectionFactory); } } }
So the solution:
Replace the original ActiveMQ pool with: pooled JMS
Note: many places on the Internet say that springboot2.0.x does not have this problem. I didn't study it in detail. You can see the source code if you are interested.
<!-- <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-pool</artifactId> <version>5.15.11</version> </dependency>--> <dependency> <groupId>org.messaginghub</groupId> <artifactId>pooled-jms</artifactId> </dependency>
test
Run the program, call the method to send the message, you can see the changes of the queue message, and the log printed by the console to receive the message.
As shown in the following figure: the number of queues in and out has been