前言

从事开发工作的同学,应该对定时任务的概念并不陌生,就是我们的系统在运行过程中能够自动执行的一些任务、工作流程,无需人工干预。常见的使用场景包括:数据库的定时备份、文件系统的定时上传云端服务、每天早上的业务报表数据生成等等,实现方式也是层出不穷,对于简单的任务,我们可能在代码里写个死循环一直判断是否触发执行即可,对于复杂的、或者定时任务的种类数量较多,需要严密监控管理的业务场景,我们需要一些专门的定时任务工具去处理。笔者用过的定时任务有三个,分别是QuartZ,XXL-JOB,Snail-Job,关于这三个工具,我做了一个表格用来区分其使用场景和特点。

对比维度QuartzXXL-JOB
项目定位经典的 Java 定时任务框架,专注于任务调度核心能力分布式任务调度平台,强调易用性和企业级特性轻量级分布式任务调度框架,注重性能和简洁性
核心架构单机 / 集群模式(基于数据库锁实现集群)中心化架构(调度中心 + 执行器)去中心化架构(无单独调度中心,节点对等)
任务触发方式基于 Cron 表达式、固定间隔、日历等支持 Cron 表达式、固定间隔、任务依赖、API 触发支持 Cron 表达式、固定间隔、事件触发
分布式能力需手动配置集群(依赖数据库同步状态)原生支持分布式部署,自动负载均衡原生分布式,节点动态发现,自动容错
任务管理需通过代码配置,无可视化界面提供 Web 控制台,支持任务 CRUD、启停、日志查看轻量控制台,支持基础任务管理和监控
失败重试支持简单重试策略(需手动配置)内置失败重试机制,可配置重试次数和间隔支持自定义重试策略,默认失败告警
任务依赖不直接支持,需手动实现依赖逻辑支持任务链式依赖、父子任务关系支持简单任务依赖,基于事件驱动
监控告警无内置监控,需集成第三方工具(如 Prometheus)内置监控面板,支持邮件、钉钉等告警方式支持指标暴露(适配 Prometheus),告警集成
性能表现单机性能稳定,集群模式下受数据库性能限制调度中心性能优异,支持高并发任务触发去中心化设计,减少网络开销,性能高效
学习成本中等(需理解 Job、Trigger、Scheduler 等核心概念)低(文档丰富,开箱即用,API 简洁)低(设计简洁,源码轻量,易于上手)
适用场景中小型应用、非分布式环境,或作为底层调度组件中大型分布式系统、企业级应用,需可视化管理微服务架构、轻量级应用、对性能敏感的场景
生态集成可集成 Spring、Spring Boot 等框架深度集成 Spring 生态,支持 Docker、K8s 部署支持 Spring Boot 自动配置,适配主流框架
社区活跃度老牌项目,社区成熟但更新较慢社区活跃,更新频繁,问题响应及时新兴项目,社区正在成长,维护积极
  1. Quartz:作为定时任务领域的 “老前辈”,其核心优势在于稳定性和灵活性,适合作为底层调度引擎,但在分布式场景下需要额外开发适配逻辑,更适合传统单体应用或对定制化要求高的场景。

  2. XXL-JOB:目前国内使用最广泛的分布式任务调度平台之一,凭借完善的功能和易用性成为企业级首选,尤其适合需要可视化管理、复杂任务依赖和高可靠性的场景(如电商定时任务、数据同步等)。

  3. Snail-Job:作为新兴框架,主打轻量和性能,去中心化设计减少了单点故障风险,适合微服务、云原生环境,或对部署复杂度和资源占用有严格要求的场景。

前两种笔者都在实际开发中使用过,相比Quartz,XXL-JOB功能更为强大,但是也是比较重了,所以我在网上寻找有没有类似的替代工具。哎还真让我找到了,就是snail-job,轻量级的分布式任务重试、任务调度平台,特别适合微服务项目,而且界面清爽颜值不错,简单好用,没有复杂配置,接下来的内容我会逐步介绍如何在我们的微服务项目种集成它。不过我在这里需要声明的一点是,企业级的大型项目,还是使用XXL-JOB,毕竟社区活跃,有很多技术支持,snail-job的很多技术问题,是需要付费才能获得解答,这一点让笔者不太舒服,而且开源也只开了一半,前端的代码给的是打包编译后的文件,不过一般的项目用着还是可以的。话不多说,直接上集成教程。


一、snail-job简介

