- 今日发现用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