当前位置: 首页 > news >正文

【使用redisson完成延迟队列的功能】使用redisson配合线程池完成异步执行功能,延迟队列和不需要延迟的队列

1. 使用redisson完成延迟队列的功能

引入依赖

spring-boot-starter-actuator是Spring Boot提供的一个用于监控和管理应用程序的模块
用于查看应用程序的健康状况、审计信息、指标和其他有用的信息。这些端点可以帮助你监控应用程序的运行状态、性能指标和健康状况。
已经有了其他的监控和管理工具,不需要使用Spring Boot Actuator提供的功能。

<!-- redisson -->
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></exclusion></exclusions>
</dependency>

1.1 延时队列工具类

添加延迟队列时使用,监测扫描时也会用这个工具类进行获取消息

package cn.creatoo.common.redis.queue;import cn.creatoo.common.core.utils.StringUtils;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;/*** 分布式延时队列工具类* @author*/
@Component
@ConditionalOnBean({RedissonClient.class})
public class RedisDelayQueueUtil {private static final Logger log = LoggerFactory.getLogger(RedisDelayQueueUtil.class);@Resourceprivate RedissonClient redissonClient;/*** 添加延迟队列** @param value     队列值* @param delay     延迟时间* @param timeUnit  时间单位* @param queueCode 队列键* @param <T>*/public <T> boolean addDelayQueue(@NonNull T value, @NonNull long delay, @NonNull TimeUnit timeUnit, @NonNull String queueCode) {if (StringUtils.isBlank(queueCode) || Objects.isNull(value)) {return false;}try {RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);delayedQueue.offer(value, delay, timeUnit);//delayedQueue.destroy();log.info("(添加延时队列成功) 队列键:{},队列值:{},延迟时间:{}", queueCode, value, timeUnit.toSeconds(delay) + "秒");} catch (Exception e) {log.error("(添加延时队列失败) {}", e.getMessage());throw new RuntimeException("(添加延时队列失败)");}return true;}/*** 获取延迟队列** @param queueCode* @param <T>*/public <T> T getDelayQueue(@NonNull String queueCode) throws InterruptedException {if (StringUtils.isBlank(queueCode)) {return null;}RBlockingDeque<Map> blockingDeque = redissonClient.getBlockingDeque(queueCode);RDelayedQueue<Map> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);T value = (T) blockingDeque.poll();return value;}/*** 删除指定队列中的消息** @param o 指定删除的消息对象队列值(同队列需保证唯一性)* @param queueCode 指定队列键*/public boolean removeDelayedQueue(@NonNull Object o, @NonNull String queueCode) {if (StringUtils.isBlank(queueCode) || Objects.isNull(o)) {return false;}RBlockingDeque<Object> blockingDeque = redissonClient.getBlockingDeque(queueCode);RDelayedQueue<Object> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);boolean flag = delayedQueue.remove(o);//delayedQueue.destroy();return flag;}
}

1.2 延迟队列执行器

package cn.creatoo.system.handler;/*** 延迟队列执行器*/
public interface RedisDelayQueueHandle<T> {void execute(T t);}

1.3 实现队列执行器

实现队列执行器接口,在这里写延迟要做的业务逻辑

package cn.creatoo.system.handler.impl;import cn.creatoo.common.core.domain.vo.WaterVo;
import cn.creatoo.system.api.RemoteFileService;
import cn.creatoo.system.handler.RedisDelayQueueHandle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import java.util.Map;@Component("exposeLinkCloudDelay")
public class ExposeLinkCloudDelay implements RedisDelayQueueHandle<Map> {@Autowiredprivate RemoteFileService remoteFileService;@Overridepublic void execute(Map map) {long dataId = Long.parseLong(map.get("dataId").toString());WaterVo waterVo = new WaterVo();waterVo.setFileLink(map.get("fileLink").toString());waterVo.setType(Integer.parseInt(map.get("type").toString()));waterVo.setDataId(dataId);remoteFileService.waterLink(waterVo);}
}

1.4 延迟队列业务枚举类

package cn.creatoo.common.core.enums;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;/*** 延迟队列业务枚举类* @author shang tf* @data 2024/3/21 14:52*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum FileRedisDelayQueueEnum {EXPOSE_LINK_DELAY("EXPOSE_LINK_DELAY","资源链接处理","exposeLinkDelay"),EXPOSE_LINK_CLOUD_DELAY("EXPOSE_LINK_CLOUD_DELAY","资源链接处理","exposeLinkCloudDelay"),COMPRESSED_LINK_DELAY("COMPRESSED_LINK_DELAY","文件压缩处理","compressedLinkDelay"),UPLOAD_TO_CLOUD_DELAY("UPLOAD_TO_CLOUD_DELAY","资源上传消费端","uploadToCloudDelay"),GET_HASHCODE_DELAY("GET_HASHCODE_DELAY","资源hash值获取","getHashcodeDelay"),UPLOAD_FILE_TO_CABINET("UPLOAD_FILE_CABINET","异步添加文件到数据柜","uploadFileCabinet");/*** 延迟队列 Redis Key*/private String code;/*** 中文描述*/private String name;/*** 延迟队列具体业务实现的 Bean* 可通过 Spring 的上下文获取*/private String beanId;
}