snail-job的官网地址:官网

在这里插入图片描述

上面的是它的官网界面截图,snail-job分为服务端客户端两组概念,这里简单介绍下

  1. 服务端:用于管理和配置定时任务、监控定时任务的执行、告警配置等,总的来说就是定时任务的统筹调度中心
  2. 客户端:这个是需要我们自己开发的部分,开发语言目前支持Python、Java,后续会支持其他语言,比如Go语言,主要是我们用来写定时任务的执行逻辑的。

二、端口概念介绍

先介绍下snail-job集成涉及到的四个端口的概念,防止混淆不清

1.服务端应用端口:这个端口是后台服务端的管理web页面的入口端口,这个是可以自由配置修改的,snail-job的服务端和XXL-JOB一样有一个管理页面。
2. 服务端通讯端口:服务端对客户端暴露的用来通信的端口,默认是17888,可以修改。
3. 客户端应用端口:这是我们自己开发的客户端服务的应用端口,也是自定义配置的。
4. 客户端通讯端口:这个是我们开发的客户端对服务端暴露的进行通信的端口,这个官网给的配置默认值是1789,当然支持修改。

之所以是高性能通信,因为其内部使用了netty框架,除了应用端口,单独再搞两个通信端口,一是为了通信不被干扰,二是为了通信数据的安全考虑,可以使用各种加密技术。本质是将 “用户交互层” 和 “核心调度层” 解耦,在功能、协议、性能、安全等层面实现精细化管控,最终保障分布式任务调度的高效、稳定和可维护性。这一设计在主流分布式框架(如 XXL-Job、Dubbo)中也较为常见,是分布式系统架构的典型优化思路。


三、服务端集成部署

代码拉取地址如下

# Gitee
git clone https://gitee.com/aizuda/snail-job.git# GitHub
git clone https://github.com/aizuda/snail-job.git

国内用户直接使用gitee地址拉取就行,项目结构如下

在这里插入图片描述
项目拉下来后,笔者因为要和自己的微服务集成,所以对源码做了一些简单的修改,比如docker文件夹,就是我新加的,docker相关配置内容,dockerfile等。

还有就是,我把这个后端的服务也集成了nacos,使得能成功注册到nacos中去,以便能和客户端通信。下面是具体操作步骤。

引入nacos

在这里插入图片描述

如上图所示,在源码的相关路径下引入nacos依赖,一个是注册中心配置,一个是配置中心,这里的配置中心我其实是没有使用了,即只是把服务注册到了nacos上

 <!-- SpringCloud Alibaba Nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>2023.0.3.2</version></dependency><!-- SpringCloud Alibaba Nacos Config --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>2023.0.3.2</version></dependency>

application.yml文件修改

server:port: 9082servlet:context-path: /snail-jobspring:application:name: snail-job-serverprofiles:active: prodcloud:nacos:# 注册中心discovery:server-addr: ****:8848namespace: hulei-devgroup: DEFAULT_GROUPusername: ******password: ******# 配置中心config:import-check:enabled: falseserver-addr: ****:8848namespace: hulei-devgroup: DEFAULT_GROUPusername: ******password: ******file-extension: ymldatasource:name: snail_job## mysqldriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/snail_job?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghaiusername: rootpassword: root
#    url: jdbc:mysql://usteu-it.rwlb.rds.aliyuncs.com:3306/snail_job?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=Asia/Shanghai
#    username: usteu_dev
#    password: KDNT_dev999## postgres#    driver-class-name: org.postgresql.Driver#    url: jdbc:postgresql://localhost:5432/snail_job?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true#    username: root#    password: root## Oracle#    driver-class-name: oracle.jdbc.OracleDriver#    url: jdbc:oracle:thin:@//localhost:1521/XEPDB1#    username: snail_job#    password: SnailJob## SQL Server#    driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver#    url: jdbc:sqlserver://localhost:1433;DatabaseName=snail_job;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true#    username: SA#    password: SnailJob@24## mariadb#    driver-class-name: org.mariadb.jdbc.Driver#    url: jdbc:mariadb://localhost:3308/snail_job?useSSL=false&characterEncoding=utf8&useUnicode=true#    username: root#    password: root## dm8#    driver-class-name: dm.jdbc.driver.DmDriver#    url: jdbc:dm://127.0.0.1:5236#    username: SYSDBA#    password: SYSDBA001# kingbase#    driver-class-name: com.kingbase8.Driver#    url: jdbc:kingbase8://localhost:54321/test#    username: root#    password: roottype: com.zaxxer.hikari.HikariDataSourcehikari:connection-timeout: 30000minimum-idle: 5maximum-pool-size: 100auto-commit: trueidle-timeout: 30000pool-name: snail_jobmax-lifetime: 1800000web:resources:static-locations: classpath:admin/mybatis-plus:typeAliasesPackage: com.aizuda.snailjob.template.datasource.persistence.poglobal-config:db-config:where-strategy: NOT_EMPTYcapital-mode: falselogic-delete-value: 1logic-not-delete-value: 0configuration:map-underscore-to-camel-case: truecache-enabled: truelogging:config: classpath:logback-boot.xml
#    level:
#    ## 方便调试 SQL
#        com.aizuda.snailjob.template.datasource.persistence.mapper: debugsnail-job:retry-pull-page-size: 1000 # 拉取重试数据的每批次的大小job-pull-page-size: 1000 # 拉取重试数据的每批次的大小server-port: 17888  # 服务器端口log-storage: 7 # 日志保存时间(单位: day)rpc-type: grpc

