ActiveMQ(一)入门
ActiveMQ(一)入门
官网: http://activemq.apache.org/
简介
ActiveMQ是Apache下的开源项目,非常流行的消息中间件,可以说要掌握消息中间件,需要从ActiveMQ开始,要掌握更加强大的RocketMQ,也需要ActiveMQ的基础。
特点:
1、支持多种语言编写客户端
2、对spring的支持,很容易和spring整合
3、支持多种传输协议:TCP,SSL,NIO,UDP等
4、支持AJAX
消息形式:
1、点对点(queue)
- 当一个消息生产者产生一个消息时,会把消息放入一个队列(Queue)中,然后消息消费者从Queue中读取消息,如果同时有多个消费者读取消息,ActiveMq保证消息只会被一个消费者读取到,消费者读取到消息之后需要向ActiveMq发送一条确认信息,确认消息已经被接收,此时,队列(Queue)中的消息出队,没被消费的消息会一直存在MQ队列中直到MQ被关闭
2、一对多(topic)
- 消息生产者(发布)将消息发布到 topic 中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到 topic 的消息会被所有订阅者消费。 当生产者发布消息,不管是否有消费者。都不会保存消息,所以一定要先有消息的消费者,后有消息的生产者。否则消息产生后会别立刻丢弃。启动项目的时候,先起消费者,再起生产者。
ActiveMQ下载安装
http://activemq.apache.org/download-archives
运行ActiveMQ(以Window为例)
解压缩apache-activemq-5.15.14-bin.zip
ActiveMQ目录结构:
bin: 下面存放的是ActiveMQ的启动脚本activemq.bat,注意分32、64位
conf: 里面是配置文件,重点关注的是activemq.xml、jetty.xml、jetty-realm.properties。在登录ActiveMQ Web控制台需要用户名、密码信息;在JMS CLIENT和ActiveMQ进行何种协议的连接、端口是什么等这些信息都在上面的配置文件中可以体现。
data: 目录下是ActiveMQ进行消息持久化存放的地方,默认采用的是kahadb,当然我们可以采用leveldb,或者采用JDBC存储到MySQL,或者干脆不使用持久化机制。
webapps: 注意ActiveMQ自带Jetty提供Web管控台
然后双击apache-activemq-5.15.14\bin\win64\activemq.bat 运行ActiveMQ程序。
ActiveMQ 默认采用 61616 端口提供消息服务,使用 8161 端口提供管理监控服务。
启动ActiveMQ以后,访问:http://localhost:8161/admin/ 默认帐号/密码:admin/admin
Linux安装:
springBoot整合ActiveMQ
1: maven依赖
<!--activemq-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
<!--activemq消息队列连接池,使用springboot2.0+及以下版本时候,maven配置依赖是:-->
<!--<dependency>-->
<!--<groupId>org.apache.activemq</groupId>-->
<!--<artifactId>activemq-pool</artifactId>-->
<!--</dependency>-->
<!--activemq消息队列连接池, 使用springboot2.1+时候,maven配置依赖是:-->
<dependency>
<groupId>org.messaginghub</groupId>
<artifactId>pooled-jms</artifactId>
</dependency>
2:yml配置
server:
port: 8081
servlet:
context-path: '/'
# activemq 配置
spring:
# jms:
#如果是点对点(queue),那么此处默认应该是false,如果发布订阅,那么一定设置为true,这种方式配置只能满足一种,如果要满足两种参考config下的配置
# pub-sub-domain: false
activemq:
# 中间件服务地址
broker-url: tcp://localhost:61616
user: admin
password: admin
# 信任所有的包
packages:
trust-all: true
#true 表示使用内置的MQ,false则连接服务器
in-memory: false
pool:
#true表示使用连接池;false时,每发送一条数据创建一个连接
enabled: true
#连接池最大连接数
max-connections: 10
#空闲的连接过期时间,默认为30秒
idle-timeout: 30S
application:
name: ActiveMQ-Provider
3:启动类添加 @EnableJms //启用消息队列
4、ActiveMqConfig配置
@Configuration
public class ActiveMqConfig {
@Value("${spring.activemq.broker-url}")
private String brokerUrl;
/**
* 点对点(queue)定义存放消息的队列,队列名字MyActiveMQQueue
* @return
*/
@Bean
public Queue queue() {
return new ActiveMQQueue("MyActiveMQQueue");
}
/**
* 一对多(topic)定义存放消息的队列,队列名字MyActiveMQTopic
*/
@Bean
public ActiveMQTopic activeMQTopic() {
return new ActiveMQTopic("MyActiveMQTopic");
}
@Bean
public ActiveMQConnectionFactory connectionFactory() {
return new ActiveMQConnectionFactory(brokerUrl);
}
/**
* 在yml中可以配置spring.jms.pub-sub-domain: false来确定使用哪种消息模式(点对点 或者 Topic),但是只能满足一种
* 这里我们使用配置文件配置可满足 点对点 和 Topic
* @param connectionFactory
* @return
*/
//Queue模式连接注入
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
bean.setConnectionFactory(connectionFactory);
return bean;
}
//Topic模式连接注入
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){
DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
//设置为发布订阅方式, 默认情况下使用的生产消费者方式
bean.setPubSubDomain(true);
bean.setConnectionFactory(connectionFactory);
return bean;
}
}
5、配置消息的生产者
/**
* @Author dw
* @ClassName MqProviderController
* @Description
* @Date 2021/1/23 23:18
* @Version 1.0
*/
@RestController
@RequestMapping("myMq")
public class MqProviderController {
//注入存放消息的点对点队列
@Autowired
private Queue queue;
//注入存放消息的Topic队列
@Autowired
private ActiveMQTopic activeMQTopic;
/**
* 注入springBoot封装的工具类
*/
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
/**
* 发送消息到点对点的消息队列中
* @param message
*/
@RequestMapping("sendToQueue")
public void sendToQueue(String message) {
//方法一:添加消息到消息队列
jmsMessagingTemplate.convertAndSend(queue, message);
//方法二:这种方式不需要手动创建queue,系统会自行创建名为test的队列
//jmsMessagingTemplate.convertAndSend("test", name);
}
/**
* 发送消息到Topic的消息队列中
* @param message
*/
@RequestMapping("sendToTopic")
public void sendToTopic(String message) {
jmsMessagingTemplate.convertAndSend(activeMQTopic, message);
}
}
6、配置消息的接受者
/**
* @Author dw
* @ClassName CustomerService
* @Description 消费者接受队列中的消息
* @Date 2021/1/23 23:23
* @Version 1.0
*/
@Component
public class CustomerService {
//############【如下配置了两个点对点消费者测试发现每个点对点消费者只能消费一次,如果多个点对点消费者,那么会平均接受到消息】########################
/**
* 【点对点消费者】
* 使用JmsListener配置消费者监听名为MyActiveMQQueue的队列,其中message是接收到的消息
* @param message
* @return
*/
@JmsListener(destination = "MyActiveMQQueue", containerFactory = "jmsListenerContainerQueue")
// SendTo 会将此方法返回的数据, 写入到 OutQueue 中去.实现双向绑定,在消费者接收到信息后给生产者返回一个内容,告诉生产者已经接收到消息
@SendTo("outQueue")
public String handleQueueMessage(String message) {
System.out.println("方法一成功接受message" + message);
return "方法一成功接受message" + message;
}
/**
* 【点对点消费者2】
* 使用JmsListener配置消费者监听名为MyActiveMQQueue的队列,其中message是接收到的消息
* @param message
* @return
*/
@JmsListener(destination = "MyActiveMQQueue", containerFactory = "jmsListenerContainerQueue")
// SendTo 会将此方法返回的数据, 写入到 OutQueue 中去.实现双向绑定,在消费者接收到信息后给生产者返回一个内容,告诉生产者已经接收到消息
@SendTo("outQueue")
public String handleQueueMessage2(String message) {
System.out.println("方法2成功接受message==" + message);
return "方法2成功接受message==" + message;
}
/**
* 【Topic消费者1】
* 使用JmsListener配置消费者监听名为MyActiveMQTopic的队列,其中message是接收到的消息
* @param message
* @return
*/
@JmsListener(destination = "MyActiveMQTopic", containerFactory = "jmsListenerContainerTopic")
public void handleTopicMessage(String message) {
System.out.println("成功接受message==" + message);
}
/**
* 【Topic消费者2】
* 使用JmsListener配置消费者监听名为MyActiveMQTopic的队列,其中message是接收到的消息
* @param message
* @return
*/
@JmsListener(destination = "MyActiveMQTopic", containerFactory = "jmsListenerContainerTopic")
public void handleTopicMessage2(String message) {
System.out.println("成功接受message==" + message);
}
}
github源码地址:https://github.com/dengwei-java/springBoot-activeMq
Spring-JMS官方文档:https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#jms