Spring Boot 整合ActiveMQ实现延时发现消息
生产者提供两个发送消息的方法,一个是即时发送消息,一个是延时发送消息。延时发送消息需要手动修改activemq目录conf下的activemq.xml配置文件,开启延时。本文中maven依赖文件和application.properties配置文件与《Spring Boot 整合 ActiveMQ 实现手动确认和重发消息》一致,保持不变。
定义消息对象
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.stereotype.Component; import java.io.Serializable; /**
* @author Wiener
*/
@Setter
@Getter
@ToString
@Component
public class User implements Serializable {
private Long id;
private int age;
private String name;
private String remark; public User() {
}
public User(Long id, int age, String name) {
super();
this.id = id;
this.age = age;
this.name = name;
}
}
编写生产者
生产者提供两个发送消息的方法,一个是即时发送消息,一个是延时发送消息。延时发送消息需要手动修改activemq目录conf下的activemq.xml配置文件,开启延时,在broker标签内新增属性schedulerSupport="true",然后重启activemq即可。
<!--
The <broker> element is used to configure the ActiveMQ broker.
-->
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.data}" schedulerSupport="true"> <destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<!-- The constantPendingMessageLimitStrategy is used to prevent
slow topic consumers to block producers and affect other consumers
by limiting the number of messages that are retained
For more information, see: http://activemq.apache.org/slow-consumer-handling.html -->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
下面定义生产者和消费者:
import org.apache.activemq.ScheduledMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jms.JmsProperties;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service; import javax.jms.*;
import java.io.Serializable; @Service("producer")
public class Producer {
/**
* 也可以注入JmsTemplate,JmsMessagingTemplate对JmsTemplate进行了封装
*/
@Autowired
private JmsMessagingTemplate jmsTemplate; /**
* 发送消息,destination是发送到的队列,message是待发送的消息
*
* @param destination
* @param message
*/
public void sendMessage(Destination destination, final String message) {
jmsTemplate.convertAndSend(destination, message);
} /**
* 延时发送
* @param destination 发送的队列
* @param data 发送的消息
* @param time 延迟时间
*/
public <T extends Serializable> void delaySendMsg(Destination destination, T data, Long time){
Connection connection = null;
Session session = null;
MessageProducer producer = null;
// 获取连接工厂
ConnectionFactory connectionFactory = jmsTemplate.getConnectionFactory();
try {
// 获取连接
connection = connectionFactory.createConnection();
connection.start();
// 获取session,true开启事务,false关闭事务
session = connection.createSession(Boolean.TRUE, Session.AUTO_ACKNOWLEDGE);
// 创建一个消息队列
producer = session.createProducer(destination);
//消息持久化
producer.setDeliveryMode(JmsProperties.DeliveryMode.PERSISTENT.getValue());
ObjectMessage message = session.createObjectMessage(data);
//设置延迟时间
message.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, time);
// 发送消息
producer.send(message);
//一旦开启事务发送,那么就必须使用commit方法提交事务
session.commit();
} catch (Exception e){
e.printStackTrace();
} finally {
try {
if (producer != null){
producer.close();
}
if (session != null){
session.close();
}
if (connection != null){
connection.close();
}
} catch (Exception e){
e.printStackTrace();
}
}
} }
JmsTemplate类的 setDeliveryMode(int deliveryMode)可以对持久化策略进行配置,1表示非持久化,2表示持久化,二者定义于DeliveryMode类中。
/**
* Set the delivery mode to use when sending a message.
* Default is the JMS Message default: "PERSISTENT".
* <p>Since a default value may be defined administratively,
* this is only used when "isExplicitQosEnabled" equals "true".
* @param deliveryMode the delivery mode to use
*/
public void setDeliveryMode(int deliveryMode) {
this.deliveryMode = deliveryMode;
}
public interface DeliveryMode {
/**
* A Jakarta Messaging provider must deliver a {@code NON_PERSISTENT} message with an at-most-once guarantee. This means that it may
* lose the message, but it must not deliver it twice.
*/
int NON_PERSISTENT = 1;
/**
* This delivery mode instructs the Jakarta Messaging provider to log the message to stable storage as part of the client's send
* operation. Only a hard media failure should cause a {@code PERSISTENT} message to be lost.
*/
int PERSISTENT = 2;
}
消费者正常消费消息即可。
@Component
public class ConsumerListener2 {
private static Logger logger = LoggerFactory.getLogger(ConsumerListener2.class);
/**
* 使用JmsListener配置消费者监听的队列
* @param receivedMsg 接收到的消息
*/
@JmsListener(destination = "myDest.queue")
public void receiveQueue(String receivedMsg) {
logger.info("Consumer2 收到的报文为: {}", receivedMsg);
}
} @Component
public class ConsumerListener {
private static Logger logger = LoggerFactory.getLogger(ConsumerListener.class); @JmsListener(destination = "myDest.queue")
public void receiveQueue(String receivedMsg) {
logger.info("Consumer收到的报文为: {}", receivedMsg);
} }
编写测试用例
import com.alibaba.fastjson.JSON;
import com.eg.wiener.controller.Producer;
import com.eg.wiener.dto.User;
import org.apache.activemq.command.ActiveMQQueue;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import javax.jms.Destination;
import java.text.SimpleDateFormat;
import java.util.Date; @SpringBootTest
class WienerApplicationTests { @Test
void contextLoads() {
} @Autowired
private Producer producer; /**
* 延迟处理
* @throws InterruptedException
*/
@Test
public void mqDelayTest() throws InterruptedException {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Destination destination = new ActiveMQQueue("myDest.queue");
User user = new User();
user.setName("演示发送消息");
user.setId(33L);
for (int i = 0; i < 6; i++) {
user.setId(i *100L);
user.setAge(i + 20);
user.setRemark(df.format(new Date()) );
producer.delaySendMsg(destination, JSON.toJSONString(user), 10000L);
}
try {
// 休眠,等等消息执行
Thread.currentThread().sleep(30000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
这里贴出延迟发送效果的部分日志:
2020-09-20 18:21:02.047 INFO 9728 --- [enerContainer-1] c.eg.wiener.controller.ConsumerListener : Consumer收到的报文为: {"age":23,"id":300,"name":"演示发送消息","remark":"2020-09-20 18:20:10"}
2020-09-20 18:21:02.064 INFO 9728 --- [enerContainer-1] c.eg.wiener.controller.ConsumerListener : Consumer收到的报文为: {"age":25,"id":500,"name":"演示发送消息","remark":"2020-09-20 18:20:10"}
remark记录了消息生成时间,而日志打印时间是消息消费时间,晚于remark时间,足以说明消息是延迟发送的。
关于本文内容,大家有什么看法?欢迎留言讨论,也希望大家多多点赞关注。楼兰胡杨祝各位生活愉快!工作顺利!
Spring Boot 整合ActiveMQ实现延时发现消息的更多相关文章
- activeMQ入门+spring boot整合activeMQ
最近想要学习MOM(消息中间件:Message Oriented Middleware),就从比较基础的activeMQ学起,rabbitMQ.zeroMQ.rocketMQ.Kafka等后续再去学习 ...
- spring boot整合activemq消息中间件
spring boot整合activemq消息中间件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi ...
- spring boot 整合activemq
1 Spring Boot与ActiveMQ整合 1.1使用内嵌服务 (1)在pom.xml中引入ActiveMQ起步依赖 <properties> <spring.version& ...
- Spring Boot 整合 ActiveMQ
依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri ...
- Spring Boot入门 and Spring Boot与ActiveMQ整合
1.Spring Boot入门 1.1什么是Spring Boot Spring 诞生时是 Java 企业版(Java Enterprise Edition,JEE,也称 J2EE)的轻量级代替品.无 ...
- Spring Boot与ActiveMQ整合
Spring Boot与ActiveMQ整合 1使用内嵌服务 (1)在pom.xml中引入ActiveMQ起步依赖 <dependency> <groupId>org.spri ...
- Spring Kafka和Spring Boot整合实现消息发送与消费简单案例
本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 先前我已经分享了Kafka的基本介绍与集群环境搭建方法.关于Kafka的 ...
- spring boot 整合quartz ,job不能注入的问题
在使用spring boot 整合quartz的时候,新建定时任务类,实现job接口,在使用@AutoWire或者@Resource时,运行时出现nullpointException的问题.显然是相关 ...
- spring boot整合websocket
转载自:https://www.cnblogs.com/GoodHelper/p/7078381.html 一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日 ...
- RabbitMQ使用及与spring boot整合
1.MQ 消息队列(Message Queue,简称MQ)——应用程序和应用程序之间的通信方法 应用:不同进程Process/线程Thread之间通信 比较流行的中间件: ActiveMQ Rabbi ...
随机推荐
- Vue3路由进阶实战:深度解析参数传递与导航守卫核心技术
一.路由参数传递的进阶应用技巧 1.1 路由配置与参数验证 // router/index.js { path: '/user/:userId(\\d+)', // 使用正则表达式限制只匹配数字 na ...
- C# 泛型类型约束 where
1 class Program { 2 static void Main(string[] args) { 3 4 } 5 } 6 7 interface IMyInterface { 8 void ...
- mysql 卸载安装教程链接
https://blog.csdn.net/weixin_56952690/article/details/129678685 https://blog.51cto.com/u_16213646/70 ...
- FastAPI复杂查询终极指南:告别if-else的现代化过滤架构
title: FastAPI复杂查询终极指南:告别if-else的现代化过滤架构 date: 2025/3/14 updated: 2025/3/14 author: cmdragon excerpt ...
- Golang入门:Linux上的go语言安装与配置
Tips:本文以本文撰写时的 Go 语言最新版本,也就是 go.1.19.2 版本为例. Linux 发行版本使用 Ubuntu 22.04.1 LTS 为例来做演示. 安装 C 工具 Go 的工具链 ...
- Invalid prop: type check failed for prop "showCheckbox". Expected Boolean, got String.
一个简单的报错 ,可以用于 代码: <el-tree :data="menus" :props="defaultProps" ...
- 第一次记录自己的java学习日常,之前都是看其他博主的java知识,现在该自己记录一下了。
对知识做总结 在学校呢,走过了非常多的坑,参加了一些比赛,但是也没有学到什么(含金量高的比赛可以参加,但是需参加之前先沉淀好自己的技术,不要报名了才去准备,得在准备中去报名),学校教的知识都是理论化, ...
- Windows Terminal 添加 git-bash
配置文件中 profiles 节点补充配置 { "guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b7}", " ...
- 枚举与string之间查找与转换
利用TypInfo单元的GetEnumName和GetEnumValue可以遍历任意枚举类型 其实上面程序运行会有err,为什么?因为没有理解和掌握JSON Objects Framework[感到简 ...
- 二叉树专题学习(C++版) 基础的上机题
前言: 由于二叉树这一章的题型比较多,涉及到的递归程序也较多,所以单开一个随笔来记录这个学习过程,希望对读者有帮助. 理论知识基础 在二叉树的选择题中,常常会涉及到对于最多或最少结点.最大或最小高度. ...