从上面的yml文件可以看到,我的服务端的应用端口配置的是9082这个端口,关于服务端的通信端口,在如上文件底部所示为17888,这个是默认的,一般没必要不去修改它。

服务端使用的数据库,我用的是mysql,所以我注释了其他数据库的连接配置。一些建表的sql脚本自然也就是mysql相关的,sql脚本位置如下

在这里插入图片描述
把对应的sql脚本拷贝到,application.yml中,你配置的mysql数据库中执行即可,执行后的自动创建的数据库名称就叫snail-job

关于docker文件,我没有使用项目自带的doc/docker下的任何内容,而是我直接在项目根目录下创建了一个文件夹docker,里面配置了我自己的dockerfile,内容如下,给大家做个参考

# 基础镜像
FROM  openjdk:17-jdk
# author
MAINTAINER usteuENV JAVA_OPTS="-Xms1g -Xmx2g -XX:+UseG1GC"# 挂载目录
VOLUME /home/snailjob-server
# 创建目录
RUN mkdir -p /home/snailjob-server
# 指定路径
WORKDIR /home/snailjob-server
# 复制jar文件到路径
COPY ./jar/snail-job-server-exec.jar /home/snailjob-server/snail-job-server-exec.jar
# 启动系统服务
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar snail-job-server-exec.jar","-Duser.timezone=GMT+08"]

docker-compose.yml中有关snail-job服务端的service配置内容如下,可以看到,我映射了宿主机和容器的两个端口

  #snail-job的服务端docker部署,使用的是本地拉取的源码打包部署,非镜像snail-job-server:container_name: snail-job-serverbuild:context: ./snailjobServerdockerfile: dockerfileports:- "9082:9082"- "17888:17888"volumes:- /etc/localtime:/etc/localtime:ro# 添加日志限制,也可以全局限制,和services同级logging:driver: "json-file"options:max-size: "100m"max-file: "1"

读者朋友也可以不用docker部署,这完全看个人需求,核心是snail-job-server-exec.jar这个jar包,至于怎么部署使用随便。

snail-job-server-exec.jar

这个就是我们package后的可执行jar包了,里面包含服务端的前端页面内容,具体位置如下

在这里插入图片描述

笔者使用的工具是IDEA,打包时操作如下图所示,注意一定要勾选skipFrontend,否则就会打包失败,前面说了前端并没有给源码,对此笔者也无力吐槽,毕竟人家搞出来这个东西就是为了挣钱的,免费给你用也还算可以了,要求不要太高哈。

在这里插入图片描述

服务端启动登录

对面上面的配置,使用IDEA启动后登录界面如下

浏览器访问地址:http://localhost:9082/snail-job

在这里插入图片描述

默认登录用户admin,密码也是admin,可以修改密码,也可以新增普通用户进行权限管控,这个后面再说,先登录进去

在这里插入图片描述
可以看到一个在线机器,为服务端机器,同时nacos服务也多了一个snail-job-server的服务

在这里插入图片描述

新建命名空间

这个只有admin账户或者拥有管理员权限的账户才能新建,有一个默认的default,但我不想用,所以自己建了,名字什么的更专业点。

在这里插入图片描述

新建执行器组

上面选择新建的命名空间,然后新增执行器组,这里的token后面客户端会用到,比较重要

在这里插入图片描述

