简单介绍下activeMQ中的概念:
1. 获得JMS connection factory. 通过我们提供特定环境的连接信息来构造factory。
2. 利用factory构造JMS connection
3. 启动connection
4. 通过connection创建JMS session.
5. 指定JMS destination.
6. 创建JMS producer或者创建JMS message并提供destination.
7. 创建JMS consumer或注册JMS message listener.
8. 发送和接收JMS message.
9. 关闭所有JMS资源,包括connection, session, producer, consumer等。
现在项目一般都是spring 管理的。直接上代买了,用activeMQ 来是 spring-jms,直接上代码了
对应的 activemq.xml 中的配置:
这是为了生成不同的死信队列:前缀是DLQ.
<!--添加方式:修改activemq.xml 在policyEntry节点同级修改或添加队列配置如下 -->
<policyEntry queue=">" producerFlowControl="true" memoryLimit="50mb">
<deadLetterStrategy>
<individualDeadLetterStrategy queuePrefix="DLQ."
useQueueForQueueMessages="true" />
</deadLetterStrategy>
</policyEntry>
maven 配置:
<!--activemq -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>5.13.3</version>
</dependency>
然后配置一个jms.xml,引入到 applicationContent 中。
activeMQ主要有2种模式 点对点 和 订阅模式。暂时实现点对点模式。点对点简单说就是,一个生产者对应一个消费者。
生产者配置:需要实现 jmsTemplate 然后定义 Destination。然后将消息发送到Destination 中去。
消费者配置:消费者,是通过监听,监听destination 。然后获取消息的。那么它必须知道监听哪里(destination),对应的监听处理以及知道具体的实现方式。
这里配置了重发策略,同时监听了死信队列中的数据
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!--jms.xml 配置 -->
<!--这里设置各个消息队列的重发机制-->
<bean id="redeliveryPolicyMap" class="org.apache.activemq.broker.region.policy.RedeliveryPolicyMap">
<property name="redeliveryPolicyEntries">
<list>
<ref bean="bizRedeliveryPolicy"/>
</list>
</property>
</bean>
<bean id="bizRedeliveryPolicy" class="org.apache.activemq.RedeliveryPolicy">
<!--重发次数 延时、延时系数、延时指数开关、目标(重发等待时间1s, 2s, 4s, 8s)-->
<property name="maximumRedeliveries" value="3"/>
<property name="redeliveryDelay" value="1000"/>
<property name="backOffMultiplier" value="2"/>
<property name="useExponentialBackOff" value="true"/>
<property name="destination" ref="queueDestination"/>
</bean>
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供-->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<!-- 这里定义重试策略,注意:只有持久化的才会重试-->
<property name="redeliveryPolicyMap" ref="redeliveryPolicyMap"/>
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory">
<property name="connectionFactory" ref="targetConnectionFactory"/>
<property name="maxConnections" value="10"/>
</bean>
<bean id="connectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="pooledConnectionFactory"/>
</bean>
<!-- Spring提供的JMS工具类,它可以进行消息发送、接收等 -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
<property name="connectionFactory" ref="connectionFactory"/>
<!-- 使 deliveryMode, priority, timeToLive设置生效-->
<property name="explicitQosEnabled" value="true" />
<!-- 持久化 如果设置为非持久化MQ服务器重启后MQ中的数据会丢失-->
<property name="deliveryPersistent" value="true"/>
<!--这里注意:如果不开启事务,消息在异常的情况下是不会重试的-->
<property name="sessionTransacted" value="true"/>
</bean>
<!--这个是队列目的地,点对点的-->
<bean id="queueDestination" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>HelloQueue</value>
</constructor-arg>
</bean>
<!-- 死信队列配置 -->
<bean id="DLQHelloQueue" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg>
<value>DLQ.HelloQueue</value>
</constructor-arg>
</bean>
<!-- 消息监听器 -->
<bean id="consumerMessageListener" class="mrw.spring.activeMq.ConsumerMessageListener"/>
<bean id="consumerDLQMessageListener" class="mrw.spring.activeMq.ConsumerDLQMessageListener"/>
<!-- 消息监听容器 -->
<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="queueDestination" />
<property name="messageListener" ref="consumerMessageListener" />
<!--这里注意:如果不开启事务,消息在异常的情况下是不会重试的-->
<property name="sessionTransacted" value="true"/>
<property name="concurrentConsumers" value="1"/>
</bean>
<bean id="jmsDLQContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="connectionFactory" />
<property name="destination" ref="DLQHelloQueue" />
<property name="messageListener" ref="consumerDLQMessageListener" />
<!--这里注意:如果不开启事务,消息在异常的情况下是不会重试的-->
<property name="sessionTransacted" value="true"/>
<property name="concurrentConsumers" value="1"/>
</bean>
</beans>
对应的发送:
@Resource
private JmsTemplate jmsTemplate;
public void sendMessage(Destination destination, final String message) {
System.out.println("---------------生产者发了一个消息:" + message);
jmsTemplate.send(destination, new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage(message);
}
});
}
对应的监听:
注意:实现对应的监听有:MessageListener 和 SessionAwareMessageListener(参数中有session)
简单说如果:ack 机制是 事务模式。如果监听中 出现异常,不捕获。那么这条消息会重发。如果捕获了,那么这条消息算是确认了。其他模式还没试过。
public class ConsumerMessageListener implements MessageListener {
public void onMessage(Message message) {
try {
if(message instanceof ObjectMessage){
ObjectMessage objectMessage = (ObjectMessage) message;
FilterCommentAudit filterCommentAudit =(FilterCommentAudit) objectMessage.getObject();
}else if(message instanceof TextMessage){
TextMessage textMsg = (TextMessage) message;
}
}catch (JMSException e){
e.printStackTrace();
}
}
}