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

SpringBoot实现定时任务,使用自带的定时任务以及调度框架quartz的配置使用

SpringBoot实现定时任务,使用自带的定时任务以及调度框架quartz的配置使用

文章目录

  • SpringBoot实现定时任务,使用自带的定时任务以及调度框架quartz的配置使用
    • 一. 使用SpringBoot自带的定时任务(适用于小型应用)
    • 二. 使用调度框架quartz(适用于中大型应用)
    • 三、数据库模式quartz的使用
        • 1. 创建数据库表
        • 2. 制定一个定时任务
        • 3. 写配置文件
        • 4. 创建接收和相应实体类
        • 5. 增删改查的controller层接口
        • 6. 编写接口测试代码

一. 使用SpringBoot自带的定时任务(适用于小型应用)

创建SpringBoot项目,创建SpringBootTestJob 类,作为定时任务类

 @Component@EnableSchedulingpublic class SpringBootTestJob {@Scheduled(cron = "0/5 * * * * ?") // 每五秒执行一次private void test() {System.out.println("SpringBootTestJob TEST");}}
  • 适用性: 适合单体应用,不适合集群,没法实时更改定时任务状态和策略

启动后,可以看到,每五秒打印内容:
在这里插入图片描述

二. 使用调度框架quartz(适用于中大型应用)

  1. 增加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
  1. 创建定时任务类
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;/*** @author SaoE* @date 2025/1/19 20:06*/
public class TestJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("TestJob TEST");}
}
  1. 增加quartz配置类QuartzConfig
 @Configurationpublic class QuartzConfig {/*** 声明一个任务* @return*/@Beanpublic JobDetail jobDetail() {return JobBuilder.newJob(TestJob.class).withIdentity("TestJob", "test").storeDurably().build();}/*** 声明一个触发器,什么时候触发这个任务* @return*/@Beanpublic Trigger trigger() {return TriggerBuilder.newTrigger().forJob(jobDetail()).withIdentity("trigger", "trigger").startNow().withSchedule(CronScheduleBuilder.cronSchedule("*/2 * * * * ?")).build();}}
  1. 启动主类
    可以看到控制台每两秒打印信息:
    在这里插入图片描述
  2. 禁止任务并发执行
    任务类增加注解@DisallowConcurrentExecution,修改如下:
@DisallowConcurrentExecution
public class TestJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("TestJob TEST开始");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("TestJob TEST结束");}
}

此时打印输出为上一个任务结束后,下一个任务立即开始。如果没有这个注解,则会并发执行。

三、数据库模式quartz的使用