在这里插入图片描述

新建用户

在这里插入图片描述
这个比较简单了,就是新建用户,赋予对应执行器组的权限,也可以对admin用户密码进行修改,不再叙述。

告警通知配置

这个主要是用来针对定时任务执行异常时的通知配置,可以配置通知人,通知方式等,实际使用中一般是,针对某个组的某个定时任务去配置,设置对应的通知人。

在这里插入图片描述

定时任务配置

这个是核心了,支持按照固定时间间隔、cron表达式、指定时间点、工作流方式,具体请看官方文档介绍,十分详细了。
在这里插入图片描述

任务类型一般就是默认集群。集群模式下,一个任务会根据路由策略只打到一个节点上执行。
执行器选择自定义执行器,里面的名称是我们在客户端代码些定时任务逻辑时对应的,不是乱填的。

在这里插入图片描述


四、客户端开发部署

这部分内容需要我们自己在应用内开发了,也非常简单,就拿笔者的微服务项目来展示吧

在这里插入图片描述

创建一个snail-job的客户端微服务,也是要注册到nacos当中去的,pom文件主要内容如下

<!-- SpringCloud Alibaba Nacos --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!-- SpringCloud Alibaba Nacos Config --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--snail-job相关组件--><dependency><groupId>com.aizuda</groupId><artifactId>snail-job-client-starter</artifactId><version>${snail-job.version}</version></dependency><dependency><groupId>com.aizuda</groupId><artifactId>snail-job-client-job-core</artifactId><version>${snail-job.version}</version></dependency><dependency><groupId>com.aizuda</groupId><artifactId>snail-job-client-retry-core</artifactId><version>${snail-job.version}</version></dependency>

上面只是列举的必要的依赖,可能还需要其他依赖,比如数据库驱动等依赖。这个服务就是客户端服务了,客户端的应用端口我设置成了9081,yml配置文件如下

server:port: 9081spring:application:name: usteu-snailjobprofiles:active: @activatedProperties@cloud:nacos:# 注册中心discovery:server-addr: @nacosAddress@namespace: @nacosNamespace@group: DEFAULT_GROUPusername: nacospassword: KDNT_dev666# 配置中心config:server-addr: @nacosAddress@namespace: @nacosNamespace@group: DEFAULT_GROUPusername: nacospassword: KDNT_dev666file-extension: ymlshared-configs:- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

其中还有部分配置,我是放在nacos中了,关键配置如下:

snail-job:# 任务调度服务器信息server:# 服务器IP地址(或域名);集群时建议通过 nginx 做负载均衡host: 127.0.0.1# 服务器通讯端口(不是后台管理页面服务端口)port: 17888# 命名空间 【上面配置的空间的唯一标识】namespace: vL4pfYMz8vFf5m0PXItAVK_aA9pGpH6L# 接入组名【上面配置的组名称】注意: 若通过注解配置了这里的配置不生效group: usteu_group# 接入组 token 【上面配置的token信息】token: SJ_Wyz3dmsdbDOkDujOTSSoBjGQP1BMsVnj# 客户端绑定IP,必须服务器可以访问到;默认自动推断,在服务器无法调度客户端时需要手动配置host: 127.0.0.1# 指定客户端通讯端口,不配置默认 1789port: 1789# 是否开启enabled: true

这里客户端配置也是需要写上服务端的ip地址和通信端口号的,之前说过是17888,剩下的命名空间,组名称,以及执行器组对应的token,都可以登录服务端管理界面去查找,客户端的通讯端口,笔者这里配置的是1789,默认值也是这个。

定时任务编写

我根据官方提供的案例,写了一个测试的定时任务

import com.aizuda.snailjob.client.job.core.annotation.JobExecutor;
import com.aizuda.snailjob.client.job.core.dto.JobArgs;
import com.aizuda.snailjob.client.model.ExecuteResult;
import com.aizuda.snailjob.common.log.SnailJobLog;
import org.springframework.stereotype.Component;/*** 测试定时任务*/
@Component
@JobExecutor(name = "testJob")
public class TestJob {public ExecuteResult jobExecute(JobArgs jobArgs) {SnailJobLog.REMOTE.info("哈哈,测试成功了:"+jobArgs.getJobId() + " " + jobArgs.getJobParams());return ExecuteResult.success();}
}

这个@JobExecutor(name = “testJob”)就是核心注解了,testJob即为我们在服务端进行定时配置时设置的执行器名称,要对应上。