1.5 启动延迟队列监测扫描

package cn.creatoo.system.handler.impl;import cn.creatoo.common.core.enums.FileRedisDelayQueueEnum;
import cn.creatoo.common.redis.queue.RedisDelayQueueUtil;
import cn.creatoo.system.handler.RedisDelayQueueHandle;
import com.alibaba.fastjson2.JSON;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** @author shang tf* @data 2024/3/14 10:45* 启动延迟队列监测扫描* 文件处理的延迟队列线程池*/
@Slf4j
@Component
public class FileRedisDelayQueueRunner implements CommandLineRunner {@Autowiredprivate RedisDelayQueueUtil redisDelayQueueUtil;@Autowiredprivate ApplicationContext context;@Autowiredprivate ThreadPoolTaskExecutor ptask;@Value("${file-thread-pool.core-pool-size:1}")private int corePoolSize;@Value("${file-thread-pool.maximum-pool-size:1}")private int maximumPoolSize;private ThreadPoolExecutor executorService;/*** 程序加载配置文件后,延迟创建线程池*/@PostConstructpublic void init() {executorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 30, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1000), new ThreadFactoryBuilder().setNameFormat("delay-queue-%d").build());}@Overridepublic void run(String... args) {ptask.execute(() -> {while (true) {try {FileRedisDelayQueueEnum[] queueEnums = FileRedisDelayQueueEnum.values();for (FileRedisDelayQueueEnum queueEnum : queueEnums) {Object value = redisDelayQueueUtil.getDelayQueue(queueEnum.getCode());if (value != null) {System.out.println("----------------value:" + JSON.toJSONString(value));RedisDelayQueueHandle<Object> redisDelayQueueHandle = (RedisDelayQueueHandle<Object>) context.getBean(queueEnum.getBeanId());executorService.execute(() -> {redisDelayQueueHandle.execute(value);});}}TimeUnit.MILLISECONDS.sleep(500);} catch (InterruptedException e) {log.error("(FileRedission延迟队列监测异常中断) {}", e.getMessage());}}});log.info("(FileRedission延迟队列监测启动成功)");}
}

1.6 使用延迟队列

使用时在需要延时的地方。
通过注入RedisDelayQueueUtil,使用addDelayQueue方法进行添加延迟任务。

Map<String, String> map = new HashMap<>();
map.put("dataId", examineVo.getId().toString());
map.put("fileLink", resourceLink);
map.put("type", resourceType.toString());
map.put("remark", "资源链接处理");
// 5秒后执行exposeLinkCloudDelay中的方法
redisDelayQueueUtil.addDelayQueue(map, 5, TimeUnit.SECONDS, FileRedisDelayQueueEnum.EXPOSE_LINK_CLOUD_DELAY.getCode());

在这里插入图片描述

2. 使用redisson完成不延时队列的功能

2.1 分布式队列工具类

