xxl-job 在 Java 项目的使用 以一个代驾项目中的订单模块举例
能搜到这里的最起码一定知道 xxl-job 是用来干什么的,我就不多啰嗦怎么下载以及它的历史了
首先我们要知道 xxl-job 这个框架的结构,如下图:
xxl-job-master:xxl-job-admin:调度中心xxl-job-core:公共依赖xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;xxl-job-executor-sample-frameless:无框架版本;
将项目拉到本地后打开目录结构就是张这个样子的
我们首先要打开 /xxl-job-master/doc/db/tables_xxl_job.sql 这个目录,然后执行调度数据库的初始化脚本,这时我们就可以去部署调度中心模块了(本地用户直接启动 SpringBoot 启动类就好了),记得启动之前先修改一下配置文件。。。
项目启动好之后就可以通过 http://your_project_ip:8080/xxl-job-admin 去访问调度中心
默认登录账号 “admin/123456”, 登录后运行界面如下图所示:

这样调度中心就启动好啦!!!
然后我们要在我们的项目中启动执行器项目
首先确保引入了依赖(使用 Maven ,不是用 Maven 的友友自行百度)
<!-- xxl-job-core -->
<dependency><groupId>com.xuxueli</groupId><artifactId>xxl-job-core</artifactId><version>2.4.1-SNAPSHOT</version>
</dependency>
然后就是编辑配置文件,具体的其实就是抄 xxl-job 示例模块的配置文件,我就贴到这了
### 调度中心部署根地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 执行器通讯TOKEN [选填]:非空时启用;
xxl.job.accessToken=
### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
xxl.job.executor.appname=xxl-job-executor-sample
### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
xxl.job.executor.address=
### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
xxl.job.executor.ip=
### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
xxl.job.executor.port=9999
### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
xxl.job.executor.logretentiondays=30
配置文件编辑完毕然后就该进行组件配置了,具体的就是将xxl-job-executor-sample-springboot 执行器项目的XxlJobConfig类复制过来
package com.atguigu.daijia.dispatch.xxl.config;import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class XxlJobConfig {private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);@Value("${xxl.job.admin.addresses}")private String adminAddresses;@Value("${xxl.job.accessToken}")private String accessToken;@Value("${xxl.job.executor.appname}")private String appname;@Value("${xxl.job.executor.address}")private String address;@Value("${xxl.job.executor.ip}")private String ip;@Value("${xxl.job.executor.port}")private int port;@Value("${xxl.job.executor.logpath}")private String logPath;@Value("${xxl.job.executor.logretentiondays}")private int logRetentionDays;@Beanpublic XxlJobSpringExecutor xxlJobExecutor() {logger.info(">>>>>>>>>>> xxl-job config init.");XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();xxlJobSpringExecutor.setAdminAddresses(adminAddresses);xxlJobSpringExecutor.setAppname(appname);xxlJobSpringExecutor.setAddress(address);xxlJobSpringExecutor.setIp(ip);xxlJobSpringExecutor.setPort(port);xxlJobSpringExecutor.setAccessToken(accessToken);xxlJobSpringExecutor.setLogPath(logPath);xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);return xxlJobSpringExecutor;}/*** 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;** 1、引入依赖:* <dependency>* <groupId>org.springframework.cloud</groupId>* <artifactId>spring-cloud-commons</artifactId>* <version>${version}</version>* </dependency>** 2、配置文件,或者容器启动变量* spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'** 3、获取IP* String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();*/}```
到这里其实我们就已经将 xxl-job 集成到我们的项目中了
然后我们编写一个测试方法```java
package com.atguigu.daijia.dispatch.xxl.job;import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;@Slf4j
@Component
public class DispatchJobHandler {@XxlJob("firstJobHandler")public void firstJobHandler() {log.info("xxl-job项目集成测试");}
}
在调度中心配置,图片中 JobHandler 的名字要和注解中 @XxlJob(“firstJobHandler”) 的名字一致
这样我们就可以在控制台看见啦!!
代码方式实现动态增删改查
但是这样我们只能通过图形化界面的方式操作,及其不方便,所以我们通过代码的方式进行动态创建,下面就以代驾项目中的订单模块举例
首先我们要在xxl-job-admin模块,添加改造后的api接口(我们自己的),如下:
@RequestMapping("/addJob")
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> addJobInfo(@RequestBody XxlJobInfo jobInfo) {return xxlJobService.add(jobInfo);
}@RequestMapping("/updateJob")
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> updateJob(@RequestBody XxlJobInfo jobInfo) {return xxlJobService.update(jobInfo);
}@RequestMapping("/removeJob")
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> removeJob(@RequestBody XxlJobInfo jobInfo) {return xxlJobService.remove(jobInfo.getId());
}@RequestMapping("/stopJob")
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> pauseJob(@RequestBody XxlJobInfo jobInfo) {return xxlJobService.stop(jobInfo.getId());
}@RequestMapping("/startJob")
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> startJob(@RequestBody XxlJobInfo jobInfo) {return xxlJobService.start(jobInfo.getId());
}@RequestMapping("/addAndStartJob")
@ResponseBody
@PermissionLimit(limit = false)
public ReturnT<String> addAndStartJob(@RequestBody XxlJobInfo jobInfo) {ReturnT<String> result = xxlJobService.add(jobInfo);int id = Integer.valueOf(result.getContent());xxlJobService.start(id);//立即执行一次JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, jobInfo.getExecutorParam(), "");return result;
}
说明:排除登录校验的注解 @PermissionLimit(limit = false)
完整配置:
xxl:job:admin:# 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册addresses: http://139.198.30.131:8080/xxl-job-admin# addresses: http://localhost:8080/xxl-job-admin# 执行器通讯TOKEN [选填]:非空时启用accessToken: executor:# 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册appname: xxl-job-executor-sample# 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。address:# 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";ip:# 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;port: 9999# 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;logpath: /data/applogs/xxl-job/jobhandler# 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;logretentiondays: 30client:jobGroupId: 1addUrl: ${xxl.job.admin.addresses}/jobinfo/addJobremoveUrl: ${xxl.job.admin.addresses}/jobinfo/removeJobstartJobUrl: ${xxl.job.admin.addresses}/jobinfo/startJobstopJobUrl: ${xxl.job.admin.addresses}/jobinfo/stopJobaddAndStartUrl: ${xxl.job.admin.addresses}/jobinfo/addAndStartJob
重点就是下面的 client 里面的内容(${xxl.job.admin.addresses} 这部分内容自己在配置文件中配置好自己的 http 接口地址就好)
然后在订单模块创建配置类:
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Data
@Component
@ConfigurationProperties(prefix = "xxl.job.client")
public class XxlJobClientConfig {private Integer jobGroupId;private String addUrl;private String removeUrl;private String startJobUrl;private String stopJobUrl;private String addAndStartUrl;
}
配置好自己的客户端
package com.atguigu.daijia.dispatch.xxl.client;import com.alibaba.fastjson.JSONObject;
import com.atguigu.daijia.common.execption.GuiguException;
import com.atguigu.daijia.common.result.ResultCodeEnum;
import com.atguigu.daijia.dispatch.xxl.config.XxlJobClientConfig;
import com.atguigu.daijia.model.entity.dispatch.XxlJobInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;/*** https://dandelioncloud.cn/article/details/1598865461087518722*/
@Slf4j
@Component
public class XxlJobClient {@Autowiredprivate XxlJobClientConfig xxlJobClientConfig;@Autowiredprivate RestTemplate restTemplate;@SneakyThrowspublic Long addJob(String executorHandler, String param, String corn, String desc){XxlJobInfo xxlJobInfo = new XxlJobInfo();xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId());xxlJobInfo.setJobDesc(desc);xxlJobInfo.setAuthor("qy");xxlJobInfo.setScheduleType("CRON");xxlJobInfo.setScheduleConf(corn);xxlJobInfo.setGlueType("BEAN");xxlJobInfo.setExecutorHandler(executorHandler);xxlJobInfo.setExecutorParam(param);xxlJobInfo.setExecutorRouteStrategy("FIRST");xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW");xxlJobInfo.setExecutorTimeout(0);xxlJobInfo.setExecutorFailRetryCount(0);HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);String url = xxlJobClientConfig.getAddUrl();ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);if(response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {log.info("增加xxl执行任务成功,返回信息:{}", response.getBody().toJSONString());//content为任务idreturn response.getBody().getLong("content");}log.info("调用xxl增加执行任务失败:{}", response.getBody().toJSONString());throw new GuiguException(ResultCodeEnum.XXL_JOB_ERROR);}public Boolean startJob(Long jobId) {XxlJobInfo xxlJobInfo = new XxlJobInfo();xxlJobInfo.setId(jobId.intValue());HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);String url = xxlJobClientConfig.getStartJobUrl();ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);if(response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {log.info("启动xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString());return true;}log.info("启动xxl执行任务失败:{},返回信息:{}", jobId, response.getBody().toJSONString());throw new GuiguException(ResultCodeEnum.XXL_JOB_ERROR);}public Boolean stopJob(Long jobId) {XxlJobInfo xxlJobInfo = new XxlJobInfo();xxlJobInfo.setId(jobId.intValue());HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);String url = xxlJobClientConfig.getStopJobUrl();ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);if(response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {log.info("停止xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString());return true;}log.info("停止xxl执行任务失败:{},返回信息:{}", jobId, response.getBody().toJSONString());throw new GuiguException(ResultCodeEnum.XXL_JOB_ERROR);}public Boolean removeJob(Long jobId) {XxlJobInfo xxlJobInfo = new XxlJobInfo();xxlJobInfo.setId(jobId.intValue());HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);String url = xxlJobClientConfig.getRemoveUrl();ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);if(response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {log.info("删除xxl执行任务成功:{},返回信息:{}", jobId, response.getBody().toJSONString());return true;}log.info("删除xxl执行任务失败:{},返回信息:{}", jobId, response.getBody().toJSONString());throw new GuiguException(ResultCodeEnum.XXL_JOB_ERROR);}public Long addAndStart(String executorHandler, String param, String corn, String desc) {XxlJobInfo xxlJobInfo = new XxlJobInfo();xxlJobInfo.setJobGroup(xxlJobClientConfig.getJobGroupId());xxlJobInfo.setJobDesc(desc);xxlJobInfo.setAuthor("qy");xxlJobInfo.setScheduleType("CRON");xxlJobInfo.setScheduleConf(corn);xxlJobInfo.setGlueType("BEAN");xxlJobInfo.setExecutorHandler(executorHandler);xxlJobInfo.setExecutorParam(param);xxlJobInfo.setExecutorRouteStrategy("FIRST");xxlJobInfo.setExecutorBlockStrategy("SERIAL_EXECUTION");xxlJobInfo.setMisfireStrategy("FIRE_ONCE_NOW");xxlJobInfo.setExecutorTimeout(0);xxlJobInfo.setExecutorFailRetryCount(0);HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<XxlJobInfo> request = new HttpEntity<>(xxlJobInfo, headers);String url = xxlJobClientConfig.getAddAndStartUrl();ResponseEntity<JSONObject> response = restTemplate.postForEntity(url, request, JSONObject.class);if(response.getStatusCode().value() == 200 && response.getBody().getIntValue("code") == 200) {log.info("增加并开始执行xxl任务成功,返回信息:{}", response.getBody().toJSONString());//content为任务idreturn response.getBody().getLong("content");}log.info("增加并开始执行xxl任务失败:{}", response.getBody().toJSONString());throw new GuiguException(ResultCodeEnum.XXL_JOB_ERROR);}}
这样操作之后就可以在接口中调用自己的 xxl-job 客户端进行定时任务调用啦
相关文章:
xxl-job 在 Java 项目的使用 以一个代驾项目中的订单模块举例
能搜到这里的最起码一定知道 xxl-job 是用来干什么的,我就不多啰嗦怎么下载以及它的历史了 首先我们要知道 xxl-job 这个框架的结构,如下图: xxl-job-master:xxl-job-admin:调度中心xxl-job-core:公共依赖…...
Alibaba开发规范_异常日志之日志规约:最佳实践与常见陷阱
文章目录 引言1. 使用SLF4J日志门面规则解释代码示例正例反例 2. 日志文件的保存时间规则解释 3. 日志文件的命名规范规则解释代码示例正例反例 4. 使用占位符进行日志拼接规则解释代码示例正例反例 5. 日志级别的开关判断规则解释代码示例正例反例 6. 避免重复打印日志规则解释…...
【数据分析】案例03:当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib)
当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib) 当当网近30日热销书籍官网写在前面 实验目的:实现当当网近30日热销图书的数据采集与可视化分析。 电脑系统:Windows 使用软件:Visual Studio Code Python版本:python 3.12.4 技术需求:scrapy、…...
需求分析应该从哪些方面来着手做?
需求分析一般可从以下几个方面着手: 业务需求方面 - 与相关方沟通:与业务部门、客户等进行深入交流,通过访谈、问卷调查、会议讨论等方式,明确他们对项目的期望、目标和整体业务需求,了解项目要解决的业务问题及达成的…...
申博经验贴
1. 所谓申博,最重要的就是定制的海投 分成两个部分 1. 定制 要根据每个教授去写不同的,一定不要泛泛的去写,一定要非常非常的具体,要引起教授的兴趣。每个教授每天都会收到几十封邮件,所以要足够的引起教授的注意&a…...
SpringAI 人工智能
随着 AI 技术的不断发展,越来越多的企业开始将 AI 模型集成到其业务系统中,从而提升系统的智能化水平、自动化程度和用户体验。在此背景下,Spring AI 作为一个企业级 AI 框架,提供了丰富的工具和机制,可以帮助开发者将…...
虚幻基础17:动画层接口
能帮到你的话,就给个赞吧 😘 文章目录 animation layer interface animation layer interface 动画层接口:动画图表的集。仅有名字。 添加到动画蓝图中,由动画蓝图实现动画图表。...
SQLAlchemy 2.0的简单使用教程
SQLAlchemy 2.0相比1.x进行了很大的更新,目前网上的教程不多,以下以链接mysql为例介绍一下基本的使用方法 环境及依赖 Python:3.8 mysql:8.3 Flask:3.0.3 SQLAlchemy:2.0.37 PyMySQL:1.1.1使用步骤 1、创建引擎,链接到mysql engine crea…...
Codeforces Round 1002 (Div. 2) A-D
复活!年后首场!本期封面是我自己AI弄的图 A - Milya and Two Arrays 题意 给两个所有数字出现次数都大于2的数组,问能不能修改排序之后对应位置相加得到新的数组使不同数字个数达到3 思路 直接计数就行了,不同的数字匹配一下…...
OpenGL学习笔记(七):Camera 摄像机(视图变换、LookAt矩阵、Camera类的实现)
文章目录 摄像机/观察空间/视图变换LookAt矩阵移动相机(处理键盘输入)移动速度欧拉角移动视角(处理鼠标输入)缩放场景(处理滚轮输入)Camera类 摄像机/观察空间/视图变换 在上一节变换中,我们讨…...
『VUE』vue-quill-editor富文本编辑器添加按钮houver提示(详细图文注释)
目录 预览效果新建一个config.js存放标题编写添加提示的方法调用添加标题方法的生命周期总结 欢迎关注 『VUE』 专栏,持续更新中 欢迎关注 『VUE』 专栏,持续更新中 预览效果 新建一个config.js存放标题 export const titleConfig [{ Choice: .ql-bold…...
如何使用 DeepSeek 和 Dexscreener 构建免费的 AI 加密交易机器人?
我使用DeepSeek AI和Dexscreener API构建的一个简单的 AI 加密交易机器人实现了这一目标。在本文中,我将逐步指导您如何构建像我一样的机器人。 DeepSeek 最近发布了R1,这是一种先进的 AI 模型。您可以将其视为 ChatGPT 的免费开源版本,但增加…...
Kafka流式计算架构
引言 Kafka 凭借其卓越的架构设计,具备极为高效的流式计算能力,在海量数据环境下,依然能够以惊人的速度实现消息的高性能消费,轻松应对高并发、低延迟的严苛业务需求。无论是实时数据处理、复杂事件分析,还是大规模数…...
C++泛型编程06(默认模板实参)
文章目录 1.4 默认模板实参 (Default Template Arguments)示例:灵活定义返回类型 当然,这里是对关于默认模板实参(Default Template Arguments)的内容进行了改进和优化后的叙述: 1.4 默认模板实参 (Default Template Arguments) 在C中&…...
微信登录模块封装
文章目录 1.资质申请2.combinations-wx-login-starter1.目录结构2.pom.xml 引入okhttp依赖3.WxLoginProperties.java 属性配置4.WxLoginUtil.java 后端通过 code 获取 access_token的工具类5.WxLoginAutoConfiguration.java 自动配置类6.spring.factories 激活自动配置类 3.com…...
SRS代码目录
代码目录: src/目录下核心代码: core:核心功能模块,包括日志、配置、错误处理等;protocol:实现RTMP、HTTP-FLV、HLS等协议的模块;app:应用层的实现,包括流的发布、播放…...
C++STL(一)——string类
目录 一、string的定义方式二、 string类对象的容量操作三、string类对象的访问及遍历操作四、string类对象的修改操作五、string类非成员函数 一、string的定义方式 string是个管理字符数组的类,其实就是字符数组的顺序表。 它的接口也是非常多的。本章介绍一些常…...
机器学习--1.KNN机器学习入门
1、机器学习概述 1.1、什么是机器学习 机器学习(Machine Learning)是人工智能(Artificial Intelligence)领域的一个子集,它主要关注如何让计算机系统通过经验学习(数据)并自动改进性能。机器学…...
Adaptive LLM Transformer²
看到了一个不错的论文https://arxiv.org/pdf/2501.06252 TRANSFORMER-SQUARED: SELF-ADAPTIVE LLMS 挺有意思的,是一家日本AI公司SakanaAI的论文(我以前写过他们的不训练提升模型的能力的文章,感兴趣可以去翻)它家有Lion Jones坐镇…...
三路排序算法
三路排序算法 引言 排序算法是计算机科学中基础且重要的算法之一。在数据分析和处理中,排序算法的效率直接影响着程序的执行速度和系统的稳定性。本文将深入探讨三路排序算法,包括其原理、实现和应用场景。 一、三路排序算法的原理 三路排序算法是一…...
代码随想录day27
669. /** lc appleetcode.cn id669 langcpp** [669] 修剪二叉搜索树*/// lc codestart /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}…...
基于LabVIEW的Modbus-RTU设备通信失败问题分析与解决
在使用 LabVIEW 通过 Modbus-RTU 协议与工业设备进行通信时,可能遇到无法正常发送或接收指令的问题。常见原因包括协议参数配置错误、硬件连接问题、数据帧格式不正确等。本文以某 RGBW 控制器调光失败为例,提出了一种通用的排查思路,帮助开发…...
1. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--前言
在我们的专栏《单体开发》中,我们实现了一个简单的记账软件的服务端,并且成功上线。随着用户数量的不断增长,问题逐渐开始显现。访问量逐渐增加,服务端的压力也随之加大。随着访问量的攀升,服务端的响应时间变得越来越…...
直方图:摄影中的视觉数据指南
目录 一、直方图基础:揭开它的神秘面纱 二、解读直方图类型:亮度与色彩的密码 (一)亮度直方图 (二)RGB 直方图 三、拍摄中巧用直方图:优化曝光与效果 (一)精准判断曝…...
一份完整系统化提升信息输出密度与逻辑严谨性的训练素材
一、方法 1. 理论基础与核心概念 1.1 信息输出密度 定义 信息输出密度可以理解为单位表达中所包含的有效信息量。它要求在有限的篇幅或时间内传递更多有价值、低冗余的信息。衡量指标 信息熵(Shannon Entropy):在信息论中,信息…...
CommonJS 和 ES6module 的区别
动态与静态 CommonJS 与 ES6 Module 最本质的区别在于前者对模块依赖的解决是“动态的”,而后者是“静态的”。在这里“动态”的含义是,模块依赖关系的建立发生在代码运行阶段:而“静态”则表示模块依赖关系的建立发生在代码编译阶段。 看一…...
IM 即时通讯系统-51-MPush开源实时消息推送系统
IM 开源系列 IM 即时通讯系统-41-开源 野火IM 专注于即时通讯实时音视频技术,提供优质可控的IMRTC能力 IM 即时通讯系统-42-基于netty实现的IM服务端,提供客户端jar包,可集成自己的登录系统 IM 即时通讯系统-43-简单的仿QQ聊天安卓APP IM 即时通讯系统-44-仿QQ即…...
前端 | JavaScript中的reduce方法
1. 什么是reduce reduce 方法是 JavaScript 中数组的重要方法之一,用于对数组中的元素进行累积计算。它接收一个回调函数作为参数,并返回一个最终计算结果。reduce 在许多场景下都非常有用,比如求和、数组扁平化、对象计数、数据转换等。 2…...
【Linux】从硬件到软件了解进程
个人主页~ 从硬件到软件了解进程 一、冯诺依曼体系结构二、操作系统三、操作系统进程管理1、概念2、PCB和task_struct3、查看进程4、通过系统调用fork创建进程(1)简述(2)系统调用生成子进程的过程〇提出问题①fork函数②父子进程关…...
2024-我的学习成长之路
因为热爱,无畏山海...
