activemq是基于jetty服务容器的,可在源码中发现。
1.maven依赖jar
<!-- 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.8.0</version> </dependency>
注意:这里依赖没有直接引入activemq-all 的依赖,因为activemq-all 会依赖slf4j 日志jar容易和 单独引进的slf4的日志jar冲突,如下(我是单独引进slf4j日志的)
<!-- 日志 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.12</version> </dependency>2.生产者 (这里指定的是订阅与发布模式)
<!-- 配置JMS服务提供商 ActiveMQ --> <bean id="activeMQConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <!-- 连接ActiveMQ服务地址 --> <property name="brokerURL" value="tcp://mqserver:61616"/> <property name="userName" value="admin"/> <property name="password" value="admin"/> </bean> <!-- 配置ActiveMQ的连接池工厂 --> <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <property name="targetConnectionFactory" ref="activeMQConnectionFactory"/> <property name="sessionCacheSize" value="100"/> </bean> <!-- 点对点队列 --> <bean id="defaultQueueDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg index="0" value="cn.zyy.tender.admin.queue.default"/> </bean> <!-- 一对多队列 --> <bean id="defaultTopicDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg index="0" value="cn.zyy.tender.admin.topic.default"/> </bean> <!-- spring管理JMS(ActiveMQ) --> <bean id="singleConnectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory"> <property name="targetConnectionFactory" ref="connectionFactory"/> </bean> <!-- spring管理jsmTemplate用于发送消息值ActiveMQ服务 --> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <!-- 指定ActiveMQ连接工厂 --> <property name="connectionFactory" ref="singleConnectionFactory"/> <!-- 指定消息队列名称 --> <property name="defaultDestinationName" value="cn.zyy.tender.admin.topic.default"/> <!--<property name="defaultDestination" ref="defaultTopicDestination"/>--> <!-- 指定为消息的订阅与发布模式 --> <property name="pubSubDomain" value="false"/> </bean>这里配置消息队列名称有两种方式,1:直接在jsmTemplate中指点默认目标名称(即:设置defaultDestionationName属性)
2通过defaultDestionation属性引进(就是上面的一对多队列)·
3.消费者配置
订阅模式配置:
<!-- 连接工厂 --> <bean id="activeMqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="${AvtiveMQ.brokerURL}"/> <property name="useAsyncSend" value="true"/> </bean> <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <property name="targetConnectionFactory" ref="activeMqConnectionFactory"/> <property name="sessionCacheSize" value="100"/> </bean> <!-- 点对点队列 --> <!-- <bean id="defaultQueueDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg index="0" value="cn.zyy.tender.admin.queue.default"/> </bean>--> <!-- 一对多队列 --> <bean id="defaultTopicDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg index="0" value="cn.zyy.tender.admin.topic.default"/> </bean> <!-- 生产者 --> <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="pubSubDomain" value="false"/> </bean> <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <!-- 指定为消息的订阅与发布模式 --> <property name="pubSubDomain" value="true"/> </bean> <!-- 消费者 --> <bean id="defaultMessageQueueListener" class="com.zyy.tender.admin.jms.DefaultMessageQueueListener"/> <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <!-- 指定队列名称 --> <property name="destination" ref="defaultTopicDestination"/> <!-- 注入自定监听器,处理队列中消息 --> <property name="messageListener" ref="defaultMessageQueueListener"/> <property name="sessionTransacted" value="true"/> <!--<property name="concurrency" value="4-10"/>--> <!-- 指定为消息的订阅与发布模式 --> <property name="pubSubDomain" value="true"/> </bean>
点对点配置:
<!-- 连接工厂 --> <bean id="activeMqConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="${AvtiveMQ.brokerURL}"/> <property name="useAsyncSend" value="true"/> </bean> <bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory"> <property name="targetConnectionFactory" ref="activeMqConnectionFactory"/> <property name="sessionCacheSize" value="100"/> </bean> <!-- 点对点队列 --> <bean id="defaultQueueDestination" class="org.apache.activemq.command.ActiveMQQueue"> <constructor-arg index="0" value="cn.zyy.tender.admin.queue.default"/> </bean> <!-- 一对多队列 --> <!--<bean id="defaultTopicDestination" class="org.apache.activemq.command.ActiveMQTopic"> <constructor-arg index="0" value="cn.zyy.tender.admin.topic.default"/> </bean>--> <!-- 生产者 --> <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="pubSubDomain" value="false"/> </bean> <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <!-- 指定为消息的订阅与发布模式 --> <property name="pubSubDomain" value="true"/> </bean> <!-- 消费者 --> <bean id="defaultMessageQueueListener" class="com.zyy.tender.admin.jms.DefaultMessageQueueListener"/> <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref="connectionFactory"/> <!-- 指定队列名称 --> <property name="destination" ref="defaultQueueDestination"/> <!-- 注入自定监听器,处理队列中消息 --> <property name="messageListener" ref="defaultMessageQueueListener"/> <property name="sessionTransacted" value="true"/> <!--<property name="concurrency" value="4-10"/>--> <!-- 指定为消息的订阅与发布模式 这里的订阅模式可由生产者(优先级高)指定--> <property name="pubSubDomain" value="false"/> </bean>
4. 生产者发送消息
jmsTemplate是交给spring容器,然后注入到spring的bean中,这里是注入到了serviceImpl中
@Resource private JmsTemplate jmsTemplate;
@Override public int isShowByPrimaryKeys(String ids) { Integer count=0; String[] split = ids.split("-"); for (final String idStr: split) { if (StringUtils.isBlank(idStr)) { continue; } jmsTemplate.send(new MessageCreator() { @Override public Message createMessage(Session session) throws JMSException { TextMessage textMessage = session.createTextMessage(idStr); return textMessage; } }); zyyTenderNewsMapper.isShowByPrimaryKey(Integer.parseInt(idStr)); count++; } return count; }
5.消费者的消息监听器
将这个消息监听器交个spring来管理,然后注入到activeMQ的 jmsContainer中(见上面消费者的配置),可以消息监听器中注入service接口来处理相应的业务需求。
/** * MQ消费者 */ public class DefaultMessageQueueListener implements MessageListener { private static Logger _log = LoggerFactory.getLogger(DefaultMessageQueueListener.class); @Autowired ThreadPoolTaskExecutor threadPoolTaskExecutor; public void onMessage(final Message message) { // 使用线程池多线程处理 threadPoolTaskExecutor.execute(new Runnable() { public void run() { if (message instanceof TextMessage) { TextMessage textMessage = (TextMessage) message; try { _log.info("消费消息:{}", textMessage.getText()); System.out.println("消费消息:"+textMessage.getText()); } catch (Exception e){ e.printStackTrace(); } } } }); } }
6.消息模式
点对点:一个消息只能被一个消费者消费一次。
订阅模式:一个消息可以被多个消费者消费一次。