另外要注意的点是,再定义其他定时器时,方法名不要修改统一都是jobExecute,否则会执行报错,我估计是反射时会寻找这个固定的执行方法吧。具体的定时任务执行业务逻辑,在方法内部写即可。

如果你真想改的话,按照下面的方式改(我是觉得没有什么必要改):

@JobExecutor(name = "testJob",method=自定义方法名)

附上一张测试结果图

在这里插入图片描述


五、总结

以上内容简单介绍了snail-job的使用方法和集成步骤,具体细节,如有不明白的,可参考官方文档,学习测试。希望本文可以给各位带来帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90820.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90820.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/90820.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

依赖注入的逻辑基于Java语言

对于一个厨师&#xff0c;要做一道菜。传统的做法是&#xff1a;你需要什么食材&#xff0c;就自己去菜市场买什么。这意味着你必须知道去哪个菜市场、怎么挑选食材、怎么讨价还价等等。你不仅要会做菜&#xff0c;还要会买菜&#xff0c;职责变得复杂了。 而依赖注入就像是有一…

skywalking镜像应用springboot的例子

目录 1、skywalking-ui连接skywalking-oap服务失败问题 2、k8s环境 检查skywalking-oap服务状态 3、本地iidea启动服务连接skywalking oap服务 4、基于apache-skywalking-java-agent-9.4.0.tgz构建skywalking-agent镜像 4.1、Dockerfile内容如下 4.2、AbstractBuilder.M…

3. java 堆和 JVM 内存结构

1. JVM介绍和运行流程-CSDN博客 2. 什么是程序计数器-CSDN博客 3. java 堆和 JVM 内存结构-CSDN博客 4. 虚拟机栈-CSDN博客 5. JVM 的方法区-CSDN博客 6. JVM直接内存-CSDN博客 7. JVM类加载器与双亲委派模型-CSDN博客 8. JVM类装载的执行过程-CSDN博客 9. JVM垃圾回收…

UnityShader——SSAO

目录 1.是什么 2.原理 3.各部分解释 2.1.从屏幕空间到视图空间 2.2.以法线半球为基&#xff0c;获取随机向量 2.3.应用偏移&#xff0c;并将其转换为uv坐标 2.4.获取深度 2.5.比较并计算贡献 2.6.最后计算 4.改进 4.1.平滑过渡 4.2.模糊 5.变量和语句解释 5.1._D…

【设计模式】外观模式(门面模式)

外观模式&#xff08;Facade Pattern&#xff09;详解一、外观模式简介 外观模式&#xff08;Facade Pattern&#xff09; 是一种 结构型设计模式&#xff0c;它为一个复杂的子系统提供一个统一的高层接口&#xff0c;使得子系统更容易使用。 外观模式又称为门面模式&#xff0…

【6.1.1 漫画分库分表】

漫画分库分表 “数据量大了不可怕&#xff0c;可怕的是不知道如何优雅地拆分。” &#x1f3ad; 人物介绍 架构师老王&#xff1a;资深数据库架构专家&#xff0c;精通各种分库分表方案Java小明&#xff1a;对分库分表充满疑问的开发者ShardingSphere师傅&#xff1a;Apache S…

Tomcat问题:启动脚本startup.bat中文乱码问题解决

一、问题描述 我们第一次下载或者打开Tomcat时可能在控制台会出现中文乱码问题二、解决办法 我的是8.x版本的tomcat用notepad打开&#xff1a;logging.properties 找到&#xff1a;java.util.logging.ConsoleHandler.encoding设置成GBK&#xff0c;重启tomcat即可

Linux中Gitee的使用

一、Gitee简介&#xff1a;Gitee&#xff08;码云&#xff09;是中国的一个代码托管和协作开发平台&#xff0c;类似于GitHub或GitLab&#xff0c;主要面向开发者提供代码管理、项目协作及开源生态服务。适用场景个人开发者&#xff1a;托管私有代码或参与开源项目。中小企业&a…

Oracle大表数据清理优化与注意事项详解

一、性能优化策略 1. 批量处理优化批量大小选择&#xff1a; 小批量(1,000-10,000行)&#xff1a;减少UNDO生成&#xff0c;但需要更多提交次数中批量(10,000-100,000行)&#xff1a;平衡性能与资源消耗大批量(100,000行)&#xff1a;适合高配置环境&#xff0c;但需监控资源使…

Anaconda及Conda介绍及使用

