boot项目中定时任务quartz
最近换项目组,发现项目中定时任务使用的是quartz框架,上一篇文章[springboot定时任务]也是使用的quartz,只不过实现方式不同,于是整理下
定时任务常用方法有Quartz,Spring自带的Schedule框架
Quartz基础知识
quartz常用组件:调度器,触发器,作业。
常用类:jobdetail(定时任务。描述job的核心逻辑);trigger(触发器。一个触发器对应一个定时任务,而一个定时任务可以对应多个触发器);schedule(调度器。管理触发器及定时任务的协调工作,一个schedule可以有多个trigger和jobdetail)
quartz提供两种作业存储类型,RAMJobStore和JDBC作业。
RAMJobStore是内存存储。数据访问快,但由于是内存存储。若服务挂掉,运行的定时任务信息就会丢失。
JDBC是数据库存储。通过quartz.properties文件,持久化任务调度信息。若应用挂掉,重启后会继续执行定时任务。
集群模式
Quartz框架
若部署多台服务器,定时任务在某一时刻只能有一个节点执行,则使用持久化任务调度信息方案
quartz默认的集群方案,保证同一时刻相同触发器只能一个节点执行;若节点执行失败,则会分派到另一节点,中途也会自动检查失效的定时调度,若不成功,则其他节点会继续执行。定时任务在集群环境下默认是多台服务器会同时执行,这时需要结合项目自己程序判断。
quartz定时任务的配置文件中有一属性 org.quartz.jobStore.isClustered=true则为集群方式,自动判断节点状态。
@Schedule注解定时任务
@Schedule注解会定时跑服务。但是若部署多台服务器时,则会导致每台服务器都会执行一次,解决办法1.指定某台服务器执行 2.使用redis锁 3.数据库状态标识记录。但这种方式若是服务器时间一样,并发时数据库标识在查询时未来得及更新,也会导致多台服务器执行定时任务。详情可见[定时任务的时间修改后立即生效]
分布式多节点多活应用同一定时任务,多节点同时执行配置
pom.xml
<!--定时任务-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>2.7.18</version>
</dependency>
QuartzConfig类
package com.example.demo.config;import com.example.demo.jobs.Test1Job;
import org.quartz.CronTrigger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import java.util.Objects;/*** @Auther: lr* @Date: 2024/3/28 14:34* @Description:*/
@Configuration
public class QuartzConfig {@Value("${cron.test1}")private String test1Cron;/*** 定时任务的信息载体* 通过FactoryBean来间接创建Job对象,若有多个Job对象,需定义多次方法* 需要重写Factory相关代码,实现spring容器管理jobdetail* @return*/@Bean(name ="test1JobDetailBean" )public JobDetailFactoryBean initTest1JobDetailBean(){JobDetailFactoryBean jobDetailFactoryBean=new JobDetailFactoryBean();jobDetailFactoryBean.setJobClass(Test1Job.class);return jobDetailFactoryBean;}/*** 触发器* 就是Trigger的一个实现类型,其中用于定义周期时间的CronScheduleBuilder* 实际上,CronTrigger是用于管理一个cron表达式的类型* @return*/@Bean(name = "test1CronTriggerBean")public CronTriggerFactoryBean initTest1CronTriggerBean(){CronTriggerFactoryBean cronTriggerFactoryBean=new CronTriggerFactoryBean();JobDetailFactoryBean jobDetailFactoryBean = this.initTest1JobDetailBean();cronTriggerFactoryBean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean.getObject()));cronTriggerFactoryBean.setCronExpression(test1Cron);return cronTriggerFactoryBean;}/*** 任务调度器* @param customJobFactory 定时任务的信息载体* @param cronTriggerFactoryBeans 触发器* @return*/@Beanpublic SchedulerFactoryBean initSchedulerFactoryBean(CustomJobFactory customJobFactory,CronTriggerFactoryBean[] cronTriggerFactoryBeans){SchedulerFactoryBean factoryBean = new SchedulerFactoryBean();factoryBean.setJobFactory(customJobFactory);CronTrigger[] cronTriggers=new CronTrigger[cronTriggerFactoryBeans.length];for(int i=0;i<cronTriggerFactoryBeans.length;i++){cronTriggers[i]=cronTriggerFactoryBeans[i].getObject();}//注册触发器,一个Scheduler可以注册若干个触发器factoryBean.setTriggers(cronTriggers);//为Scheduler设置Jobdetail的工厂,可以覆盖掉springboot默认提供的工厂,保证jobdetail自动装配有效factoryBean.setJobFactory(customJobFactory);return factoryBean;}}
Test1Job
package com.example.demo.jobs;import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;
import java.util.Date;/*** @Auther: lr* @Date: 2024/3/28 14:42* @Description:*/
@Slf4j
public class Test1Job implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {//todoSimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-mm-dd HH:mm");String format = simpleDateFormat.format(new Date());log.info("{}开始执行定时任务1: {}",format ,jobExecutionContext.getJobDetail().getKey().getName());}
}
运行结果
可以看到多台机器都会执行到该定时任务

分布式多节点多活应用同一定时任务,单节点执行配置
pom.xml
<!--定时任务-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId><version>2.7.18</version>
</dependency>
<!--引入druid数据源-->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
<!--定时任务-->
quartz.yml
org:quartz:dataSource:myDS:URL: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Hongkong&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=truedriver: com.mysql.cj.jdbc.DrivermaxConnections: 5user: rootpassword: 123456connectionProvider:class: com.example.demo.config.QuartzConnectionProviderscheduler:instanceName: ClusterQuartzinstanceId: AUTOrmi:export: falseproxy: falsewrapJobExecutionInUserTransaction: falsejobStore:driverDelegateClass: org.quartz.impl.jdbcjobstore.PostgreSQLDelegatetablePrefix: QRTZ_isClustered: trueacquireTriggersWithinLock: truemisfireThreshold: 5000useProperties: truedataSource: myDSthreadPool:class: org.quartz.simpl.SimpleThreadPoolthreadCount: 1threadPriority: 5threadsInheritContextClassLoaderOfInitializingThread: true
数据库表整理
DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
DROP TABLE IF EXISTS QRTZ_LOCKS;
DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_TRIGGERS;
DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
DROP TABLE IF EXISTS QRTZ_CALENDARS;CREATE TABLE QRTZ_JOB_DETAILS(SCHED_NAME VARCHAR(120) NOT NULL,JOB_NAME VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,JOB_CLASS_NAME VARCHAR(250) NOT NULL,IS_DURABLE VARCHAR(1) NOT NULL,IS_NONCONCURRENT VARCHAR(1) NOT NULL,IS_UPDATE_DATA VARCHAR(1) NOT NULL,REQUESTS_RECOVERY VARCHAR(1) NOT NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);CREATE TABLE QRTZ_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,JOB_NAME VARCHAR(200) NOT NULL,JOB_GROUP VARCHAR(200) NOT NULL,DESCRIPTION VARCHAR(250) NULL,NEXT_FIRE_TIME BIGINT(13) NULL,PREV_FIRE_TIME BIGINT(13) NULL,PRIORITY INTEGER NULL,TRIGGER_STATE VARCHAR(16) NOT NULL,TRIGGER_TYPE VARCHAR(8) NOT NULL,START_TIME BIGINT(13) NOT NULL,END_TIME BIGINT(13) NULL,CALENDAR_NAME VARCHAR(200) NULL,MISFIRE_INSTR SMALLINT(2) NULL,JOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
);CREATE TABLE QRTZ_SIMPLE_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,REPEAT_COUNT BIGINT(7) NOT NULL,REPEAT_INTERVAL BIGINT(12) NOT NULL,TIMES_TRIGGERED BIGINT(10) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_CRON_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,CRON_EXPRESSION VARCHAR(200) NOT NULL,TIME_ZONE_ID VARCHAR(80),PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_SIMPROP_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,STR_PROP_1 VARCHAR(512) NULL,STR_PROP_2 VARCHAR(512) NULL,STR_PROP_3 VARCHAR(512) NULL,INT_PROP_1 INT NULL,INT_PROP_2 INT NULL,LONG_PROP_1 BIGINT NULL,LONG_PROP_2 BIGINT NULL,DEC_PROP_1 NUMERIC(13,4) NULL,DEC_PROP_2 NUMERIC(13,4) NULL,BOOL_PROP_1 VARCHAR(1) NULL,BOOL_PROP_2 VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_BLOB_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,BLOB_DATA BLOB NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_CALENDARS(SCHED_NAME VARCHAR(120) NOT NULL,CALENDAR_NAME VARCHAR(200) NOT NULL,CALENDAR BLOB NOT NULL,PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS(SCHED_NAME VARCHAR(120) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);CREATE TABLE QRTZ_FIRED_TRIGGERS(SCHED_NAME VARCHAR(120) NOT NULL,ENTRY_ID VARCHAR(95) NOT NULL,TRIGGER_NAME VARCHAR(200) NOT NULL,TRIGGER_GROUP VARCHAR(200) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,FIRED_TIME BIGINT(13) NOT NULL,SCHED_TIME BIGINT(13) NOT NULL,PRIORITY INTEGER NOT NULL,STATE VARCHAR(16) NOT NULL,JOB_NAME VARCHAR(200) NULL,JOB_GROUP VARCHAR(200) NULL,IS_NONCONCURRENT VARCHAR(1) NULL,REQUESTS_RECOVERY VARCHAR(1) NULL,PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);CREATE TABLE QRTZ_SCHEDULER_STATE(SCHED_NAME VARCHAR(120) NOT NULL,INSTANCE_NAME VARCHAR(200) NOT NULL,LAST_CHECKIN_TIME BIGINT(13) NOT NULL,CHECKIN_INTERVAL BIGINT(13) NOT NULL,PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);CREATE TABLE QRTZ_LOCKS(SCHED_NAME VARCHAR(120) NOT NULL,LOCK_NAME VARCHAR(40) NOT NULL,PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);commit;
QuartzSingleConfig配置文件
package com.example.demo.config;import com.example.demo.jobs.Test2Job;
import org.quartz.CronTrigger;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;import javax.sql.DataSource;
import java.io.IOException;
import java.util.Objects;
import java.util.Properties;/*** @Auther: lr* @Date: 2024/3/28 14:34* @Description:*/
@Configuration
public class QuartzSingleConfig {@Value("${cron.test2}")private String test2Cron;/*** 加载quartz配置*/@Beanpublic Properties quartzProperties() throws IOException {PropertiesFactoryBean propertiesFactoryBean=new PropertiesFactoryBean();propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.yml"));propertiesFactoryBean.afterPropertiesSet();return propertiesFactoryBean.getObject();}/*** 定时任务的信息载体** @return*/@Bean(name = "test2JobDetailBean")public JobDetailFactoryBean initTest2JobDetailBean() {JobDetailFactoryBean jobDetailFactoryBean = new JobDetailFactoryBean();jobDetailFactoryBean.setJobClass(Test2Job.class);jobDetailFactoryBean.setDurability(true);return jobDetailFactoryBean;}/*** 触发器** @return*/@Bean(name = "test2CronTriggerBean")public CronTriggerFactoryBean initTest2CronTriggerBean() {CronTriggerFactoryBean cronTriggerFactoryBean = new CronTriggerFactoryBean();JobDetailFactoryBean jobDetailFactoryBean = this.initTest2JobDetailBean();cronTriggerFactoryBean.setJobDetail(Objects.requireNonNull(jobDetailFactoryBean.getObject()));cronTriggerFactoryBean.setCronExpression(test2Cron);return cronTriggerFactoryBean;}/*** 任务调度器** @param customJobFactory 定时任务的信息载体* @param cronTriggerFactoryBeans 触发器* @return*/@Bean(name = "schedulerFactoryBean")public SchedulerFactoryBean initSchedulerFactoryBean(CustomJobFactory customJobFactory,CronTriggerFactoryBean[] cronTriggerFactoryBeans,@Qualifier("dataSource") DataSource dataSource) throws IOException {SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();//自动覆盖quartz.properties配置的数据源schedulerFactoryBean.setDataSource(dataSource);//设置quartz的配置文件schedulerFactoryBean.setQuartzProperties(quartzProperties());schedulerFactoryBean.setJobFactory(customJobFactory);CronTrigger[] cronTriggers = new CronTrigger[cronTriggerFactoryBeans.length];for (int i = 0; i < cronTriggerFactoryBeans.length; i++) {cronTriggers[i] = cronTriggerFactoryBeans[i].getObject();}schedulerFactoryBean.setTriggers(cronTriggers);// 用于quartz集群,QuartzScheduler 启动时更新己存在的JobschedulerFactoryBean.setOverwriteExistingJobs(true);//延长启动schedulerFactoryBean.setStartupDelay(1);return schedulerFactoryBean;}}
Durid连接池quartz工具类 QuartzConnectionProvider
package com.example.demo.config;import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;
import org.quartz.SchedulerException;
import org.quartz.utils.ConnectionProvider;import java.sql.Connection;
import java.sql.SQLException;/*** @Auther: lr* @Date: 2024/3/28 17:01* @Description:*/
@Data
public class QuartzConnectionProvider implements ConnectionProvider {/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** 常量配置,与quartz.properties文件的key保持一致(去掉前缀),同时提供set方法,Quartz框架自动注入值。** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*///JDBC驱动public String driver;//JDBC连接串public String URL;//数据库用户名public String user;//数据库用户密码public String password;//数据库最大连接数public int maxConnection;//数据库SQL查询每次连接返回执行到连接池,以确保它仍然是有效的。public String validationQuery;private boolean validateOnCheckout;private int idleConnectionValidationSeconds;public String maxCachedStatementsPerConnection;private String discardIdleConnectionsSeconds;public static final int DEFAULT_DB_MAX_CONNECTIONS = 10;public static final int DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION = 120;//Druid连接池private DruidDataSource datasource;/** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~** 接口实现** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/public Connection getConnection() throws SQLException {return datasource.getConnection();}public void shutdown() throws SQLException {datasource.close();}public void initialize() throws SQLException {if (this.URL == null) {throw new SQLException("DBPool could not be created: DB URL cannot be null");}if (this.driver == null) {throw new SQLException("DBPool driver could not be created: DB driver class name cannot be null!");}if (this.maxConnection < 0) {throw new SQLException("DBPool maxConnectins could not be created: Max connections must be greater than zero!");}datasource = new DruidDataSource();try {datasource.setDriverClassName(this.driver);} catch (Exception e) {try {throw new SchedulerException("Problem setting driver class name on datasource: " + e.getMessage(), e);} catch (SchedulerException e1) {}}datasource.setUrl(this.URL);datasource.setUsername(this.user);datasource.setPassword(this.password);datasource.setMaxActive(this.maxConnection);datasource.setMinIdle(1);datasource.setMaxWait(0);datasource.setMaxPoolPreparedStatementPerConnectionSize(this.DEFAULT_DB_MAX_CACHED_STATEMENTS_PER_CONNECTION);if (this.validationQuery != null) {datasource.setValidationQuery(this.validationQuery);if (!this.validateOnCheckout)datasource.setTestOnReturn(true);elsedatasource.setTestOnBorrow(true);datasource.setValidationQueryTimeout(this.idleConnectionValidationSeconds);}}
}
Test2Job类
package com.example.demo.jobs;import lombok.extern.slf4j.Slf4j;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import java.text.SimpleDateFormat;
import java.util.Date;/*** @Auther: lr* @Date: 2024/3/29 9:29* @Description:*/
@Slf4j
public class Test2Job implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {//todoSimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm");String format = simpleDateFormat.format(new Date());log.info("{}开始执行定时任务2: {}",format ,jobExecutionContext.getJobDetail().getKey().getName());}}
启动项目后,可以看出数据库中定时任务的表达式已经存储在表中


如图所示,定时任务的信息存储在表中。
相关文章:
boot项目中定时任务quartz
最近换项目组,发现项目中定时任务使用的是quartz框架,上一篇文章[springboot定时任务]也是使用的quartz,只不过实现方式不同,于是整理下 定时任务常用方法有Quartz,Spring自带的Schedule框架 Quartz基础知识 quartz…...
使用阿里云OSS实现视频上传功能
目录 前言 视频上传 前言 阿里云对象存储服务(OSS)作为一种高可用、高扩展性的云端存储服务,为开发者提供了便捷、安全的对象存储解决方案。本文将介绍如何利用阿里云OSS实现视频上传功能。 视频上传 前期准备请看阿里云OSS文件上传和下载…...
LOTO示波器软件新增导览功能
新版本的大部分型号LOTO示波器的上位机软件我们改成了导航工具条方式。原来的方式是把所有功能都显示在不同的标签页中,这样的优点是非常快捷方便,基本上用鼠标一两次点击就能直达想要的功能设置。但是缺点是不熟练的客户可能记不住各种功能的标签位置在…...
【StructueEngineering】SYMBOL SCHEDULE
文章目录 标记表列SYMBOL SCHEDULELINES线条COLUMN REFERENCE SYMBOL柱参考标记SECTION REFERENCE SYMBOLS剖面参考标记DETAILREFERENCE SYMBOLS详图参考标记GENERALELEVATIONSYMBOLS一般立面图标记MISCELLANEOUS SYMBOLS杂项标记 STEEL FRAMING SYMBOLS钢结构平面图标记COLUMN…...
简化跨网文件传输摆渡过程,降低IT人员工作量
在当今数字化时代,IT企业面临着日益增长的数据交换需求。随着网络安全威胁的不断演变,网关隔离成为了保护企业内部网络不受外部威胁的重要手段。然而,隔离的同时,企业也需要在不同网络间安全、高效地传输文件,这就催生…...
关于python中屏蔽输出
python中屏蔽输出包含屏蔽标准输出(比如打印出来的内容)、屏蔽标准错误(错误信息)还有屏蔽logging信息等。 屏蔽标准输出 import contextlib import oswith open(os.devnull, "w") as devnull:with contextlib.redire…...
螺旋矩阵(算法题)
文章目录 螺旋矩阵解题思路 螺旋矩阵 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5]]解题思路 模…...
ffmpeg-webrtc(metartc)给ffmpeg添加webrtc协议
这个是使用metrtc的库为ffmpeg添加webrtc传输协议,目前国内还有一个这样的开源项目,是杨成立大佬,大师兄他们在做,不过wili页面维护的不好,新手不知道如何使用,我专门对它做过介绍,另一篇博文&a…...
C语言知识大纲
一、基础 (一)变量定义和使用 (二)数据类型的字节数 (三)变量转换 (四)程序主要结构 (五)if和else判断 (六)switch判断 (七)while循环 (八)do while循环 (九)for循环 (十)基本输入输出 (十一)数组定义和使用 (十二)函数定义和使用 (十三)指针 (十四)多级指针 (十…...
【必会面试题】synchronized锁升级的过程
目录 Java中的synchronized关键字用于实现同步控制,以保护共享资源免受并发访问的影响。为了提高性能,特别是针对多线程环境中的锁机制,Java引入了锁升级的概念。锁升级的过程主要是为了减少锁操作的开销,根据竞争情况动态地调整锁…...
设计模式——工厂三兄弟之简单工厂
1.业务需求 大家好,我是菠菜。在介绍这期简单工厂设计模式前,我们先来看看这样的需求:制作一个简单的计算器,能够实现控制台输入俩个数以及运算符完成运算。 2.初步实现 实现第一版思路: 创建计算器类&…...
如何使用ChatGPT撰写短视频爆款文案
在这个快速发展的数字时代,短视频已经成为最受欢迎的娱乐和信息获取方式之一。对于内容创作者来说,如何制作出爆款短视频,吸引更多观众的注意力,是他们面临的一大挑战。文案,作为视频内容的灵魂,起着至关重…...
申办风景园林设计乙级资质如何整理技术人员的专业培训证明
整理技术人员的专业培训证明是申办风景园林设计乙级资质的重要环节,它直接关系到证明技术人员持续学习和专业能力提升的情况。以下是整理专业培训证明的一些建议步骤: 收集培训记录:首先,向所有参与设计工作的技术人员收集他们参加…...
类别型特征
#机器学习 #深度学习 #基础知识 #特征工程 #数据编码 背景 在现实生活中,我们面对的数据类型有很多,其中有的数据天然为数值类型具备数值意义,那么可以很自然地和算法结合,但是大部分数据他没有天然的数值意义,那么将他们送入到算法前,就需要对数据进行编码处理,将其转换为数…...
java医院管理系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的医院管理系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 医院管理系统的主要使用者分…...
vue2 面试题
一、.vue的性能优化怎么做? 1.编码优化: 不要把所有的数据都放在data中;v-for时给每个元素绑定事件用事件代理;keep-alive缓存组件;尽可能拆分组件,提高复用性、维护性;key值要保证唯一&#…...
【JavaEE精炼宝库】多线程(3)线程安全 | synchronized
目录 一、线程安全 1.1 经典线程不安全案例: 1.2 线程安全的概念: 1.3 线程不安全的原因: 1.3.1 案例刨析: 1.3.2 线程不安全的名词解释: 1.3.3 Java 内存模型 (JMM): 1.3.4 解决线程不安全问题: 二…...
el-table-column两种方法处理特殊字段,插槽和函数
问题:后端返回的字段为数字 解决办法: {{ row[item.prop] 1 ? "启用" : "禁用" }} {{ row[item.prop] }} 最终果: 另外:如果多种状态时可用函数 {{ getStatus(row[item.prop]) }} {{ row[item.prop…...
huggingface笔记: accelerate estimate-memory 命令
探索可用于某一机器的潜在模型时,了解模型的大小以及它是否适合当前显卡的内存是一个非常复杂的问题。为了缓解这个问题,Accelerate 提供了一个 命令行命令 accelerate estimate-memory。 accelerate estimate-memory {MODEL_NAME} --library_name {LIBR…...
李飞飞亲自撰文:大模型不存在主观感觉能力,多少亿参数都不行
近日,李飞飞连同斯坦福大学以人为本人工智能研究所 HAI 联合主任 John Etchemendy 教授联合撰写了一篇文章,文章对 AI 到底有没有感觉能力(sentient)进行了深入探讨。 「空间智能是人工智能拼图中的关键一环。」知名「AI 教母」李…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
