StreamUtils
package com.redis.utils; import com.SpringUtils;
import com.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Range;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisZSetCommands;
import org.springframework.data.redis.connection.stream.Record;
import org.springframework.data.redis.connection.stream.*;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StreamOperations;
import org.springframework.data.redis.core.StringRedisTemplate; import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* redis Stream类型数据操作Dao接口
* @author muzhi
* @author <a href="mailto:maming.zhong2526@nvxclouds.com">Muzhi Zhang</a>
* @version 1.0.0
* @date 2023-12-14 20:45
*/
@Slf4j
public class StreamUtils<T> {
private final StringRedisTemplate stringRedisTemplate;
private final StreamOperations<String,String, T> streamOperations; public StreamUtils() {
this.stringRedisTemplate = SpringUtils.getBean(StringRedisTemplate.class);
this.streamOperations = stringRedisTemplate.opsForStream();
stringRedisTemplate.execute((RedisCallback) RedisConnection::scriptingCommands);
} /**
* 获取当前操作 StreamOperations
* @return
*/
public StreamOperations getStreamOperations() {
return streamOperations;
} /**
*
* @return
*/
public StringRedisTemplate getStringRedisTemplate() {
return stringRedisTemplate;
} /**
* 初始化stream和消费者组
* @param key
* @param group
*/
public void initStream(String key, String group) {
//判断key是否存在,如果不存在则创建
boolean hasKey = true;
if (StringUtils.isNotBlank(key)){
hasKey = stringRedisTemplate.hasKey(key);
}
if(!hasKey){
Map<String,T> map = new HashMap<>();
map.put("field", (T) "value");
String recordId = insertStreamAll(key, map);
createGroup(key,group);
//将初始化的值删除掉
remove(key,recordId); log.debug("stream:{}-group:{} initialize success",key,group);
}
} /**
* 添加消息到末尾
* @param key
* @param field
* @param value
* @return
*/
public String insertStream(String key, String field, T value) {
Map<String, T> content = new HashMap<>(1);
content.put(field, value);
return insertStreamAll(key, content);
} /**
* 批量添加消息到末尾
* @param key
* @param content
* @return
*/
public String insertStreamAll(String key, Map<String, T> content) {
return streamOperations.add(key,content).getValue();
} /**
* 删除消息,这里的删除仅仅是设置了标志位,不影响消息总长度
* 消息存储在stream的节点下,删除时仅对消息做删除标记,当一个节点下的所有条目都被标记为删除时,销毁节点
* @param key
* @param recordIds
* @return
*/
public Long remove(String key, String... recordIds) {
return streamOperations.delete(key,recordIds);
} /**
* 创建消费组
* @param key
* @param group
* @return
*/
public String createGroup(String key, String group) {
return streamOperations.createGroup(key,group);
} /**
* 确认已消费
* @param key
* @param group
* @param recordIds
* @return
*/
public Long ack(String key, String group, String... recordIds) {
return streamOperations.acknowledge(key, group, recordIds);
} /**
* 确认已消费
* @param group
* @param record
* @return
*/
public Long ack(String group, Record<String, ?> record) {
return streamOperations.acknowledge(group, record);
} /**
* 消息长度
* @param key
* @return
*/
public Long len(String key) {
return streamOperations.size(key);
} /**
* 从头开始读
* @param key
* @return
*/
public List<MapRecord<String, String, T>> readByZero(String key) {
return streamOperations.read(StreamOffset.fromStart(key));
} /**
* 从指定的ID开始读
* @param key
* @param recordId
* @return
*/
public List<MapRecord<String, String, T>> readById(String key, String recordId) {
return streamOperations.read(StreamOffset.from(MapRecord.create(key, new HashMap<>(1)).withId(RecordId.of(recordId))));
} /**
* 读取pending 中未处理的数据
* @param key
* @param consumer
* @return
*/
public PendingMessages readWithPending(String key, Consumer consumer) {
//从零到最大,10条数据
// return streamOperations.pending(key, consumer, Range.closed("0", "+"), 10L);
return streamOperations.pending(key, consumer);
} /**
* 读取pending 中未处理的数据
* @param key
* @param group
* @return
*/
public PendingMessagesSummary readWithPending(String key, String group) {
return streamOperations.pending(key, group);
} /**
* 获取消费组信息
* @param key
* @param group
* @return
*/
public StreamInfo.XInfoConsumers getConsumers(String key, String group) { return streamOperations.consumers(key, group);
} /**
* 获取消息列表,会自动过滤已经删除的消息
* @param key
* @param rightOpen
* @return
*/
public List<MapRecord<String, String, T>> getMsgList(String key, Range<String> rightOpen) {
return streamOperations.range(key, rightOpen);
} /**
* 从特定范围内的流中读取记录
* @param key
* @param startId
* @param endId
* @param count
* @return
*/
public List<MapRecord<String, String, T>> range(String key, RecordId startId, RecordId endId, Integer count) { return streamOperations .range(key,
Range.from(Range.Bound.exclusive(startId.getValue())).to(Range.Bound.exclusive(startId.getValue())),
RedisZSetCommands.Limit.limit().count(count));
}
}
StreamUtils的更多相关文章
- java.lang.NoSuchMethodError: org.springframework.util.StreamUtils.emptyInput()Ljava/io/InputStream;
今天写用spring的MockMvc测试controller的demo时出现了这个错误,条件反射的进行了百度,没有搜到匹配的答案,但给了一些解决问题的思路:首先NoSuchMethodError要不就 ...
- 003-Spring 中的StreamUtils
一.概述 StreamUtils是spring中用于处理流的类,是java.io包中inputStream和outputStream,不是java8中Steam.使用时仅依赖spring-core 二 ...
- Spring 中StreamUtils教程
本文我们介绍StreamUtils类使用.StreamUtils是spring中用于处理流的类,是java.io包中inputStream和outputStream,不是java8中Steam.使用时 ...
- Android之三种网络请求解析数据(最佳案例)
AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法. ...
- CloudNotes之桌面客户端篇:笔记撰写样式的支持
最近在CloudNotes桌面客户端中新增了笔记撰写样式的功能.当用户新建笔记的时候,可以在输入笔记标题的同时,选择笔记撰写样式,由安装包默认提供的样式主要有默认样式(Default).羊皮纸样式(L ...
- 从无到有实现登录功能以及thinkphp怎么配置数据库信息
好开心,终于解决了.从学习android到现在写登录功能已经不是一次两次了,如今再写想着肯定是信手拈来,没有想到的是尽然折磨了我一天的时间才搞定它.唉...... 先来看几张截图,这次的登录跟以往的不 ...
- Android的Handler机制
Handler机制的原理 Android 的 Handler 机制(也有人叫消息机制)目的是为了跨线程通信,也就是多线程通信.之所以需 要跨线程通信是因为在 Android 中主线程通常只负责 UI ...
- 解析文件+AcitonBar展示:
//项目效果:
- Android中获取选择图片与获取拍照返回结果差异
导语: 如今的安卓应用在选择图片的处理上大多合并使用拍照和从相册中选择这两种方式 今天在写一个这样的功能时遇到一个尴尬的问题,同样是拍照获取图片功能,在不同手机上运行的效果不一样,下面是在某型手机上测 ...
- android 从服务器获取新闻数据并显示在客户端
新闻客户端案例 第一次进入新闻客户端需要请求服务器获取新闻数据,做listview的展示, 为了第二次再次打开新闻客户端时能快速显示新闻,需要将数据缓存到数据库中,下次打开可以直接去数据库中获取新闻直 ...
随机推荐
- windows下配置pytorch环境
借鉴了B站大佬的视频,自己总结安装如下. 首先安装anaconda 按照操作顺序,依次安装,按照我个人习惯,不喜欢讲文件安装在C盘,你们自己决定. 安装完毕之后. 之后打开Anaconda Promp ...
- 权限控制 vue3
- 云原生周刊:Meshery v0.70 发布 | 2024.1.22
开源项目推荐 flux-cluster-template 该项目用于部署由 Flux.SOPS.GitHub Actions.Renovate.Cilium 等支持的 Kubernetes 集群,专注 ...
- 解决IDEA中SpringBoot框架使用@Autowired注解方式注入mapper对象出现红色下划线的问题
点击编译器左上角File,点击settings进入设置界面,找到图片中对应的位置,将红线圈住的地方改为Warning,点击右下角的Apply即可
- linux不常用命令
1.查看进程的内存资源占用 [root@abdi1 elasticsearch]# pidstat -r -p 1791 1 Linux 3.10.0-514.el7.x86_64 (abdi1) 0 ...
- Linux基础-学会使用命令帮助
概述 使用 whatis 使用 man 查看命令程序路径 which 总结 参考资料 概述 Linux 命令及其参数繁多,大多数人都是无法记住全部功能和具体参数意思的.在 linux 终端,面对命令不 ...
- 《JVM第6课》本地方法栈
1 什么是本地方法 首先要知道什么是本地方法,本地方法并不是 JVM 自己的方法,也不是 jre 里面的方法,而是指那些操作系统自己的方法(如C/C++方法),它们在操作系统目录里.可以这么理解,本地 ...
- 访问浪潮带外BMC界面的远程控制台重定向(KVM)无法访问,提示JViewer未签名,mac电脑安装JDK8
报错截图: 安装JDK8 下载JDK1.8的安装包 Java Downloads | Oracle 下载的安装包双击按提示流程安装: 按照完成以后.我们可以查看JDK的安装路径.在资源库/Librar ...
- ubuntu apache默认没开启rewrite 如何开启
注意看到 /etc/apache2/apache2.conf # Include module configuration:IncludeOptional mods-enabled/*.loadInc ...
- C# 开发的环境监测上位机应用
前言 在工业和科研领域,环境监测系统的重要性日益凸显.上位机软件作为环境监测系统的关键组成部分,负责数据采集.处理和显示,对提高监测效率和准确性起着至关重要的作用. 本文将向大家介绍一款用 C# 开发 ...