废话少说,上干货:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-activemqartifactId>
<version>2.2.4.RELEASEversion>
dependency>
<dependency>
<groupId>org.apache.activemqgroupId>
<artifactId>activemq-poolartifactId>
<version>5.15.11version>
dependency>
spring:
activemq:
# mq通信地址
broker-url: tcp://39.96.70.45:61616
# 是否启用内存模式(就是不安装MQ,项目启动时同时启动一个MQ实例)
in-memory: false
pool:
# 是否开启连接池,使用ActiveMQ的连接池需要引入activemq-pool依赖
# true时候会报required a bean of type 'org.springframework.jms.core.JmsMessagingTemplate' that could not be found.异常,文章最后有处理方案。
enabled: false
# 空闲的连接过期时间,默认为30秒
idle-timeout: 30000
# 连接池最大连接数
max-connections: 10
@EnableJms
@SpringCloudApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication .class, args);
}
}
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配置
*
* @author wangdy
* @date 2020/2/7 15:15
*/
@Configuration
public class ActiveMqConfig {
/**
* 定义存放消息的队列
*/
@Bean
public Queue queue() {
return new ActiveMQQueue("chat-queue");
}
}
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;
/**
发送消息
*/
@Override
public void sendMessage(String message) {
// 方法1:添加消息到消息队列
jmsMessagingTemplate.convertAndSend(queue, message);
// 方法2:这种方式不需要手动创建queue,系统会自行创建名为testQueue的队列
// jmsMessagingTemplate.convertAndSend("testQueue", message);
}
/**
消费消息
*/
@Override
@JmsListener(destination = "chat-queue")// 使用JmsListener配置消费者监听的队列,其中message是接收到的消息
public void handleMessage(String message) {
System.out.println("成功接收:message" + message);
}
}
上面的设置pool.enabled=true启动会报错,通过查看源码,发现由于我这里springboot的版本用的2.1.x,默认使用的是 @ConditionalOnClass({ JmsPoolConnectionFactory.class, PooledObject.class }),源码如下:
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);
}
}
// 注意:此处用的是import org.messaginghub.pooled.jms.JmsPoolConnectionFactory;
@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);
}
}
}
所以解决方案:
替换原来的activemq-pool 改用:pooled-jms
注意:网上很多地方说springboot2.0.x没有此问题。我没细研究,感兴趣的可以看下源码。
<dependency>
<groupId>org.messaginghubgroupId>
<artifactId>pooled-jmsartifactId>
dependency>
运行程序,调用方法发送消息,可以看到队列消息的变化情况,和控制台打印的接受消息的日志。
如下图:入队列数和出队列数都有了