ActiveMQ消息队列是Apache出品的,能力强劲的开源消息总线,他完全支持jms1.1和j2ee1.4规范
ActiveMQ解决了服务之间的耦合,使用他可以增加系统并发处理量
ActiveMQ使用的标准的生产者和消费者模型(生产者和消费者可以跨平台、跨系统)有中间平台
ActiveMQ有两种数据结构
Queue队列 生产者生产了一个消息,只能有一个消费者进行消费
Topic话题 生产者生产了一个消息,可以有多个消费者进行消费
使用java开发ActiveMQ只需要导入activemq-all-5.14.0-jar就可以了
使用ActiveMQ的好处:
1、系统整合:同构/异构系统整合,分布式环境中
2、降低模块间耦合:比如AB两个系统,A性能瓶颈或宕机、
系统差不干扰B
3、实现异步:1.推消息 2.削峰请求
4、数据同步:web应用->缓存,搜索,db
ActiveMQ整合spring实现生产者的步骤
第一步:
需要配置web.xml,在applicationContext.xml中导入相应的jar包
spring-context
activemq-all
spring-jms
第二步:需要在applicationContext.xml中配置
<!-- 扫描包 -->
<context:component-scan base-package="包名路径" />
<!-- ActiveMQ 连接工厂 -->
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<!-- 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码-->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://localhost:61616" userName="admin" password="admin" />
<!-- Spring Caching连接工厂 -->
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<!-- 同上,同理 -->
<!-- <constructor-arg ref="amqConnectionFactory" /> -->
<!-- Session缓存数量 -->
<property name="sessionCacheSize" value="100" />
</bean>
<!-- Spring JmsTemplate 的消息生产者 start-->
<!-- 定义JmsTemplate的Queue类型 -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<constructor-arg ref="connectionFactory" />
<!-- 非pub/sub模型(发布/订阅),即队列模式 queue -->
<property name="pubSubDomain" value="false" />
</bean>
<!-- 定义JmsTemplate的Topic类型 -->
<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<constructor-arg ref="connectionFactory" />
<!-- pub/sub模型(发布/订阅) topic -->
<property name="pubSubDomain" value="true" />
</bean>
基于Queue模式的生产者类,队列模式
@Service
public class QueueSender {
// 注入jmsTemplate
@Autowired
@Qualifier("jmsQueueTemplate")
private JmsTemplate jmsTemplate;
public void send(String queueName, final String message) {
jmsTemplate.send(queueName, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
MapMessage mapMessage = session.createMapMessage();
mapMessage.setString("title", "东风快递");
mapMessage.setString("Email", model.getEmail());
return mapMessage;
}
});
}
}
基于Topic模式的生产者类,发布/订阅模式
@Service
public class TopicSender {
// 注入jmsTemplate
@Autowired
@Qualifier("jmsTopicTemplate")
private JmsTemplate jmsTemplate;
public void send(String topicName, final String message) {
jmsTemplate.send(topicName, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(message);
}
});
}
}
ActiveMQ整合spring实现消费者的步骤
第二步:需要在applicationContext.xml中配置 <!-- 扫描包 -->
<context:component-scan base-package="包名路径" />
<!-- ActiveMQ 连接工厂 -->
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<!-- 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码-->
<amq:connectionFactory id="amqConnectionFactory"
brokerURL="tcp://localhost:61616" userName="admin" password="admin" />
<!-- Spring Caching连接工厂 -->
<!-- Spring用于管理真正的ConnectionFactory的ConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<!-- 目标ConnectionFactory对应真实的可以产生JMS Connection的ConnectionFactory -->
<property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
<!-- 同上,同理 -->
<!-- <constructor-arg ref="amqConnectionFactory" /> -->
<!-- Session缓存数量 -->
<property name="sessionCacheSize" value="100" />
</bean>
<!-- 消息消费者 start-->
<!-- 定义Queue监听器 -->
<jms:listener-container destination-type="queue" container-type="default"
connection-factory="connectionFactory" acknowledge="auto">
<!-- 默认注册bean名称,应该是类名首字母小写 -->
<jms:listener destination="spring_queue" ref="queueConsumer2"/>
<jms:listener destination="spring_queue" ref="queueConsumer3"/>
</jms:listener-container>
<!-- 定义Topic监听器 -->
<jms:listener-container destination-type="topic" container-type="default"
connection-factory="connectionFactory" acknowledge="auto">
<jms:listener destination="spring_topic" ref="topicConsumer1"/>
<jms:listener destination="spring_topic" ref="topicConsumer2"/>
</jms:listener-container>
<!-- 消息消费者 end -->
对应Queue模式的消费者类QueueConsumer1、QueueConsumer2
@Service("queueConsumer2")
//这里与<jms:listener destination="spring_queue" ref="queueConsumer2"/>的ref对应,默认名为类名首字母小写,即ref="queueConsumer1"
public class QueueConsumer1 implements MessageListener {
public void onMessage(Message message) {
MapMessage mapMessage = (MapMessage) message;
try {
System.out.println("消费者获取消息:" + mapMessage.getTitle());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
对应Topic模式的消费者类TopicConsumer1、TopicConsumer2
@Service
public class TopicConsumer1 implements MessageListener {
public void onMessage(Message message) {
TextMessage textMessage = (TextMessage) message;
try {
System.out.println("消费者TopicConsumer1获取消息:" + textMessage.getText());
} catch (JMSException e) {
e.printStackTrace();
}
}
}
生产者消费者开发注意点
1)中间平台brokerURL,生产者和消费者配置要一样,连接同一个平台
2)destination生产者和消费者配置要一样
3)Queue的生产者与Queue的消费者对应、Topic的生产者与Topic的消费者对应
4)生产者和消费者配置对比
生产者
a.包扫描,扫描到生产者那个类
b.mq连接工厂
c.spring封装mq连接工厂
d.提供模板,关联spring封装mq连接工厂
<property name="pubSubDomain" value="false" /> false队列模式queue true订阅模式topic
消费者
a.包扫描,扫描到消费者那个类
b.mq连接工厂
c.spring封装mq连接工厂
d.配置监听 关联spring封装mq连接工厂
<jms:listener destination="与生产者发起的消息名字对应" ref="与消费者类上的@Service的名字对应"/>