ActiveMQ延时队列取消超时支付订单

  • 今日发现用ActiveMQ用于取消超时支付订单更加方便。
  • ActiveMQ在推送消息的时候可以指定延时时间,假设订单支付超时15分钟,则在进入消息的时候,逻辑判断订单状态后可以进行操作。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.moriartyzzb</groupId>
	<artifactId>acitve-mq-project</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>AcitveMq</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--activeMq-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-activemq</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
server:
  port: 9999
  servlet.context-path: /mq
spring:
  activemq:
    broker-url: tcp://127.0.0.1:61616
    user: admin
    password: jDrPve8z6xvfLvQv
    close-timeout: 15s

package com.moriartyzzb.acitvemqproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AcitveMqApplication {

	public static void main(String[] args) {
		SpringApplication.run(AcitveMqApplication.class, args);
	}

}

 

package com.moriartyzzb.acitvemqproject.config;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;

/**
 * @author Zengzhibin
 * @title: ActiveMQConfiguration
 * @projectName acitve-mq-project
 * @description: TODO
 * @date 2021/2/23 14:34
 */
@Configuration
public class ActiveMQConfiguration {

    //这个Bean用于和mq建立连接、mq的地址、用户名、密码从配置文件中获取
    @Bean(name = "innerConnectionFactory")
    @Primary
    public ActiveMQConnectionFactory firstConnectionFactory(
        //mq服务地址
        @Value("${spring.activemq.broker-url}") String brokerUrl,
        //mq用户名
        @Value("${spring.activemq.user}") String username,
        //mq密码
        @Value("${spring.activemq.password}") String password) {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setBrokerURL(brokerUrl);
        factory.setUserName(username);
        factory.setPassword(password);
        factory.setTrustAllPackages(true);
        factory.setMaxThreadPoolSize(ActiveMQConnection.DEFAULT_THREAD_POOL_SIZE);
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        //定义ReDelivery(重发机制)机制 ,重发时间间隔是100毫秒,最大重发次数是3次
        //是否在每次尝试重新发送失败后,增长这个等待时间
        redeliveryPolicy.setUseExponentialBackOff(true);
        //重发次数,默认为6次   这里设置为1次
        redeliveryPolicy.setMaximumRedeliveries(1);
        //重发时间间隔,默认为1秒
        redeliveryPolicy.setInitialRedeliveryDelay(1000);
        //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
        redeliveryPolicy.setBackOffMultiplier(2);
        //最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第
        //二次重连时间间隔为 20ms,第三次重连时间间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。
        redeliveryPolicy.setMaximumRedeliveryDelay(1000);
        factory.setRedeliveryPolicy(redeliveryPolicy);
        return factory;
    }

    //在Topic模式中,对消息的监听需要对containerFactory进行配置
    @Bean("topicJmsListenerContainerFactory")
    public JmsListenerContainerFactory<?> topicJmsListenerContainerFactory(
            //将“innerConnectionFactory”这个Bean注入
            @Qualifier("innerConnectionFactory") ActiveMQConnectionFactory connectionFactory) {
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setSessionTransacted(true);
        factory.setPubSubDomain(true);
        return factory;
    }

    // 在Queue模式中,对消息的监听需要对containerFactory进行配置
    @Bean("queueJmsListenerContainerFactory")
    public JmsListenerContainerFactory<?> queueJmsListenerContainerFactory(
            //将“innerConnectionFactory”这个Bean注入
            @Qualifier("innerConnectionFactory") ActiveMQConnectionFactory connectionFactory) {
        SimpleJmsListenerContainerFactory factory = new SimpleJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setSessionTransacted(true);
        factory.setPubSubDomain(false);
        return factory;
    }
}
package com.moriartyzzb.acitvemqproject.operator;

import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jms.JmsProperties;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

import javax.jms.*;


/**
 * @author Zengzhibin
 * @title: ActivemqOperator
 * @projectName acitve-mq-project
 * @description: TODO
 * @date 2021/2/23 14:39
 */
@Component
public class ActivemqOperator {
    private final JmsMessagingTemplate jmsTemplate;
    @Autowired
    public ActivemqOperator(JmsMessagingTemplate jmsTemplate) {
        this.jmsTemplate = jmsTemplate;
    }

    /**
     * 发送主题消息
     */
    public void sendMsgTopic(String topic, String message) {
        Destination destination = new ActiveMQTopic(topic);
        jmsTemplate.convertAndSend(destination, message);
    }

    /**
     * 发送队列消息
     */
    public void sendMsgQueue(String queue, String message) {
        Destination destination = new ActiveMQQueue(queue);
        jmsTemplate.convertAndSend(destination, message);
    }

    /**
     * 发送延时队列消息
     */
    public <T> void delaySend(String queue, String message, Long time) {
        Connection connection = null;
        Session session = null;
        MessageProducer producer = null;
        ConnectionFactory connectionFactory = jmsTemplate.getConnectionFactory();
        Destination destination = new ActiveMQQueue(queue);
        try {
            connection = connectionFactory.createConnection();
            connection.start();
            session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
            producer = session.createProducer(destination);
            producer.setDeliveryMode(JmsProperties.DeliveryMode.PERSISTENT.getValue());
            ObjectMessage objectMessage = session.createObjectMessage(message);

            objectMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);

            producer.send(objectMessage);
            session.commit();
        } catch (Exception e) {
            throw new RuntimeException("delaySend exception : " + e.getMessage());
        } finally {
            try {
                if (producer != null) {
                    producer.close();
                }
                if (session != null) {
                    session.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

package com.moriartyzzb.acitvemqproject.controller;

import com.moriartyzzb.acitvemqproject.operator.ActivemqOperator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author Zengzhibin
 * @title: MqController
 * @projectName acitve-mq-project
 * @description: TODO
 * @date 2021/2/23 14:31
 */
@RequestMapping("/testMq")
@RestController
public class MqController {
    private final ActivemqOperator activemqOperator;
    //构造方式注入bean
    @Autowired
    public MqController(ActivemqOperator activemqOperator) {
        this.activemqOperator = activemqOperator;
    }

    @GetMapping("/queue")
    public String testMqQueue() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        System.out.println("当前订单【123456789】生成时间: "+df.format(new Date()));// new Date()为获取当前系统时间
        //设置延时时间推送到activeMQ
        activemqOperator.delaySend("testQueue","延时10S",10000L);
        return "OK";
    }

    @JmsListener(destination = "testQueue", containerFactory = "queueJmsListenerContainerFactory")
    public void listenerMq(String message) {
        //业务逻辑,根据单号查询是否已经付款
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
        System.out.println("当前订单【123456789】失效时间: "+df.format(new Date()));// new Date()为获取当前系统时间
    }
}

代码地址 https://download.csdn.net/download/p_moriarty/15451383

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值