文章目录Anaconda简介为什么选择 Anaconda&#xff1f;Anaconda 安装Win 平台macOS 平台Linux 平台Anaconda 界面使用Conda简介Conda下载安装conda 命令环境管理包管理其他常用命令Jupyter Notebook&#xff08;可选&#xff09;Anaconda简介 Anaconda 是一个数据科学和机器学…

外包干了一周,技术明显退步

我是一名本科生&#xff0c;自2019年起&#xff0c;我便在南京某软件公司担任功能测试的工作。这份工作虽然稳定&#xff0c;但日复一日的重复性工作让我逐渐陷入了舒适区&#xff0c;失去了前进的动力。两年的时光匆匆流逝&#xff0c;我却在原地踏步&#xff0c;技术没有丝毫…

【QT】多线程相关教程

一、核心概念与 Qt 线程模型 1.线程与进程的区别: 线程是程序执行的最小单元&#xff0c;进程是资源分配的最小单元&#xff0c;线程共享进程的内存空间(堆&#xff0c;全局变量等)&#xff0c;而进程拥有独立的内存空间。Qt线程只要关注同一进程内的并发。 2.为什么使用多线程…

VS 版本更新git安全保护问题的解决

问题&#xff1a;我可能移动了一个VS C# 项目&#xff0c;然后&#xff0c;发现里面的git版本检测不能用了 正在打开存储库: X:\Prj_C#\3D fatal: detected dubious ownership in repository at X:/Prj_C#/3DSnapCatch X:/Prj_C#/3D is owned by:S-1-5-32-544 but the current …

Git常用命令一览

Git 是基于 Linux内核开发的版本控制工具。与常用的版本控制工具 CVS, Subversion 等不同&#xff0c;它采用了分布式版本库的方式&#xff0c;不必服务器端软件支持&#xff08;ps&#xff1a;这得分是用什么样的服务端&#xff0c;使用http协议或者git协议等不太一样。并且在…

基于 JSON 文件定位图片缺陷点并保存

基于JSON的图片缺陷处理流程 ├── 1. 输入检查 │ ├── 验证图片文件是否存在 │ └── 验证JSON文件是否存在 │ ├── 2. 数据加载 │ ├── 打开并加载图片 │ └── 读取并解析JSON文件 │ ├── 3. 缺陷信息提取 │ ├── 检查JSON中是否存在shapes字…

Redis基础学习(五大值数据类型的常用操作命令)

目录 一、Redis基本知识与Redis键&#xff08;key&#xff09;常用操作命令。 二、Redis的五大值的数据类型。&#xff08;value&#xff09; 三、Redis关于键&#xff08;key&#xff09;的值常用操作指令表格统计。 &#xff08;1&#xff09;字符串&#xff08;String&#…

Ubuntu——办公软件 LibreOffice 安装与使用指南

十四、LibreOffice 安装与使用1、核心组件组件​​​​图标​​​​对应MS Office​​​​核心功能定位​​​​Writer​​&#x1f4dd;Word专业文档处理与排版​​Calc​​&#x1f4ca;Excel数据计算与分析​​Impress​​&#x1f3ac;PowerPoint演示文稿制作​​Draw​​&…

Securecrt丢失tab以及终端重新配色

今天在使用 Securecrt 的时候&#xff0c;发现 Securecrt 的 tab 标签消失不见了&#xff0c;仔细回想起来&#xff0c;应该是上一次误按了 alt enter 最大化&#xff0c;然后导致配置丢失的问题 还有表现就是菜单中的 Session Tabs 无论勾选还是不勾选都没有任何变化&#xf…

frp搭建内网穿透教程

frp搭建内网穿透教程 步骤1&#xff1a;准备工作 公网服务器&#xff1a;需要一台具有公网IP的服务器作为中转服务器&#xff0c;安装frp服务器端&#xff08;frps&#xff09;。内网设备&#xff1a;需要暴露服务的内网设备&#xff0c;安装frp客户端&#xff08;frpc&#xf…

【JavaEE进阶】图书管理系统(未完待续)

目录 用户登录 添加图书 图书列表 修改图书 删除图书 批量删除 拦截器 &#x1f343;前言 什么是拦截器? 拦截器的基本使用 自定义拦截器 注册配置拦截器 拦截路径 拦截器执行流程 项目实现统一拦截 定义拦截器 注册配置拦截器 前⾯图书管理系统, 咱们只完成了⽤⼾登录和图书列…