ActiveMQ的地位
ActiveMQ是Apache开源组织开源的一款老牌消息队列,用纯java编写,有多种通信协议。性能各方面可能不及RabbitMQ和kafuka等热门消息队列,但还是有一些公司会在技术选型上选择该产品。
ActiveMQ的安装与使用(以5.15.5版本为例)
- Linux部署:
下载:wget http://archive.apache.org/dist/activemq/5.15.5/apache-activemq-5.15.5-bin.tar.gz
解压:tar -zxvf apache-activemq-5.15.5-bin.tar.gz
启动服务:bin/activemq start
查看启动状态:bin/activemq status
停止服务:bin/activemq stop
- windows部署:
下载:http://archive.apache.org/dist/activemq/5.15.5/apache-activemq-5.15.5-bin.tar.gz
下载后解压,到bin目录里面启动即可。
- docker容器部署(需先安装docker)
镜像库里搜索镜像:docker search activemq
下载镜像:docker pull webcenter/activemq
运行镜像:docker run -d -p 61616:61616 -p 8161:8161 --name activemq -d docker.io/webcenter/activemq
启动后http://101.133.140.191:8161/进入还原页面,http://101.133.140.191:8161/admin/进入管理员页面(需要登录:username:admin password:admin)。在页面中开源管理和监控对应的队列。
ActiveMQ和SpringBoot的江湖之路
早期ActiveMQ和普通JAVA WEB整合需要下载对应的包,操控API即可。在这个SpringBoot四处可见的时代ActiveMQ和SpringBoot的整合只能说是伸手就来。
- 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.15.0</version>
</dependency>
- application.yml基本配置
spring:
activemq:
broker-url: tcp://101.133.140.191:61616
in-memory: true
packages:
trust-all: true
user: admin
password: admin
pool:
enabled: true
max-connections: 30
# jms: #若需要同时支持Queue和Topic需做额外配置
# pub-sub-domain: false #默认false = Queue true = Topic
注:yml配置默认是开启Queue模式队列的,若需支持Topic模式则需要将spring.jms.pub-sub-domain属性设置为true。需要特别注意单纯在yml配置是不可以同时兼容Queue和Topic模式的,需特殊配置。
- 基本配置
/**
* 本类用于做AciveMQ的基本配置
*/
@Configuration
public class MQConfig {
/**
* 5.*版本认为队列里面应该传普通数据类型的数据,不应该传自定义的对象类型数据
* 因为官方认为对象类是不安全的,所以若想传对象类型需要在实现Serializable
* 接口的同时做如下配置。
*
*
* 设置连接工厂的序列化集合和重新发送策略
* @param url
* @return
*/
@Bean("defaultActiveMQConnectionFactory")
public ActiveMQConnectionFactory factory(@Value("${spring.activemq.broker-url}") String url){
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(url);
// 设置信任序列化包集合
List<String> models = new ArrayList<>();
models.add("java.lang");
models.add("java.util");
models.add("cn.zhangpf.interfaceManage.utils");
models.add("cn.zhangpf.interfaceManage.entity");
factory.setTrustedPackages(models);
// 设置处理机制
RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
redeliveryPolicy.setMaximumRedeliveries(0); // 消息处理失败重新处理次数
factory.setRedeliveryPolicy(redeliveryPolicy);
return factory;
}
/**
* 同时支持topic与queue
* @param activeMQConnectionFactory
* @return
*/
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(@Qualifier("defaultActiveMQConnectionFactory") ConnectionFactory activeMQConnectionFactory) {
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setPubSubDomain(true);
bean.setConnectionFactory(activeMQConnectionFactory);
return bean;
}
//普通队列
@Bean("activeQueue")
@Primary
public Queue getQueue(){
ActiveMQQueue activeMQQueue = new ActiveMQQueue("active.queue");
return activeMQQueue;
}
//广播队列
@Bean("activeTopic")
public Topic getTioic(){
ActiveMQTopic activeMQTopic = new ActiveMQTopic("active.topic");
return activeMQTopic;
}
//延迟队列
@Bean("delayedQueue")
public Queue getDelayedQueue(){
ActiveMQQueue activeMQQueue = new ActiveMQQueue("delayed.queue");
return activeMQQueue;
}
}
- 生产普通消息和延迟消息
@Component
public class ActiveMQUtil<T extends Serializable> {
private static JmsMessagingTemplate jmsMessagingTemplate;
@Autowired
private ActiveMQUtil(JmsMessagingTemplate jmsMessagingTemplate){
this.jmsMessagingTemplate = jmsMessagingTemplate;
}
/**
* 往队列里发送消息
* @param destination
* @param data
*/
public static void sendMessage(Destination destination, MQModel data){
jmsMessagingTemplate.convertAndSend(destination,data);
}
public static void sendMessage(Destination destination, String data){
jmsMessagingTemplate.convertAndSend(destination,data);
}
/**
* 往队列里发送延时消息
* @param destination 队列
* @param data 数据
* @param time 延迟时间
* @throws UnsupportedEncodingException
* @throws JMSException
* @throws InterruptedException
*/
public static void sendDelayedMessage(Destination destination, MQModel data, long time) throws UnsupportedEncodingException, JMSException, InterruptedException {
MessageProducer producer = null;
Session session=null;
Connection connection=null;
try {
connection = jmsMessagingTemplate.getConnectionFactory().createConnection();
connection.start();
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(destination);
producer.setDeliveryMode(JmsProperties.DeliveryMode.PERSISTENT.getValue());
ObjectMessage message = session.createObjectMessage(data);
//设置延迟时间
message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
producer.send(message);
session.commit();
}catch (Exception e){
e.printStackTrace();
}
finally {
if(session != null){
session.close();
}
if(producer != null){
producer.close();
}
if(connection!=null){
connection.close();
}
}
}
public static<T extends Serializable> void sendDelayedMessage(Destination destination, T data, long time) throws UnsupportedEncodingException, JMSException, InterruptedException {
MessageProducer producer = null;
Session session=null;
Connection connection=null;
try {
connection = jmsMessagingTemplate.getConnectionFactory().createConnection();
connection.start();
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
producer = session.createProducer(destination);
producer.setDeliveryMode(JmsProperties.DeliveryMode.PERSISTENT.getValue());
ObjectMessage message = session.createObjectMessage(data);
//设置延迟时间
message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
producer.send(message);
session.commit();
}catch (Exception e){
e.printStackTrace();
}
finally {
if(session != null){
session.close();
}
if(producer != null){
producer.close();
}
if(connection!=null){
connection.close();
}
}
}
}
- 消费普通消息和延迟消息
@Component
public class QueueMessage {
/**
* 监听延时队列
* @param entity
*/
@JmsListener(destination = "delayed.queue")
public void getMessage54(ComAppMsgEntity entity) {
List<ComAppMsgEntity> appMsgEntities = Stream.of(entity).collect(Collectors.toList());
System.out.println(entity);
System.out.println(new Date());
}
/**
* 监听普通队列
* @param entity
*/
@JmsListener(destination = "active.queue")
public void getMessage3(String entity) {
System.out.println("收到消息:"+entity);
}
/**
* 监听Topic
* @param entity
*/
@JmsListener(destination = "active.topic",containerFactory = "jmsListenerContainerTopic")
public void getMessage1(MQModel model) throws UnsupportedEncodingException {
System.out.println(new Date());
System.out.println("订阅者1:"+model );
}
}
- 测试
@Autowired
Queue queue;
@Autowired
@Qualifier("delayedQueue")
Queue delayedQueue;
@Autowired
Topic topic;
@Test
public void sendMessageByQueue(){
//普通队列
ActiveMQUtil.sendMessage(queue, "msg");
//普通订阅消息
ActiveMQUtil.sendMessage(topic, "msg");
//延时队列
ActiveMQUtil.sendDelayedMessage(delayedQueue, comAppMsgEntity, 11000L);
}