生产者提供两个发送消息的方法,一个是即时发送消息,一个是延时发送消息。延时发送消息需要手动修改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实现延时发现消息的更多相关文章

  1. activeMQ入门+spring boot整合activeMQ

    最近想要学习MOM(消息中间件:Message Oriented Middleware),就从比较基础的activeMQ学起,rabbitMQ.zeroMQ.rocketMQ.Kafka等后续再去学习 ...

  2. spring boot整合activemq消息中间件

    spring boot整合activemq消息中间件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi ...

  3. spring boot 整合activemq

    1 Spring Boot与ActiveMQ整合 1.1使用内嵌服务 (1)在pom.xml中引入ActiveMQ起步依赖 <properties> <spring.version& ...

  4. Spring Boot 整合 ActiveMQ

    依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri ...

  5. Spring Boot入门 and Spring Boot与ActiveMQ整合

    1.Spring Boot入门 1.1什么是Spring Boot Spring 诞生时是 Java 企业版(Java Enterprise Edition,JEE,也称 J2EE)的轻量级代替品.无 ...

  6. Spring Boot与ActiveMQ整合

    Spring Boot与ActiveMQ整合 1使用内嵌服务 (1)在pom.xml中引入ActiveMQ起步依赖 <dependency> <groupId>org.spri ...

  7. Spring Kafka和Spring Boot整合实现消息发送与消费简单案例

    本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 先前我已经分享了Kafka的基本介绍与集群环境搭建方法.关于Kafka的 ...

  8. spring boot 整合quartz ,job不能注入的问题

    在使用spring boot 整合quartz的时候,新建定时任务类,实现job接口,在使用@AutoWire或者@Resource时,运行时出现nullpointException的问题.显然是相关 ...

  9. spring boot整合websocket

    转载自:https://www.cnblogs.com/GoodHelper/p/7078381.html 一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日 ...

  10. RabbitMQ使用及与spring boot整合

    1.MQ 消息队列(Message Queue,简称MQ)——应用程序和应用程序之间的通信方法 应用:不同进程Process/线程Thread之间通信 比较流行的中间件: ActiveMQ Rabbi ...

随机推荐

  1. C# Semaphore

    1.Semaphore定义Semaphore,是负责协调各个线程, 以保证它们能够正确.合理的使用公共资源.也是操作系统中用于控制进程同步互斥的量. Semaphore常用的方法有两个WaitOne( ...

  2. [第三章]ABAQUS CM插件中文手册

    ABAQUS Composite Modeler User Manual(zh-CN) Dassault Systèmes, 2018 注: 源文档的交叉引用链接,本文无效 有些语句英文表达更易理解, ...

  3. python 二级 语言基本元素笔记-字符串

    l='12345' 1.递增顺序: 正向递增从0开始 负向从[-1]开始,l[1]=2,l[-1]=5 2.切片操作:左开右闭,l[2:5]=3,4 3.导入库,引入 库名.函数名 input函数 输 ...

  4. OpenCV开发笔记(八十三):图像remap实现哈哈镜效果

    前言   对图像进行非规则的扭曲,实现哈哈镜就是一种非常规的扭曲方式,本文先描述remap的原理,然后通过remap实现哈哈镜.   Demo              基于原始算法,可以进行二次开发 ...

  5. [tldr]通过指令获取github仓库的单个文件的内容

    针对一个公开的github仓库,有些时候不需要clone整个仓库的内容,只需要对应的几个文件.但是直接通过网页点击下载文件很麻烦,在服务器上也不好这样操作. 因此,如何使用curl或者wget指令快速 ...

  6. Golang 入门 : 常量

    常量 相对于变量而言,常量是在程序使用过程中,不会改变的数据.有些地方你需要将定义好的常量重复使用,代码中你不允许它的值改变.例如 圆周率 在程序执行过程中不会改变. 常量的声明 const Pi f ...

  7. 简易TXT文本小说阅读器

    上次学习爬取小说保存到txt文本文件,方便离线阅读,现在做一个简易TXT文本小说阅读器,支持手动翻页和自动翻页阅读. 废话不多说,直接上代码,实践下. read_txt.py: import time ...

  8. Linux运维面试题之:Root密码忘记如何解决

    目录 6.5 Root密码忘记如何解决 6.5.1 系统自带救援模式 6.5.2 U盘.光盘救援系统 6.5 Root密码忘记如何解决 解决方案有两种:自救,别人救 解决方案 应用场景 1️⃣ 系统自 ...

  9. Linux终端居然也可以做文件浏览器?

    大家好,我是良许. 在抖音上做直播已经整整 5 个月了,我很自豪我一路坚持到了现在[笑脸] 最近我在做直播的时候,也开始学习鱼皮大佬,直播写代码.当然我不懂 Java 后端,因此就写写自己擅长的 Sh ...

  10. vscode安装离线插件autopep8

    商店 从上面的链接进去,在visual studio code一栏开始搜索,我要的是autopep8,所以搜索得到的是这样的: 点进去后,是这个界面,然后我是离线下载,要的是拓展包,所以是下面操作 下 ...