RuoYi-Vue-Plus (XXL-JOB任务调度中心二:配置管理与定时任务编写、执行策略、命令行任务、邮件报警等等
一、后端xxl job的配置属性介绍
- enabled : 是否开启执行器,如果为false,调度中心就调用不了后端定时任务
- admin-addresses:调度中心的地址,多个则可以逗号拼接: url1,url2,url3
- access-token: 执行器通讯TOKEN ,必须和xxl-job代码里面的一致
src/main/resources/application.yml 配置文件中 accessToken:--- # xxljob系统配置 xxl:job:# 鉴权tokenaccessToken: xxl-job# 国际化i18n: zh_CN# 日志清理logretentiondays: 30triggerpool:fast:max: 200slow:max: 100
appname: 执行器AppName, 配置完调度中心可以识别到
port: 执行器端口号,执行器名称可以一致appname: xxl-job-executor,但是如果多个执行器端口号必须区分开来- address: 执行器注册地址,默认自动获取IP
- ip: 执行器IP:默认自动获取IP
- logpath: 日志保存路径
logretentiondays: 日志保存天数
通过配置可以知道,xxl-job 调度中心识别执行器的流程:
开启执行器后,执行器根据admin-addresses 地址和 xxl-job 注册到 调度中心,并绑定执行器名称端口日志等信息
--- # xxl-job 配置
xxl.job:# 执行器开关enabled: true#enabled: false# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。admin-addresses: http://localhost:9100/xxl-job-admin# 执行器通讯TOKEN:非空时启用access-token: xxl-jobexecutor:# 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册appname: xxl-job-executor# 28080 端口 随着主应用端口飘逸 避免集群冲突port: 2${server.port}# 执行器注册:默认IP:PORTaddress:# 执行器IP:默认自动获取IPip:# 执行器运行日志文件存储磁盘路径logpath: ./logs/xxl-job# 执行器日志文件保存天数:大于3生效logretentiondays: 30
测试:启动调度中心和后台,将后台注册到调度中心
启动xxx-job调度中心和 后台执行器,
则可以看到注册成功:
二、任务管理
2.1 常用配置:
- 调度配置-调度类型:一般我们默认选择CRON表达式,可以参考文章:cron 定时任务_cron 每月最后一天-CSDN博客
- 任务配置-运行模式:默认BEAN模式,后面代码会演示 分片广播、命令行任务
- 任务配置-JobHandler:对应注解里面标注的名称 @XxlJob("demoJobHandler")
/*** 1、简单任务示例(Bean模式)*/@XxlJob("demoJobHandler")public void demoJobHandler() throws Exception {XxlJobHelper.log("XXL-JOB, Hello World.");for (int i = 0; i < 5; i++) {XxlJobHelper.log("beat at:" + i);}// default success}
高级配置-路由策略:
第一个(First):总是选择注册列表中的第一个执行器执行。最后一个(Last):总是选择注册列表中的最后一个执行器执行。轮询(Round):按顺序轮流选择执行器执行,实现简单负载均衡。随机(Random):随机选择一个执行器执行,增加执行的不确定性。一致性HASH(Consistent Hash):通过Hash算法稳定地选择执行器,即使执行器数量变化也能保持任务分配的连续性。最少使用(Least Used)(LFU或类似概念):选择最近最少被使用的执行器,以平衡负载。最近未使用(Least Recently Used, LRU):选择最久未被使用的执行器执行。故障转移(Failover):当首选执行器不可用时,自动选择下一个可用的执行器。忙碌转移(Busyover):不仅考虑故障,还考虑执行器的忙碌状态,避免过载。分片广播(Sharding Broadcast):所有执行器都执行一次任务,但每个执行器可以处理不同的数据分片,适用于大数据量处理。
高级配置-阻塞处理策略:
单机串行(默认): 描述:任务按调度顺序一个接一个地执行,前一个执行完再执行下一个。 特点:简单,但可能导致任务等待时间长。丢弃后续调度: 描述:如果执行器正忙,新任务会被丢弃。 特点:防止任务堆积,但可能会丢失任务。覆盖之前调度: 描述:如果执行器正忙,会中断当前任务,立即执行新任务。 特点:确保新任务快速执行,但可能影响旧任务。
- 高级配置-任务超时时间 : 默认0, 表示不超时
- 高级配置-失败重试次数 : 默认0, 表示不重试
三、 ruoyi-job 模块
ruoyi-job 是我们定义统一编写定时任务的子模块,现在看看怎么编写第一个定时任务:
引入依赖xxl-job核心包、已经公共common包
<dependencies><!-- 通用工具--><dependency><groupId>com.ruoyi</groupId><artifactId>ruoyi-common</artifactId></dependency><!-- xxl-job-core --><dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId></dependency></dependencies>
1- 编写 XxlJobProperties
@ConfigurationProperties(prefix = "xxl.job") 映射 yml中的配置属性
@Data
@ConfigurationProperties(prefix = "xxl.job")
public class XxlJobProperties {private Boolean enabled;private String adminAddresses;private String accessToken;private Executor executor;@Data@NoArgsConstructorpublic static class Executor {private String appname;private String address;private String ip;private int port;private String logPath;private int logRetentionDays;}
}
2- 编写 XxlJobConfig 配置类
主要就是启动执行器,并配置调度中心地址、token、执行器等等
注解解释:
@ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true") :
开启配置属性:xxl.job 中 enabled为true时候才会 注册, @Bean注解标注的xxlJobExecutor 类
@Slf4j
@Configuration //标注配置类
@EnableConfigurationProperties(XxlJobProperties.class) //启用配置属性
@AllArgsConstructor
@ConditionalOnProperty(prefix = "xxl.job", name = "enabled", havingValue = "true") //开启配置属性:enabled为true时候才会 注册:xxlJobExecutor
public class XxlJobConfig {private final XxlJobProperties xxlJobProperties;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {log.info(">>>>>>>>>>> xxl-job config init.");// 初始化 xxl-job 执行器XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();// 配置 调度中心地址xxlJobSpringExecutor.setAdminAddresses(xxlJobProperties.getAdminAddresses());// 配置 tokenxxlJobSpringExecutor.setAccessToken(xxlJobProperties.getAccessToken());// 配置 执行器XxlJobProperties.Executor executor = xxlJobProperties.getExecutor();//执行器相关属性xxlJobSpringExecutor.setAppname(executor.getAppname());xxlJobSpringExecutor.setAddress(executor.getAddress());xxlJobSpringExecutor.setIp(executor.getIp());xxlJobSpringExecutor.setPort(executor.getPort());xxlJobSpringExecutor.setLogPath(executor.getLogPath());xxlJobSpringExecutor.setLogRetentionDays(executor.getLogRetentionDays());return xxlJobSpringExecutor;}}
3-编写定时任务
完成上面配置类,便可以直接编写定时任务
@Slf4j
@Service
public class SampleService {/*** 1、简单任务示例(Bean模式)*/@XxlJob("demoJobHandler")public void demoJobHandler() throws Exception {XxlJobHelper.log("XXL-JOB, Hello World.");for (int i = 0; i < 5; i++) {XxlJobHelper.log("beat at:" + i);}// default success}
四、参数传递
更新任务时候设置参数,如图:
运行任务后台便可以接受到参数:
@XxlJob("demoJobHandler")public void demoJobHandler() throws Exception {XxlJobHelper.log("XXL-JOB, Hello World.");String jobParam = XxlJobHelper.getJobParam();log.info("jobParam:{}" , jobParam);for (int i = 0; i < 5; i++) {XxlJobHelper.log("beat at:" + i);}// default success}
结果:
2024-08-04 15:39:32 JRebel: Reconfiguring reprocessed bean 'sampleService' [com.ruoyi.job.service.SampleService]
2024-08-04 15:39:36 [xxl-job, JobThread-1-1722757089189] INFO com.ruoyi.job.service.SampleService- jobParam:type=1&flag=true
当然,JSON也可以传递都后台,按需求进行处理即可
2024-08-04 15:43:09 [xxl-job, EmbedServer bizThreadPool-1028558242] INFO c.x.job.core.executor.XxlJobExecutor- >>>>>>>>>>> xxl-job regist JobThread success, jobId:1, handler:com.xxl.job.core.handler.impl.MethodJobHandler@6146a40f[class com.ruoyi.job.service.SampleService#demoJobHandler] 2024-08-04 15:43:09 [xxl-job, JobThread-1-1722757389734] INFO com.ruoyi.job.service.SampleService- jobParam:{“type”:1,&"code":0}
五、轮询策略
前置场景,启动2个端口不一样的执行器8080和8081端口,则会在2个注册的节点上轮流访问
总结:
- 执行器交替执行,减少服务器压力,实现负载均衡
- 如果一个节点挂了则会交给另一个节点处理
六、分片广播
场景:如果我们要同时通知1万个对象,当前有5个执行器,采用轮询则要循环1万次,所以此场景就应该采用分片广播策略
新增分片广播任务
后台处理:
对分片总是进行取余模拟,分片执行
/*** 2、分片广播任务*/@XxlJob("shardingJobHandler")public void shardingJobHandler() throws Exception {// 分片索引int shardIndex = XxlJobHelper.getShardIndex();// 分片总数int shardTotal = XxlJobHelper.getShardTotal();//循环10次,模拟分片广播for (int i = 0; i < 10; i++) {//取余模拟,分片执行if (i % shardTotal == shardIndex) {XxlJobHelper.log("第 {} 片, 命中分片开始处理", i);}}}
执行结果:
执行新增分片广播任务,生成2条调用日志
分别查看日志内容:
分片0执行了,第 0、4、6、8任务
分片1执行了,第 1、3、5、7、9任务
这样对比轮询去处理该场景任务,极大的提升了任务处理的速度
分片广播的应用场景
- 数据处理任务:如对大量数据进行清洗、分析、转换等操作,可以将任务拆分成多个小任务,分布式地执行。
- 分布式计算任务:如对大规模数据进行机器学习、深度学习等计算,可以将计算任务拆分成多个小任务,分布式地执行,加速计算过程。
- 并发请求任务:如对多个服务进行并发请求,可以将请求拆分成多个小请求,分布式地执行,提高请求的并发处理能力。
注意事项:
- 在实现分片广播任务时,需要确保执行器集群中的执行器回调地址(xxl.job.admin.addresses)保持一致。
- 同一个执行器集群内的AppName(xxl.job.executor.appname)也需要保持一致。
- 在任务执行过程中,需要考虑并发执行的情况,确保任务逻辑的正确性。
总之,XXL-JOB的分片广播功能为分布式任务调度提供了一种高效、灵活的实现方式,适用于多种需要并行处理的任务场景。
七、命令行任务
演示window下执行命令行,linux也是一样的
1-先新记事本建文件 mkdir.bat文件,内容如下:
命令行执行命令:新建一个文件夹,yyyy-MM-dd HH-mm-ss 作为文件夹名称
@echo off
setlocal enabledelayedexpansion:: 获取当前日期
for /f "tokens=2-4 delims=/-" %%a in ('date /t') do (set YY=%%cset MM=%%aset DD=%%b
):: 获取当前时间
for /f "tokens=1-3 delims=: " %%h in ('time /t') do (set HH=%%hset MM=%%iset SS=%%j
):: 格式化日期和时间字符串以适应文件夹名
set "folderName=%YY%-%MM%-%DD%_%HH%-%MM%-%SS%"
:: 创建文件夹
md "D:\CPanFiles\download\!folderName!"
2-创建调度任务:
任务运行参数为上面mkdir.bat文件的地址,我放在D盘downlad文件夹下面
3-commandJobHandler 运行命令行后台如下:
获取定时任务参数,执行命令行
@XxlJob("commandJobHandler")public void commandJobHandler() throws Exception {//1-获取参数String command = XxlJobHelper.getJobParam();int exitValue = -1;BufferedReader bufferedReader = null;try {// commandProcessBuilder processBuilder = new ProcessBuilder();processBuilder.command(command);processBuilder.redirectErrorStream(true);// 执行命令行Process process = processBuilder.start();//Process process = Runtime.getRuntime().exec(command);//字符流 读取BufferedInputStream bufferedInputStream = new BufferedInputStream(process.getInputStream());bufferedReader = new BufferedReader(new InputStreamReader(bufferedInputStream));// 记录到日志表String line;while ((line = bufferedReader.readLine()) != null) {XxlJobHelper.log(line);}process.waitFor();exitValue = process.exitValue();} catch (Exception e) {XxlJobHelper.log(e);} finally {if (bufferedReader != null) {bufferedReader.close();}}if (exitValue == 0) {// default success} else {XxlJobHelper.handleFail("command exit value(" + exitValue + ") is failed");}}
前台点击执行任务:生成文件夹成功
八、HTTP平台请求
这里模拟发送请求到百度
httpJobHandler 后台:
拿到参数,发送HTTP请求,返回请求结果
@XxlJob("httpJobHandler")public void httpJobHandler() throws Exception {// param parseString param = XxlJobHelper.getJobParam();if (param == null || param.trim().length() == 0) {XxlJobHelper.log("param[" + param + "] invalid.");XxlJobHelper.handleFail();return;}//获取http请求参数String[] httpParams = param.split("\n");String url = null;String method = null;String data = null;for (String httpParam : httpParams) {if (httpParam.startsWith("url:")) {url = httpParam.substring(httpParam.indexOf("url:") + 4).trim();}if (httpParam.startsWith("method:")) {method = httpParam.substring(httpParam.indexOf("method:") + 7).trim().toUpperCase();}if (httpParam.startsWith("data:")) {data = httpParam.substring(httpParam.indexOf("data:") + 5).trim();}}//校验参数if (url == null || url.trim().length() == 0) {XxlJobHelper.log("url[" + url + "] invalid.");XxlJobHelper.handleFail();return;}if (method == null || !Arrays.asList("GET", "POST").contains(method)) {XxlJobHelper.log("method[" + method + "] invalid.");XxlJobHelper.handleFail();return;}boolean isPostMethod = method.equals("POST");// request 发送http请求HttpURLConnection connection = null;BufferedReader bufferedReader = null;try {// connectionURL realUrl = new URL(url);connection = (HttpURLConnection) realUrl.openConnection();// connection settingconnection.setRequestMethod(method);connection.setDoOutput(isPostMethod);connection.setDoInput(true);connection.setUseCaches(false);connection.setReadTimeout(5 * 1000);connection.setConnectTimeout(3 * 1000);connection.setRequestProperty("connection", "Keep-Alive");connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");connection.setRequestProperty("Accept-Charset", "application/json;charset=UTF-8");// do connectionconnection.connect();// dataif (isPostMethod && data != null && data.trim().length() > 0) {DataOutputStream dataOutputStream = new DataOutputStream(connection.getOutputStream());dataOutputStream.write(data.getBytes("UTF-8"));dataOutputStream.flush();dataOutputStream.close();}// valid StatusCode :获取http状态int statusCode = connection.getResponseCode();if (statusCode != 200) {throw new RuntimeException("Http Request StatusCode(" + statusCode + ") Invalid.");}// result :获取返回结果bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));StringBuilder result = new StringBuilder();String line;while ((line = bufferedReader.readLine()) != null) {result.append(line);}String responseMsg = result.toString();XxlJobHelper.log(responseMsg);return;} catch (Exception e) {XxlJobHelper.log(e);XxlJobHelper.handleFail();return;} finally {try {if (bufferedReader != null) {bufferedReader.close();}if (connection != null) {connection.disconnect();}} catch (Exception e2) {XxlJobHelper.log(e2);}}}
执行结果:跳转到百度登录页面:
9-生命周期
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")
init :当 XXL-JOB 框架启动并加载此任务时,会尝试调用标注了
@XxlJob
注解的类中的init
方法(如果存在), 这可以用于执行一些初始化操作,比如资源加载、数据库连接初始化等destroy 当 XXL-JOB 框架停止或卸载此任务时,会尝试调用标注了
@XxlJob
注解的类中的destroy
方法(如果存在),这可以用于执行一些清理操作,比如关闭数据库连接、释放资源等。
@XxlJob(value = "demoJobHandler2", init = "init", destroy = "destroy")public void demoJobHandler2() throws Exception {XxlJobHelper.log("XXL-JOB, Hello World.");}public void init() {log.info("init");}public void destroy() {log.info("destory");}
十、报警邮件配置
1-以qq邮箱举例接受错误报警提醒进入到安全设置(页面右上角)
2-生成授权码:
3-后台配置下 授权码(上面生成的 ) 以及 邮箱账号
--- # 邮件配置
spring:mail:from: 13361831qq.comhost: smtp.qq.comusername: 13361831qq.com# 邮箱授权码password: ixxxj0000jfoghbihport: 25properties:mail:smtp:auth: truesocketFactory:class: javax.net.ssl.SSLSocketFactorystarttls:enable: truerequired: true
4- 创建定时任务绑定邮箱
执行任务结果:收到信息成功
相关文章:

RuoYi-Vue-Plus (XXL-JOB任务调度中心二:配置管理与定时任务编写、执行策略、命令行任务、邮件报警等等
一、后端xxl job的配置属性介绍 enabled : 是否开启执行器,如果为false,调度中心就调用不了后端定时任务admin-addresses:调度中心的地址,多个则可以逗号拼接: url1,url2,url3access-token: 执行器通讯TOKEN ,必须和x…...

【docker】虚拟化与docker基础
一、虚拟化 1.虚拟化概述 什么是虚拟化? 虚拟化:将应用程序和系统内核资源进行解耦,以操作系统级别进行隔离,目的是提高资源利用率 2、虚拟化的功能 将虚拟化的性能优化趋近于物理资源的性能,主要用于提高资源利用…...

Vue3安装ffmpeg做视频截取报错
通过 yarn 安装 ffmpeg 时报错。 即,执行以下指令时报错: yarn add ffmpeg/ffmpeg^0.10.0 yarn add ffmpeg/core^0.10.0错误信息: node_modules\pngquant-bin: Command failed. Error: pngquant failed to build, make sure that libpng-d…...
如何在 Java 中实现自定义的排序算法?
在Java中实现自定义排序算法的步骤如下: 创建一个类,实现Java的Comparator接口,该接口包含一个compare方法,用于比较两个对象的大小。在compare方法中,根据自定义的排序规则,比较两个对象的大小并返回-1、…...
【Homebrew】brew 命令
Brew(也称为Homebrew)是Mac OS上的一款包管理器,它允许用户通过简单的命令行界面来安装、更新、卸载和管理软件包。以下是一些常用的Brew命令及其功能说明: 安装与卸载 安装Brew 命令(适用于大多数用户,可…...
【https】无法安装OpenSSL时如何在局域网开通https服务
【背景】 做Stream传输服务,需要用到fetch方法,所以自然也需要https服务。 公司的开发机由于某些管理上的原因无法直接安装openssl for win的安装包。 【分析】 没有命令行工具,就试试看万能的python包吧,直接安装cryptography包。 pip install cryptography【方法】 …...

OpenGL实现3D游戏编程【连载1】——初探3D世界
1、前言 在我学习C的过程中,研究了一下OpenGL编程,打开了3D世界的编程世界,3D世界的效果还是相当不错。而且OpenGL能够支持跨平台兼容,是不错的学习方向,于是就自己学习了网上的很多教程,并将所有学到的知…...

工程化实践:工程配置化设计
文内项目 Github:XIAOJUSURVEY 配置化是很灵活且很常见的使用,那XIAOJUSURVEY里有哪些地方应用到了呢? 基础模板 问卷模板 在创建问卷时,我们提供了多种问卷类型选择,例如普通问卷、投票、报名、NPS等。 为了实…...

浏览器事件循环详解
1. 浏览器的进程模型 1.1. 何为进程? 程序运行需要有它自己的专属内存空间,可以把这块内存空间简单的理解为进程。 每个应用至少有一个进程,进程之间相互独立,即使要通信,也需要双方同意。 1.2. 何为线程?…...
Linux:线程管理(线程创建、线程退出、线程回收、线程分离、其它线程函数)
线程管理 (1)What(什么是线程管理) 对程序中线程的创建、调度、同步、退出、回收等操作进行有效的控制和协调 (2)Why(为什么要管理线程) 充分利用系统资源,提高程序的并发的性能和稳定性。但如果管理不当,…...

【JVM】常见面试题
🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 文章目录 1. JVM 中的内存区域划分2. JVM 的类加载机制2.1 加载(Loading)✨双亲委派模型2.2 验证(Verification)2.3 准…...

0805作业+梳理
一、作业: 代码: create.c #include<myhead.h> int main(int argc, const char *argv[]) {//创建一个有名管道文件if(mkfifo("./linux",0664)-1){perror("mkfifo linux error");return -1;}getchar();system("rm linux…...

Java高并发编程详解教程(对高并发更深一层的领悟和体会 电子版)
前言 第一部分主要阐述Thread的基础知识,详细介绍线程的API使用、线程安全、线程间数据通信以及如何保护共享资源等内容,它是深入学习多线程内容的基础。 在第二部分中之所以引人 ClassLoader,是因为 ClassLoader 与线程不无关系࿰…...
字符串中的第一个唯一字符
给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。 s 只包含小写字母 示例 1: 输入: s "leetcode" 输出: 0示例 2: 输入: s "loveleetcode" 输出: 2示例 3: 输…...

leetcode数论(3044. 出现频率最高的质数)
前言 经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。现阶段开始专项练习。 描述 给你一个大小为 m x n 、下标从 0 开始的二维矩阵 mat 。在每个单元格,你可以按以下方式生成数字: 最多有 8 条路径可以选择࿱…...

70.加载功能菜单功能设计
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 内容参考于:易道云信息技术研究院 上一个内容:69.搭建分析工具界面 以 69.搭建分析工具界面 它的代码为基础进行修改 效果图…...

在线Banner设计工具大比拼:谁更胜一筹
在数字营销的时代,一个吸引眼球的 Banner 广告是吸引潜在客户、提高品牌知名度的关键。为了帮助营销人员和设计师快速创建专业的 Banner 广告,市面上出现了多种易于使用的 Banner 设计工具。本文将介绍几个受欢迎的 Banner 设计工具,包括即时…...
C++ STL copy, move 用法
一:功能 正向(从前向后的顺序)拷贝/移动操作,将一个容器元素拷贝/移动到另一容器中。 二:用法 #include <iostream> #include <vector> #include <algorithm>int main() {std::vector<std::str…...

MoonBit 周报 Vol.52:增加类型别名的支持、错误类型声明方式说明、MoonBit AI 支持生成文档等!
weekly 2024-08-05 MoonBit更新 JSON字面量支持array spread。 let xs: Array[json.JsonValue] [1, 2, 3, 4] let _: json.JsonValue [1, ..xs]增加了类型别名的支持,主要是为了渐进式代码重构和迁移,而不是某种给类型简短名字的机制。例如…...

Android开发之事件分发
#来自ウルトラマンゼロ(哉阿斯) 1 Activity 构成 平常布局展示在ContentView中。 2 事件分发 事件分发的本质其实就是把事件(Touch)封装成 MotionEvent 类,然后传递给 View 的层级处理。 MotionEvent 事件类型主要有…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...