package cn.creatoo.common.redis.queue;import cn.creatoo.common.core.utils.StringUtils;
import org.redisson.api.RBoundedBlockingQueue;
import org.redisson.api.RQueue;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.Objects;/*** 分布式队列工具类*/
@Component
@ConditionalOnBean({RedissonClient.class})
public class RedisBlockQueueUtil {private static final Logger log = LoggerFactory.getLogger(RedisBlockQueueUtil.class);@Resourceprivate RedissonClient redissonClient;//public <T> boolean addQueue(@NonNull T value, @NonNull String queueCode) {if (StringUtils.isBlank(queueCode) || Objects.isNull(value)) {return false;}try {RBoundedBlockingQueue<T> queue = redissonClient.getBoundedBlockingQueue(queueCode);queue.trySetCapacity(10000);queue.put(value);} catch (Exception e) {throw new RuntimeException("(添加redisson队列失败)");}return true;}/*** 获取队列* @param queueCode* @param <T>*/public <T> T getQueuePeek(@NonNull String queueCode) throws InterruptedException {if (StringUtils.isBlank(queueCode)) {return null;}RQueue<T> queue = redissonClient.getBoundedBlockingQueue(queueCode);T obj = (T) queue.peek();return obj;}public <T> T getQueueTake(@NonNull String queueCode) throws InterruptedException {if (StringUtils.isBlank(queueCode)) {return null;}RBoundedBlockingQueue<T> queue = redissonClient.getBoundedBlockingQueue(queueCode);T obj = (T) queue.take();return obj;}}

2.2 队列业务枚举

package cn.creatoo.common.core.enums;import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;/*** 队列业务枚举*/
@Getter
@NoArgsConstructor
@AllArgsConstructor
public enum RedisQueueEnum {FLOW_RECORD("redissionQueue:FLOW_RECORD", "流量流水"),USER_LOGIN_RECORD("redissionQueue:USER_LOGIN_RECORD", "用户登录流水"),USER_REGISTER_RECORD("redissionQueue:USER_REGISTER_RECORD", "用户注册流水"),SMS_SEND_RECORD("redissionQueue:SMS_SEND_RECORD", "短信流水");/*** 队列 Redis Key*/private String code;/*** 中文描述*/private String name;}

2.3 启动队列监测扫描

package cn.creatoo.system.handler.impl;import cn.creatoo.common.core.enums.RedisQueueEnum;
import cn.creatoo.common.core.utils.StringUtils;
import cn.creatoo.common.mongodb.model.FlowStatistics;
import cn.creatoo.common.mongodb.model.MessageSendRecord;
import cn.creatoo.common.mongodb.model.UserLogin;
import cn.creatoo.common.mongodb.model.UserRegister;
import cn.creatoo.common.redis.queue.RedisBlockQueueUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** description: 启动队列监测扫描*/
@Slf4j
@Component
public class RedisQueueRunner implements CommandLineRunner {@Autowiredprivate RedisBlockQueueUtil redisBlockQueueUtil;//@Autowired//private IBdStatcountService bdStatcountService;@Autowiredprivate ThreadPoolTaskExecutor ptask;@Resourceprivate MongoTemplate mongoTemplate;//@Autowired//private BdAdminHomeService bdAdminHomeService;@Value("${prodHost.mall}")private String mallHost;ThreadPoolExecutor executorService = new ThreadPoolExecutor(4, 8, 30, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>(1000),new ThreadFactoryBuilder().setNameFormat("queue-%d").build());@Overridepublic void run(String... args) throws Exception {ptask.execute(() -> {while (true){try {RedisQueueEnum[] queueEnums = RedisQueueEnum.values();for (RedisQueueEnum queueEnum : queueEnums) {Object value = redisBlockQueueUtil.getQueuePeek(queueEnum.getCode());if (value != null) {executorService.execute(() -> {try {//System.out.println(value.toString());if(queueEnum.getCode().equals(RedisQueueEnum.FLOW_RECORD.getCode())){FlowStatistics flowStatistics = redisBlockQueueUtil.getQueueTake(queueEnum.getCode());/* if(flowStatistics!=null && StringUtils.isNotBlank(flowStatistics.getUrl())){mongoTemplate.insert(flowStatistics, "pv_" + new SimpleDateFormat("yyyy").format(new Date()));// 添加首页统计缓存bdAdminHomeService.addDetailCache(flowStatistics);if(StringUtils.isNotBlank(flowStatistics.getUrl())){bdStatcountService.browseByUrl(flowStatistics.getUrl());}}*/} else if (queueEnum.getCode().equals(RedisQueueEnum.USER_LOGIN_RECORD.getCode())) {UserLogin userLogin = redisBlockQueueUtil.getQueueTake(queueEnum.getCode());mongoTemplate.insert(userLogin, "user_login_" + new SimpleDateFormat("yyyy").format(new Date()));} else if (queueEnum.getCode().equals(RedisQueueEnum.USER_REGISTER_RECORD.getCode())) {UserRegister userRegister = redisBlockQueueUtil.getQueueTake(queueEnum.getCode());mongoTemplate.insert(userRegister, "user_register");} else if (queueEnum.getCode().equals(RedisQueueEnum.SMS_SEND_RECORD.getCode())) {MessageSendRecord sendRecord = redisBlockQueueUtil.getQueueTake(queueEnum.getCode());mongoTemplate.insert(sendRecord, "sms_send_" + new SimpleDateFormat("yyyy").format(new Date()));}} catch (InterruptedException e) {log.error("(Redission队列监测异常中断) {}", e.getMessage());}});}}TimeUnit.MILLISECONDS.sleep(500);} catch (InterruptedException e) {log.error("(Redission队列监测异常中断) {}", e.getMessage());}}});log.info("(Redission队列监测启动成功)");}
}

2.4 使用

这个是直接执行,没有延迟的功能