1. 创建数据库表
-- #
-- # Quartz seems to work best with the driver mm.mysql-2.0.7-bin.jar
-- #
-- # PLEASE consider using mysql with innodb tables to avoid locking issues
-- #
-- # In your Quartz properties file, you'll need to set
-- # org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
-- #
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  comment '定时任务名称',JOB_NAME  VARCHAR(200) NOT NULL  comment 'job名称',JOB_GROUP VARCHAR(200) NOT NULL  comment 'job组',DESCRIPTION VARCHAR(250) NULL  comment '描述',JOB_CLASS_NAME   VARCHAR(250) NOT NULL  comment 'job类名',IS_DURABLE VARCHAR(1) NOT NULL  comment '是否持久化',IS_NONCONCURRENT VARCHAR(1) NOT NULL  comment '是否非同步',IS_UPDATE_DATA VARCHAR(1) NOT NULL  comment '是否更新数据',REQUESTS_RECOVERY VARCHAR(1) NOT NULL  comment '请求是否覆盖',JOB_DATA BLOB NULL  comment 'job数据',PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
);
CREATE TABLE QRTZ_TRIGGERS
(SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',TRIGGER_NAME VARCHAR(200) NOT NULL comment '触发器名称',TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',JOB_NAME  VARCHAR(200) NOT NULL  comment 'job名称',JOB_GROUP VARCHAR(200) NOT NULL  comment 'job组',DESCRIPTION VARCHAR(250) NULL  comment '描述',NEXT_FIRE_TIME BIGINT(13) NULL  comment '下一次触发时间',PREV_FIRE_TIME BIGINT(13) NULL  comment '前一次触发时间',PRIORITY INTEGER NULL  comment '等级',TRIGGER_STATE VARCHAR(16) NOT NULL  comment '触发状态',TRIGGER_TYPE VARCHAR(8) NOT NULL  comment '触发类型',START_TIME BIGINT(13) NOT NULL  comment '开始时间',END_TIME BIGINT(13) NULL  comment '结束时间',CALENDAR_NAME VARCHAR(200) NULL  comment '日程名称',MISFIRE_INSTR SMALLINT(2) NULL  comment '未触发实例',JOB_DATA BLOB NULL  comment 'job数据',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  comment '定时任务名称',TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',REPEAT_COUNT BIGINT(7) NOT NULL  comment '重复执行次数',REPEAT_INTERVAL BIGINT(12) NOT NULL  comment '重复执行间隔',TIMES_TRIGGERED BIGINT(10) NOT NULL  comment '已经触发次数',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  comment '定时任务名称',TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',CRON_EXPRESSION VARCHAR(200) NOT NULL  comment 'cron表达式',TIME_ZONE_ID VARCHAR(80)  comment '时区',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  comment '定时任务名称',TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',STR_PROP_1 VARCHAR(512) NULL  comment '开始配置1',STR_PROP_2 VARCHAR(512) NULL  comment '开始配置2',STR_PROP_3 VARCHAR(512) NULL  comment '开始配置3',INT_PROP_1 INT NULL  comment 'int配置1',INT_PROP_2 INT NULL  comment 'int配置2',LONG_PROP_1 BIGINT NULL  comment 'long配置1',LONG_PROP_2 BIGINT NULL  comment 'long配置2',DEC_PROP_1 NUMERIC(13,4) NULL  comment '配置描述1',DEC_PROP_2 NUMERIC(13,4) NULL  comment '配置描述2',BOOL_PROP_1 VARCHAR(1) NULL  comment 'bool配置1',BOOL_PROP_2 VARCHAR(1) NULL  comment 'bool配置2',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  comment '定时任务名称',TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',BLOB_DATA BLOB NULL  comment '数据',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  comment '定时任务名称',CALENDAR_NAME  VARCHAR(200) NOT NULL comment '日程名称',CALENDAR BLOB NOT NULL  comment '日程数据',PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
(SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',TRIGGER_GROUP  VARCHAR(200) NOT NULL  comment '触发器组',PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS
(SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',ENTRY_ID VARCHAR(95) NOT NULL  comment 'entryId',TRIGGER_NAME VARCHAR(200) NOT NULL  comment '触发器名称',TRIGGER_GROUP VARCHAR(200) NOT NULL  comment '触发器组',INSTANCE_NAME VARCHAR(200) NOT NULL  comment '实例名称',FIRED_TIME BIGINT(13) NOT NULL  comment '执行时间',SCHED_TIME BIGINT(13) NOT NULL  comment '定时任务时间',PRIORITY INTEGER NOT NULL  comment '等级',STATE VARCHAR(16) NOT NULL  comment '状态',JOB_NAME VARCHAR(200) NULL  comment 'job名称',JOB_GROUP VARCHAR(200) NULL  comment 'job组',IS_NONCONCURRENT VARCHAR(1) NULL  comment '是否异步',REQUESTS_RECOVERY VARCHAR(1) NULL  comment '是否请求覆盖',PRIMARY KEY (SCHED_NAME,ENTRY_ID)
);
CREATE TABLE QRTZ_SCHEDULER_STATE
(SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',INSTANCE_NAME VARCHAR(200) NOT NULL  comment '实例名称',LAST_CHECKIN_TIME BIGINT(13) NOT NULL  comment '最近检入时间',CHECKIN_INTERVAL BIGINT(13) NOT NULL  comment '检入间隔',PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
);
CREATE TABLE QRTZ_LOCKS
(SCHED_NAME VARCHAR(120) NOT NULL  comment '定时任务名称',LOCK_NAME  VARCHAR(40) NOT NULL  comment 'lock名称',PRIMARY KEY (SCHED_NAME,LOCK_NAME)
);
2. 制定一个定时任务

和上面一样的TestJob

@DisallowConcurrentExecution
public class TestJob implements Job {@Overridepublic void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {System.out.println("TestJob TEST开始");try {Thread.sleep(3000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("TestJob TEST结束");}
}
3. 写配置文件

MyJobFactory.java:

@Component
public class MyJobFactory extends SpringBeanJobFactory {@Resourceprivate AutowireCapableBeanFactory beanFactory;/*** 这里覆盖了super的createJobInstance方法,对其创建出来的类再进行autowire。*/@Overrideprotected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {Object jobInstance = super.createJobInstance(bundle);beanFactory.autowireBean(jobInstance);return jobInstance;}
}

SchedulerConfig.java:

@Configuration
public class SchedulerConfig {@Resourceprivate MyJobFactory myJobFactory;@Beanpublic SchedulerFactoryBean schedulerFactoryBean(@Qualifier("dataSource") DataSource dataSource) throws IOException {SchedulerFactoryBean factory = new SchedulerFactoryBean();factory.setDataSource(dataSource);factory.setJobFactory(myJobFactory);factory.setStartupDelay(2);return factory;}
}
4. 创建接收和相应实体类

接收实体类CronJobReq.java:

public class CronJobReq {private String group;private String name;private String description;private String cronExpression;@Overridepublic String toString() {final StringBuffer sb = new StringBuffer("CronJobDto{");sb.append("cronExpression='").append(cronExpression).append('\'');sb.append(", group='").append(group).append('\'');sb.append(", name='").append(name).append('\'');sb.append(", description='").append(description).append('\'');sb.append('}');return sb.toString();}public String getGroup() {return group;}public void setGroup(String group) {this.group = group;}public String getCronExpression() {return cronExpression;}public void setCronExpression(String cronExpression) {this.cronExpression = cronExpression;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

响应实体类CronJobResp.java:

@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class CronJobResp {private String group;private String name;private String description;private String state;private String cronExpression;@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date nextFireTime;@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date preFireTime;@Overridepublic String toString() {final StringBuffer sb = new StringBuffer("CronJobDto{");sb.append("cronExpression='").append(cronExpression).append('\'');sb.append(", group='").append(group).append('\'');sb.append(", name='").append(name).append('\'');sb.append(", description='").append(description).append('\'');sb.append(", state='").append(state).append('\'');sb.append(", nextFireTime=").append(nextFireTime);sb.append(", preFireTime=").append(preFireTime);sb.append('}');return sb.toString();}public String getGroup() {return group;}public void setGroup(String group) {this.group = group;}public String getCronExpression() {return cronExpression;}public void setCronExpression(String cronExpression) {this.cronExpression = cronExpression;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Date getNextFireTime() {return nextFireTime;}public void setNextFireTime(Date nextFireTime) {this.nextFireTime = nextFireTime;}public Date getPreFireTime() {return preFireTime;}public void setPreFireTime(Date preFireTime) {this.preFireTime = preFireTime;}public String getState() {return state;}public void setState(String state) {this.state = state;}
}
5. 增删改查的controller层接口

任务和quartz通过接口来关联。CronJobReq类的name属性会告诉quartz操作哪个定时任务。

JobController.java:

@RestController
@RequestMapping(value = "/admin/job")
public class JobController {private static Logger LOG = LoggerFactory.getLogger(JobController.class);@Autowiredprivate SchedulerFactoryBean schedulerFactoryBean;@RequestMapping(value = "/run")public CommonResp<Object> run(@RequestBody CronJobReq cronJobReq) throws SchedulerException {String jobClassName = cronJobReq.getName();String jobGroupName = cronJobReq.getGroup();LOG.info("手动执行任务开始:{}, {}", jobClassName, jobGroupName);schedulerFactoryBean.getScheduler().triggerJob(JobKey.jobKey(jobClassName, jobGroupName));return new CommonResp<>();}@RequestMapping(value = "/add")public CommonResp add(@RequestBody CronJobReq cronJobReq) {String jobClassName = cronJobReq.getName();String jobGroupName = cronJobReq.getGroup();String cronExpression = cronJobReq.getCronExpression();String description = cronJobReq.getDescription();LOG.info("创建定时任务开始:{},{},{},{}", jobClassName, jobGroupName, cronExpression, description);CommonResp commonResp = new CommonResp();try {// 通过SchedulerFactory获取一个调度器实例Scheduler sched = schedulerFactoryBean.getScheduler();// 启动调度器sched.start();//构建job信息JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) Class.forName(jobClassName)).withIdentity(jobClassName, jobGroupName).build();//表达式调度构建器(即任务执行的时间)CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);//按新的cronExpression表达式构建一个新的triggerCronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName).withDescription(description).withSchedule(scheduleBuilder).build();sched.scheduleJob(jobDetail, trigger);} catch (SchedulerException e) {LOG.error("创建定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("创建定时任务失败:调度异常");} catch (ClassNotFoundException e) {LOG.error("创建定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("创建定时任务失败:任务类不存在");}LOG.info("创建定时任务结束:{}", commonResp);return commonResp;}@RequestMapping(value = "/pause")public CommonResp pause(@RequestBody CronJobReq cronJobReq) {String jobClassName = cronJobReq.getName();String jobGroupName = cronJobReq.getGroup();LOG.info("暂停定时任务开始:{},{}", jobClassName, jobGroupName);CommonResp commonResp = new CommonResp();try {Scheduler sched = schedulerFactoryBean.getScheduler();sched.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));} catch (SchedulerException e) {LOG.error("暂停定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("暂停定时任务失败:调度异常");}LOG.info("暂停定时任务结束:{}", commonResp);return commonResp;}@RequestMapping(value = "/resume")public CommonResp resume(@RequestBody CronJobReq cronJobReq) {String jobClassName = cronJobReq.getName();String jobGroupName = cronJobReq.getGroup();LOG.info("重启定时任务开始:{},{}", jobClassName, jobGroupName);CommonResp commonResp = new CommonResp();try {Scheduler sched = schedulerFactoryBean.getScheduler();sched.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));} catch (SchedulerException e) {LOG.error("重启定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("重启定时任务失败:调度异常");}LOG.info("重启定时任务结束:{}", commonResp);return commonResp;}@RequestMapping(value = "/reschedule")public CommonResp reschedule(@RequestBody CronJobReq cronJobReq) {String jobClassName = cronJobReq.getName();String jobGroupName = cronJobReq.getGroup();String cronExpression = cronJobReq.getCronExpression();String description = cronJobReq.getDescription();LOG.info("更新定时任务开始:{},{},{},{}", jobClassName, jobGroupName, cronExpression, description);CommonResp commonResp = new CommonResp();try {Scheduler scheduler = schedulerFactoryBean.getScheduler();TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);// 表达式调度构建器CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);CronTriggerImpl trigger1 = (CronTriggerImpl) scheduler.getTrigger(triggerKey);trigger1.setStartTime(new Date()); // 重新设置开始时间CronTrigger trigger = trigger1;// 按新的cronExpression表达式重新构建triggertrigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withDescription(description).withSchedule(scheduleBuilder).build();// 按新的trigger重新设置job执行scheduler.rescheduleJob(triggerKey, trigger);} catch (Exception e) {LOG.error("更新定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("更新定时任务失败:调度异常");}LOG.info("更新定时任务结束:{}", commonResp);return commonResp;}@RequestMapping(value = "/delete")public CommonResp delete(@RequestBody CronJobReq cronJobReq) {String jobClassName = cronJobReq.getName();String jobGroupName = cronJobReq.getGroup();LOG.info("删除定时任务开始:{},{}", jobClassName, jobGroupName);CommonResp commonResp = new CommonResp();try {Scheduler scheduler = schedulerFactoryBean.getScheduler();scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));} catch (SchedulerException e) {LOG.error("删除定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("删除定时任务失败:调度异常");}LOG.info("删除定时任务结束:{}", commonResp);return commonResp;}@RequestMapping(value="/query")public CommonResp query() {LOG.info("查看所有定时任务开始");CommonResp commonResp = new CommonResp();List<CronJobResp> cronJobDtoList = new ArrayList();try {Scheduler scheduler = schedulerFactoryBean.getScheduler();for (String groupName : scheduler.getJobGroupNames()) {for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {CronJobResp cronJobResp = new CronJobResp();cronJobResp.setName(jobKey.getName());cronJobResp.setGroup(jobKey.getGroup());//get job's triggerList<Trigger> triggers = (List<Trigger>) scheduler.getTriggersOfJob(jobKey);CronTrigger cronTrigger = (CronTrigger) triggers.get(0);cronJobResp.setNextFireTime(cronTrigger.getNextFireTime());cronJobResp.setPreFireTime(cronTrigger.getPreviousFireTime());cronJobResp.setCronExpression(cronTrigger.getCronExpression());cronJobResp.setDescription(cronTrigger.getDescription());Trigger.TriggerState triggerState = scheduler.getTriggerState(cronTrigger.getKey());cronJobResp.setState(triggerState.name());cronJobDtoList.add(cronJobResp);}}} catch (SchedulerException e) {LOG.error("查看定时任务失败:" + e);commonResp.setSuccess(false);commonResp.setMessage("查看定时任务失败:调度异常");}commonResp.setContent(cronJobDtoList);LOG.info("查看定时任务结束:{}", commonResp);return commonResp;}}
6. 编写接口测试代码

test.http:

POST http://localhost:8000/batch/admin/job/add
Content-Type: application/json{"name": "com.mystudy.train.batch.job.TestJob","jobGroupName": "default","cronExpression": "*/2 * * * * ?","desc": "test job"
}###GET http://localhost:8000/batch/admin/job/query###POST http://localhost:8000/batch/admin/job/pause
Content-Type: application/json{"name": "com.mystudy.train.batch.job.TestJob","jobGroupName": "default"
}###POST http://localhost:8000/batch/admin/job/resume
Content-Type: application/json{"name": "com.mystudy.train.batch.job.TestJob","jobGroupName": "default"
}###POST http://localhost:8000/batch/admin/job/reschedule
Content-Type: application/json{
"name": "com.mystudy.train.batch.job.TestJob",
"jobGroupName": "default",
"cronExpression": "*/5 * * * * ?",
"desc": "test job"
}###POST http://localhost:8000/batch/admin/job/delete
Content-Type: application/json{
"name": "com.mystudy.train.batch.job.TestJob",
"jobGroupName": "default"
}###

相关文章:

SpringBoot实现定时任务,使用自带的定时任务以及调度框架quartz的配置使用

SpringBoot实现定时任务&#xff0c;使用自带的定时任务以及调度框架quartz的配置使用 文章目录 SpringBoot实现定时任务&#xff0c;使用自带的定时任务以及调度框架quartz的配置使用一. 使用SpringBoot自带的定时任务&#xff08;适用于小型应用&#xff09;二. 使用调度框架…...

java上传图片功能实现

1 MinIO核心概念 下面介绍MinIO中的几个核心概念&#xff0c;这些概念在所有的对象存储服务中也都是通用的。 对象&#xff08;Object&#xff09; 对象是实际的数据单元&#xff0c;例如我们上传的一个图片。 存储桶&#xff08;Bucket&#xff09; 存储桶是用于组织对象的命…...

73,【5】BUUCTF WEB [网鼎杯 2020 玄武组]SSRFMe(未解出)

进入靶场 又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码又是代码 <?php // 检查 URL 是否为内部 IP 地址 function check_inner_ip($url) {// 使用正则表达式检查 URL 格式是否以 http、https、gopher 或 d…...

【FreeRTOS 教程 一】任务结构体及其基础创建使用

目录 一、任务与协程的区别&#xff1a; &#xff08;1&#xff09;任务的特点&#xff1a; &#xff08;2&#xff09;协程的特点&#xff1a; &#xff08;3&#xff09;总结&#xff1a; 二、任务概述 &#xff1a; &#xff08;1&#xff09;任务状态&#xff1a; &…...

深入剖析 JVM 内存模型

前言&#xff1a; 下面分别介绍了新生代和老年代的不同收集器及其相关子类型&#xff0c;并附有示例代码和说明&#xff0c;感兴趣的朋友可以参考一下。 简介&#xff1a; 在 Java 虚拟机&#xff08;JVM&#xff09;的世界里&#xff0c;内存模型是其核心架构之一&#xff0…...

解决DeepSeek-R1模型在Cursor中使用报错的问题

在使用Cursor时&#xff0c;如果你尝试调用DeepSeek-R1模型&#xff0c;可能会遇到以下报错信息&#xff1a; {"error": {"message": "deepseek-reasoner does not support successive user or assistant messages (messages[1] and messages[2] in …...

ASP.NET Core 6.0 如何处理丢失的 Startup.cs 文件

介绍 .NET 6.0 已经发布&#xff0c;ASP.NET Core 6.0 也已发布。其中有不少变化让很多人感到困惑。例如&#xff0c;“谁动了我的奶酪”&#xff0c;它在哪里Startup.cs&#xff1f;在这篇文章中&#xff0c;我将深入研究这个问题&#xff0c;看看它移动到了哪里以及其他变化。…...

Java如何向http/https接口发出请求

用Java发送web请求所用到的包都在java.net下&#xff0c;在具体使用时可以用如下代码&#xff0c;你可以把它封装成一个工具类 import javax.net.ssl.*; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Outpu…...

数据分析 变异系数

目录 变异系数的应用场景包括&#xff1a; 特点&#xff1a; 注意事项&#xff1a; np.nanvar——方差&#xff0c;np.sanstd标准差 简单来讲就是平均值/标准差 变异系数&#xff08;Coefficient of Variation, CV&#xff09;是一种相对量的变异指标&#xff0c;常用于衡…...

利用免费GIS工具箱实现高斯泼溅切片,将 PLY 格式转换为 3dtiles

在地理信息系统&#xff08;GIS&#xff09;和三维数据处理领域&#xff0c;不同数据格式有其独特应用场景与优势。PLY&#xff08;Polygon File Format&#xff09;格式常用于存储多边形网格数据&#xff0c;而 3DTiles 格式在 Web 端三维场景展示等方面表现出色。将 PLY 格式…...

面试-二维数组

应用 快递业务有N个站点&#xff0c;1<N<10000&#xff1b;站点0、站点1可达&#xff0c;记作0-1&#xff1b;如果0-1、1-2&#xff0c;则站点0、站点2可达&#xff0c;记作0-2&#xff1b;s[i][j]1表示i-j可达&#xff0c;反之s[i][j]0表示i-j不可达&#xff1b;s[i][j…...

如何使用 findIndex() 方法查找数组中的第一个匹配元素的索引?

使用 findIndex() 方法查找数组中第一个匹配元素的索引 目录 简介findIndex() 方法概述如何使用 findIndex() 查找第一个匹配元素的索引 基本用法使用箭头函数和回调函数 实际项目中的代码示例 示例 1&#xff1a;查找第一个符合条件的用户索引示例 2&#xff1a;查找第一个符…...

5. 马科维茨资产组合模型+政策意图AI金融智能体(Qwen-Max)增强方案(理论+Python实战)

目录 0. 承前1. AI金融智能体1.1 What is AI金融智能体1.2 Why is AI金融智能体1.3 How to AI金融智能体 2. 数据要素&计算流程2.1 参数集设置2.2 数据获取&预处理2.3 收益率计算2.4 因子构建与预期收益率计算2.5 协方差矩阵计算2.6 投资组合优化2.7 持仓筛选2.8 AI金融…...

Centos类型服务器等保测评整/etc/pam.d/system-auth

修改服务器配置文件/etc/pam.d/system-auth&#xff0c;但是&#xff0c;把一下配置放在password的配置第一行才会生效 执行命令&#xff1a;配置口令要求&#xff1a;大小写字母、数字、特殊字符组合、至少8位&#xff0c;包括强制设置root口令&#xff01; sed -i 14a pas…...

从工厂到桌面:3D打印制造潮玩手办

传统潮玩手办的制造过程复杂且成本高昂。从设计到成品&#xff0c;需要经过多道工序&#xff0c;包括手工建模、模具制作、注塑成型等。这一过程不仅耗时耗力&#xff0c;而且难以满足消费者日益增长的个性化需求。此外&#xff0c;传统制造方式对于小批量生产或定制化产品的经…...

Java高频面试之SE-16

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; Java中异常的处理方式有哪些&#xff1f; 在 Java 中&#xff0c;异常的处理方式主要有以下几种&#xff1a; 1. 使用 try-catch 语句 …...

三分钟简单了解一些HTML的标签和语法_01

1.图片建议建立一个文件夹如下图所示 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"keywords"><title>魔神羽落</title><style>.testone{background-color: #ff53e…...

缓存-Redis-数据结构-redis哪些数据结构是跳表实现的?

在 Redis 中&#xff0c;跳表&#xff08;Skip List&#xff09; 被用于实现 有序集合&#xff08;Sorted Set&#xff09; 数据结构。以下是对此实现的详细解释&#xff1a; Redis中的有序集合&#xff08;Sorted Set&#xff09; 有序集合&#xff08;Sorted Set&#xff0…...

Linux 系统错误处理简介

Linux 系统错误处理简介 1. errno&#xff1a;错误代码的载体2. strerror()&#xff1a;错误信息的翻译官3. perror()&#xff1a;便捷的错误信息输出4. 系统调用与库函数的区别5. 错误处理的最佳实践 在 C/C 程序开发中&#xff0c;我们经常需要处理各种错误情况 Linux 系统提…...

逐笔成交逐笔委托Level2高频数据下载和分析:20250122

逐笔委托逐笔成交下载 链接: https://pan.baidu.com/s/1WP6eGLip3gAbt7yFKg4XqA?pwd7qtx 提取码: 7qtx Level2逐笔成交逐笔委托数据分享下载 通过Level2逐笔成交和逐笔委托这种每一笔的毫秒级别的数据可以分析出很多有用的点&#xff0c;包括主力意图&#xff0c;虚假动作&…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

多模态大语言模型arxiv论文略读(108)

CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题&#xff1a;CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者&#xff1a;Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...