消息中间件之ActiveMQ(三):SpringBoot整合ActiveMQ

废话少说,上干货:

整合

  1. 建立一个springboot的初始化项目
    略(这个可以会)
  2. pom.xml引入如下包:
    注意:我这里用的是5.15.11,所以引入的包也是要最新的5.15.11
        <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>
  1. application.yml加入如下配置:
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
  1. 启动类加上如下注解:
    @EnableJms:声明对 JMS 注解的支持
@EnableJms
@SpringCloudApplication
public class DemoApplication {
	    public static void main(String[] args) {
        SpringApplication.run(DemoApplication .class, args);
    }
}
  1. 建立activeMQ配置类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配置
 *
 * @author wangdy
 * @date 2020/2/7 15:15
 */
@Configuration
public class ActiveMqConfig {
	/**
	 * 定义存放消息的队列
	 */
	@Bean
	public Queue queue() {
		return new ActiveMQQueue("chat-queue");
	}
}
  1. 生产和发送消息
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>

测试

运行程序,调用方法发送消息,可以看到队列消息的变化情况,和控制台打印的接受消息的日志。
如下图:入队列数和出队列数都有了
消息中间件之ActiveMQ(三):SpringBoot整合ActiveMQ_第1张图片

你可能感兴趣的:(Java,activemq,springboot整合,连接池异常)