   redisBlockQueueUtil.addQueue(userRegister, RedisQueueEnum.USER_REGISTER_RECORD.getCode());

在这里插入图片描述

相关文章:

【使用redisson完成延迟队列的功能】使用redisson配合线程池完成异步执行功能,延迟队列和不需要延迟的队列

1. 使用redisson完成延迟队列的功能 引入依赖 spring-boot-starter-actuator是Spring Boot提供的一个用于监控和管理应用程序的模块 用于查看应用程序的健康状况、审计信息、指标和其他有用的信息。这些端点可以帮助你监控应用程序的运行状态、性能指标和健康状况。 已经有了…...

Linux 性能分析工具 perf 的使用指南

什么是perf&#xff0c;可以用来干什么 perf 是 Linux 内核的性能分析工具集&#xff0c;它可以用来监控和分析系统和应用程序的性能。perf 提供了一系列功能强大的子命令&#xff0c;可以帮助开发者和系统管理员&#xff1a; 监控 CPU 使用率&#xff1a;识别最消耗 CPU 的代…...

【QT入门】 Qt代码创建布局之水平布局、竖直布局详解

往期回顾&#xff1a; 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号-CSDN博客 【QT入门】 Qt内存管理机制详解-CSDN博客 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解 先看两个问题&#xff1a; 1、ui设计器设计界面很方便&#xf…...

C 传递数组给函数

如果您想要在函数中传递一个一维数组作为参数&#xff0c;您必须以下面三种方式来声明函数形式参数&#xff0c;这三种声明方式的结果是一样的&#xff0c;因为每种方式都会告诉编译器将要接收一个整型指针。同样地&#xff0c;您也可以传递一个多维数组作为形式参数。 方式 1…...

二次开发Flink-coGroup算子支持迟到数据通过测输出流提取

目录 1.背景 2.coGroup算子源码分析 2.1完整的coGroup算子调用流程 2.2coGroup方法入口 2.3 CoGroupedStreams对象分析 2.4WithWindow内部类分析 2.5CoGroupWindowFunction函数分析 3.修改源码支持获取迟到数据测输出流 3.1复制CoGroupedStreams 3.2新增WithWindow.si…...

【容器源码篇】Set容器(HashSet,LinkedHashSet,TreeSet的特点)

文章目录 ⭐容器继承关系&#x1f339;Set容器&#x1f5d2;️HashSet源码解析构造方法public HashSet()public HashSet(Collection<? extends E> c)public HashSet(int initialCapacity, float loadFactor)HashSet(int initialCapacity, float loadFactor, boolean dum…...

网络工程师实验命令(华为数通HCIA)

VRP系统的基本操作 dis version #查看设备版本信息 sys #进入系统视图 system-name R1 #改设备名字为R1进入接口配置IP地址 int g0/0/0 ip address 192.168.1.1 255.255.255.0 #配置接口地址为192.168.1.1/255.255.255.0 ip address 192.168.1.2 24 sub #此…...

AI大模型学习:AI大模型在特定领域的应用

1. 引言 随着人工智能技术的飞速发展&#xff0c;AI大模型已成为推动科技创新的重要力量。从自然语言处理到图像识别&#xff0c;再到复杂决策支持系统&#xff0c;AI大模型在多个领域展现出了前所未有的潜力和应用广度。本文旨在深入探讨AI大模型在特定领域中的应用&#xff0…...

Channel 结合 Select 使用

在Go语言中&#xff0c;channel和select结合使用是一种强大的并发模式。channel允许在不同的goroutine之间安全地传递消息&#xff0c;而select使得goroutine可以同时等待多个通信操作&#xff08;channel操作&#xff09;。 select语句等待多个channel操作中的任意一个完成。…...

LeetCode-1669题:合并两个链表(原创)

【题目描述】 给你两个链表 list1 和 list2 &#xff0c;它们包含的元素分别为 n 个和 m 个。请你将 list1 中下标从 a 到 b 的全部节点都删除&#xff0c;并将list2 接在被删除节点的位置。下图中蓝色边和节点展示了操作后的结果&#xff1a; 请你返回结果链表的头指针。 【…...

微服务高级篇(三):分布式缓存+Redis集群

文章目录 一、单点Redis的问题及解决方案二、Redis持久化2.1 单机安装Redis2.2 RDB持久化2.3 AOF持久化2.4 RDB和AOF对比 三、Redis主从3.1 搭建Redis主从架构3.1.1 集群结构3.1.2 准备实例和配置3.1.3 启动3.1.4 开启主从关系3.1.5 测试 3.2 数据同步3.2.1 全量同步【建立连接…...

机器学习——元学习

元学习&#xff08;Meta Learning&#xff09;是一种机器学习方法&#xff0c;旨在使模型能够学习如何学习。它涉及到在学习过程中自动化地学习和优化学习算法或模型的能力。元学习的目标是使模型能够从有限的训练样本中快速适应新任务或新环境。 在传统的机器学习中&#xff…...

day56 动态规划part13

300. 最长递增子序列 中等 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,…...

Mybatis别名 动态sql语句 分页查询

给Mybatis的实体类起别名 给Mybatis的xml文件注册mapper映射文件 动态sql语句 1 if 2 choose 3 where 4 foreach 一&#xff09;if 查询指定名称商品信息 语法&#xff1a; SELECT * FROM goods where 11 <if test "gName!null"> and g.g_name like co…...

【算法题】三道题理解算法思想--滑动窗口篇

滑动窗口 本篇文章中会带大家从零基础到学会利用滑动窗口的思想解决算法题&#xff0c;我从力扣上筛选了三道题&#xff0c;难度由浅到深&#xff0c;会附上题目链接以及算法原理和解题代码&#xff0c;希望大家能坚持看完&#xff0c;绝对能有收获&#xff0c;大家有更好的思…...

go env 命令详解

文章目录 1.简介2.格式3.示例4.环境变量参考文献 1.简介 go env 用于查看和设置 Go 环境变量。 默认情况下 go env 输出格式为 Shell 脚本格式&#xff08;如 Windows 上是 batch 文件格式&#xff09;。如果指定变量名称&#xff0c;则只输出变量的值。 2.格式 go env [-j…...

flutter 单例模式

总的思想就是&#xff1a; 确保整个应用程序中只有一个 TranslationService 实例。 避免重复创建相同的实例,节省资源。 为整个应用程序提供一个全局访问点,方便在不同地方使用同一个实例。 1.类创建个实例 2.然后用构造函数赋值给实例 3.其他地方调用时返回实例 import pack…...

1.7.2 python练习题15道

1、求出1 / 1 1 / 3 1 / 5……1 / 99的和 (1分之一1分之三1分支5....) 2、用循环语句&#xff0c;计算2 - 10之间整数的循环相乘的值 &#xff08;2*3*4*5....10) 3、用for循环打印九九乘法表 4、求每个字符串中字符出现的个数如&#xff1a;helloworld 5、实现把字符串str …...

python如何获取word文档的总页数

最近在搞AI. 遇到了一个问题&#xff0c;就是要进行doc文档的解析。并且需要展示每个文档的总页数。 利用AI. 分别尝试了chatGPT, 文心一言&#xff0c; github copilot&#xff0c;Kimi 等工具&#xff0c;给出来的答案都不尽如人意。 给的最多的查询方式就是下面这种。 这个…...

python解压RAR文件

本文使用创作助手。 要在Python中解压RAR文件&#xff0c;你可以使用第三方库rarfile。以下是一个示例代码&#xff0c;演示如何解压RAR文件&#xff1a; 首先&#xff0c;你需要安装 rarfile 库。你可以使用以下命令进行安装&#xff1a; pip install rarfile然后&#xff…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...