分布式延时队列(Enhanced JMS Scheduler in ActiveMQ)

来源:互联网 发布:九亿娱乐域名 编辑:程序博客网 时间:2024/06/04 19:16

需求:

1.24小时超时取消订单

2.日程管理,在设置的日程时间之前10分钟提醒,日程时间支持修改

消息队列配置,支持配置多个消息队列,不同消息队列使用不同的destination

biz-activemq.xml

<?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:aop="http://www.springframework.org/schema/aop"xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"xmlns:jee="http://www.springframework.org/schema/jee" xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"default-autowire="byName"><!-- 如业务需要扩展请按照 1 2 3 4 步骤进行配置 --><!-- 公共部分 配置JMS连接工厂 --><bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"><property name="brokerURL" value="${activemq.brokerURL}" /></bean><!-- 1.发送消息的目的地(队列) --><bean id="orderTimeoutQueue" class="org.apache.activemq.command.ActiveMQQueue"><!-- 设置消息队列的名字 --><constructor-arg index="0" value="orderTimeoutQueue" /></bean><!-- 2. 配置Jms模板 --><bean id="orderTimeoutJmsTemplate" class="org.springframework.jms.core.JmsTemplate"><property name="connectionFactory" ref="connectionFactory" /><property name="defaultDestination" ref="orderTimeoutQueue" /></bean><!-- 3. 配置JMS监听器  --><bean id="orderTimeoutMessageListener" class="com.yk.appointment.delayedqueue.OrderTimeoutMessageListener"></bean><!-- 4. 注册JMS监听器到spring容器 --><bean id="orderTimeoutListenerContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer"><property name="connectionFactory" ref="connectionFactory" /><property name="destination" ref="orderTimeoutQueue" /><property name="messageListener" ref="orderTimeoutMessageListener" /></bean></beans>

发送消息  OrderTimeoutProducer.java
/** * 文件名:ProducerService.java * 创建日期:  2017年10月9日 * 作者:      ningfangming * 版权所有(C) 2016-2017  * 保留所有权利. */package com.yk.appointment.delayedqueue;/** * 功能描述: * @author ningfangming 2017年10月9日 */import javax.annotation.Resource;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ScheduledMessage;import org.springframework.jms.core.JmsTemplate;import org.springframework.jms.core.MessageCreator;import org.springframework.stereotype.Service;@Servicepublic class OrderTimeoutProducer {@Resource(name = "orderTimeoutJmsTemplate")private JmsTemplate orderTimeoutJmsTemplate;/**     * 向指定队列发送延时消息,time为毫秒数     */public void sendMessage(final String msg, final Long timeout) {String destination =  orderTimeoutJmsTemplate.getDefaultDestination().toString();System.out.println("向队列" + destination.toString() + "发送了消息------------" + msg);orderTimeoutJmsTemplate.send(new MessageCreator() {public Message createMessage(Session session) throws JMSException {TextMessage message = session.createTextMessage(msg);message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, timeout);return message;}});}public void sendMessage(final String msg) {this.sendMessage(msg, 24*3600*1000L);}}

监听消费者 OrderTimeoutMessageListener.java

/** * 文件名:QueueMessageListener.java * 创建日期:  2017年10月9日 * 作者:      ningfangming * 版权所有(C) 2016-2017 * 保留所有权利. */package com.yk.appointment.delayedqueue;import javax.jms.Message;import javax.jms.MessageListener;import javax.jms.TextMessage;public class OrderTimeoutMessageListener implements MessageListener {        //当收到消息后,自动调用该方法    @Override    public void onMessage(Message message) {        TextMessage tm = (TextMessage) message;        try {            System.out.println("OrderTimeoutMessageListener监听到了文本消息:\t"                    + tm.getText());            // 你自己的处理逻辑,取消订单,修改订单状态等                                } catch (Exception e) {            e.printStackTrace();        }    }}

pom 文件配置

            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jms</artifactId>
                <version>${org.springframework-version}</version>
            </dependency>
            <dependency>
     <groupId>org.apache.activemq</groupId>
     <artifactId>activemq-core</artifactId>
     <version>5.5.1</version>
   </dependency>


===================================以上为24小时取消订单===============================

按照日程id取消日程,仅为demo

/** * 文件名:EnhanceScheduler.java * 创建日期:  2017年10月12日 * 作者:      ningfangming * 版权所有(C) 2016-2017 深圳市华康全景信息技术有限公司 * 保留所有权利. */package com.github.xjs.util.delayedqueue;import javax.jms.Connection;import javax.jms.ConnectionFactory;import javax.jms.Destination;import javax.jms.JMSException;import javax.jms.Message;import javax.jms.MessageConsumer;import javax.jms.MessageProducer;import javax.jms.Session;import javax.jms.TextMessage;import org.apache.activemq.ActiveMQConnectionFactory;import org.apache.activemq.ScheduledMessage;/** * 功能描述: * @author ningfangming 2017年10月12日 */public class EnhanceScheduler {public static void main(String[] args){try {createMsg("723984837693673475");createMsg("723984837693673473");cancelMsg("723984837693673473");} catch (JMSException e) {e.printStackTrace();}}public static void createMsg(String msg) throws JMSException{ConnectionFactory factory = new ActiveMQConnectionFactory();Connection connection = factory.createConnection();        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        Destination destination = session.createQueue("delayed");        MessageProducer producer = session.createProducer(destination);        TextMessage message = session.createTextMessage(msg);        message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 24*3600*1000);        producer.send(message);}public static void cancelMsg(String msg) throws JMSException{ConnectionFactory factory = new ActiveMQConnectionFactory();Connection connection = factory.createConnection();        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);        // Create the Browse Destination and the Reply To location        Destination requestBrowse = session.createTopic(ScheduledMessage.AMQ_SCHEDULER_MANAGEMENT_DESTINATION);        Destination browseDest = session.createTemporaryQueue();        // Create the "Browser"        MessageConsumer browser = session.createConsumer(browseDest);        connection.start();        // Send the browse request        MessageProducer producer = session.createProducer(requestBrowse);        TextMessage request = session.createTextMessage();        request.setStringProperty(ScheduledMessage.AMQ_SCHEDULER_ACTION,                                  ScheduledMessage.AMQ_SCHEDULER_ACTION_BROWSE);        request.setJMSReplyTo(browseDest);        producer.send(request);        Message scheduled = browser.receive();        while(scheduled!=null){        TextMessage textScheduled = (TextMessage)scheduled;            if(textScheduled.getText().equals(msg)){            Message remove = session.createMessage();                remove.setStringProperty(ScheduledMessage.AMQ_SCHEDULER_ACTION,                        ScheduledMessage.AMQ_SCHEDULER_ACTION_REMOVE);                String scheduleId = scheduled.getStringProperty(ScheduledMessage.AMQ_SCHEDULED_ID);                System.out.println(scheduleId);                remove.setStringProperty(ScheduledMessage.AMQ_SCHEDULED_ID,scheduleId);                producer.send(remove);            }            scheduled = browser.receive();        }        }}