Quartz [kwɔːts] 是OpenSymphony开源组织在Job scheduling领域又一个开源项目,完全由Java开发,可以用来执行定时任务,类似于java.util.Timer。但是相较于Timer, Quartz增加了很多功能:
1.持久性作业 - 就是保持调度定时的状态;
2.作业管理 - 对调度作业进行有效的管理;
Quartz是一个强大任务调度框架,可以用来干嘛?如一个OA系统需要在每周五9点自动生成数据报表,或者想每月10号自动还款,又或者每周给暗恋的女生定时发送邮件,又或者人事系统会在每天早晨8点给有待办的人员自动发送Email提醒。
下面介绍Quartz的三个核心概念(job,Trigger,Scheduler)。
1、任务job
job就是你想实现的任务类,每一个job必须实现org.quartz.job接口,且只需实现接口定义的execute()方法。
Job:工作任务调度的接口,任务类需要实现该接口,该接口中定义execute方法,类似jdk提供的TimeTask类的run方法,在里面编写任务执行的业务逻辑。
Job:实例在Quartz中的生命周期,每次调度器执行job时它在调用execute方法前,会创建一个新的job实例,当调用完成后,关联的job对象实例会被是释放,释放的实例会被垃圾回收机制回收。
2、触发器Trigger
Trigger 为你执行任务的触发器,比如你想每天定时1点发送邮件,Trigger将会设置1点执行该任务。
Trigger主要包含两种:SimpleTrigger和CronTriggerr。
3、调度器Scheduler
Scheduler是任务的调度器,会将任务job和触发器TRigger结合,负责基于Trigger设定的时间执行job。
Scheduler :用于与调度程序交互的主程序接口。
Job : 预先定义的希望在未来时间被调度程序执行的任务类,自定义。
JobDetall :使用JobDetail来定义定时任务的实例,JobDetail实例是通过JobBuilder类创建。
JobDataMap :可包含数据对象,在job实例执行的是好,可使用包含的数据;JobDataMap是java Map接口的实现,增加了一些存取基本类型方法。
Trgger触发器 :Trigger对象是用于触发执行Job的,当调度一个Job时,我们实例一个触发器然后调整它的属性来满足Job执行的条件,表明任务在什么时候执行。定义了一个已经被安排的任务将在什么时候执行的时间条件,比如每秒执行一次。
JobBuilder :用于声明一个任务实例,也可以定义关于该任务的详情比如:任务名,组名等,这个声明的实例将作为一个实例执行的任务。
TriggerBuilder :触发器创建器,用于创建触发器trigger实例。
JobListener,TriggerListener,SchedulerListener监听器,用于对组件的监听。
三、Spring Boot 集成Quartz
1、创建项目并加入依赖(Spring Boot的扩展默认集成Quartz)
<!-- quartz定时任务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
2、新建Job任务
/**
* 新建 Quartz的Job 任务
*/
public class MyJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("Hello Quartz");
}
}
3、创建Schedule,执行任务
public class QuartzTest {
public static void main(String[] args) throws Exception {
// 1. 创建一个JobDetail,把实现了Job接口的类邦定到JobDetail 构建者模式 绑定job withIdentity这里起一个唯一的名字
JobDetail jobDetail = JobBuilder.newJob(MyJob.class)
.withIdentity("job1") // 唯一标识
.build();
// 2.创建一个Trigger触发器的实例,定义该job立即执行,并且每2秒执行一次,一直执行 repeatForever重复
SimpleTrigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("trigger1") // 唯一标识
.startNow() // 立即生效
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(2) // 每2秒执行一次
.repeatForever()) // 一直重复执行
.build();
// 3.创建schedule调度器并执行 StdSchedulerFactory 工厂模式
StdSchedulerFactory factory = new StdSchedulerFactory();
// 获取调度器实例
Scheduler scheduler = factory.getScheduler();
// 开启调度器
scheduler.start();
// 把SimpleTrigger和JobDetail注册给调度器
scheduler.scheduleJob(jobDetail, trigger);
// 关闭调度器
// scheduler.shutdown();
}
}
运行程序,控制台会每两秒打印一个"Hello Quartz"。
Job是Quartz中的一个接口,接口下只有execute方法,在这个方法中编写业务逻辑。
JobDetail用来绑定Job,为Job实例提供许多属性:
name group jobClass jobDataMap
JobDetail绑定指定的Job,每次Scheduler调度执行一个Job的时候,首先会拿到对应的Job,然后创建该Job实例,再去执行Job中的execute()的内容,任务执行结束后,关联的Job对象实例会被释放,且会被JVM GC清除。
为什么设计成JobDetail + Job,不直接使用Job
JobDetail定义的是任务数据,而真正的执行逻辑是在Job中。 这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。而JobDetail & Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以规避并发访问的问题。
Trigger
Trigger是Quartz的触发器,会去通知Scheduler何时去执行对应Job。
new Trigger().startAt():表示触发器首次被触发的时间;
new Trigger().endAt():表示触发器结束触发的时间;
SimpleTrigger
SimpleTrigger可以实现在一个指定时间段内执行一次作业任务或一个时间段内多次执行作业任务。
下面的程序就实现了程序运行5s后开始执行Job,执行Job 5s后结束执行:
Date startDate = new Date();
startDate.setTime(startDate.getTime() + 5000);
Date endDate = new Date();
endDate.setTime(startDate.getTime() + 5000);
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", "triggerGroup1")
.usingJobData("trigger1", "这是jobDetail1的trigger")
.startNow()//立即生效
.startAt(startDate)
.endAt(endDate)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(1)//每隔1s执行一次
.repeatForever())
.build();//一直执行
CronTrigger
CronTrigger功能非常强大,是基于日历的作业调度,而SimpleTrigger是精准指定间隔,所以相比SimpleTrigger,CroTrigger更加常用。CroTrigger是基于Cron表达式的。
public class MyScheduler2 {
public static void main(String[] args) throws SchedulerException, InterruptedException {
//1.创建JobDetail实例,并与PrintWordsJob类绑定(Job执行内容)
JobDetail jobDetail=JobBuilder.newJob(PrintWordsJob.class)
.usingJobData("jobDetail", "这个Job用来测试的")
.withIdentity("job","group")
.build();
//2.触发器
CronTrigger trigger=TriggerBuilder.newTrigger().withIdentity("trigger", "group").startNow()//立刻执行
.usingJobData("trigger1", "这是jobDetail1的trigger")
.withSchedule(CronScheduleBuilder.cronSchedule("0 * * * * ?"))//表示每次0秒时候执行。
.build();
//3.调度器
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.scheduleJob(jobDetail,trigger);
System.out.println("--------scheduler start ! ------------");
scheduler.start();
System.out.println("--------scheduler shutdown ! ------------");
}
}
JobDetail是任务的定义,而Job是任务的执行逻辑。在JobDetail里会引用一个Job Class定义。
每一个JobDetail都会有一个JobDataMap。JobDataMap本质就是一个Map的扩展类,只是提供了一些更便捷的方法,比如getString()之类的。
1.编写触发类
public static void demo2()throws Exception{
//1. 创建一个JobDetail,把实现了Job接口的类邦定到JobDetail
JobDetail jobDetail= JobBuilder.newJob(SecondJob.class)
.withIdentity("demo2")
.usingJobData("name","zhangan")
.usingJobData("age",22)
.build();
CronTrigger trigger=TriggerBuilder.newTrigger()
.withIdentity("trriger2")
.withSchedule(CronScheduleBuilder
.cronSchedule("45 50 10 * * ?"))
.build();
//创建schedule实例
StdSchedulerFactory factory = new StdSchedulerFactory();
//获取调度器实例
Scheduler scheduler = factory.getScheduler();
//开启调度器
scheduler.start();
//把SimpleTrigger和JobDetail注册给调度器
scheduler.scheduleJob(jobDetail,trigger);
}
2.编写具体任务类
public class SecondJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
//打印当前的执行时间 例如 2021-08-30 10:12:00
Date date = new Date();
//格式化时间
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("现在的时间是:"+ sf.format(date));
//具体的业务逻辑
System.out.println("开始生成任务报表 或 开始发送邮件");
JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
String name= jobDataMap.getString("name");
int age= jobDataMap.getInt("age");
System.out.println("name="+name+",age="+age);
}
}
我在app/helpers/sessions_helper.rb中有一个帮助程序文件,其中包含一个方法my_preference,它返回当前登录用户的首选项。我想在集成测试中访问该方法。例如,这样我就可以在测试中使用getuser_path(my_preference)。在其他帖子中,我读到这可以通过在测试文件中包含requiresessions_helper来实现,但我仍然收到错误NameError:undefinedlocalvariableormethod'my_preference'.我做错了什么?require'test_helper'require'sessions_hel
有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url
我一直很高兴地使用DelayedJob习惯用法:foo.send_later(:bar)这会调用DelayedJob进程中对象foo的方法bar。我一直在使用DaemonSpawn在我的服务器上启动DelayedJob进程。但是...如果foo抛出异常,Hoptoad不会捕获它。这是任何这些包中的错误...还是我需要更改某些配置...或者我是否需要在DS或DJ中插入一些异常处理来调用Hoptoad通知程序?回应下面的第一条评论。classDelayedJobWorker 最佳答案 尝试monkeypatchingDelayed::W
我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b
我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。
我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
在前面两节的例子中,主界面窗口的尺寸和标签控件显示的矩形区域等,都是用C++代码编写的。窗口和控件的尺寸都是预估的,控件如果多起来,那就不好估计每个控件合适的位置和大小了。用C++代码编写图形界面的问题就是不直观,因此Qt项目开发了专门的可视化图形界面编辑器——QtDesigner(Qt设计师)。通过QtDesigner就可以很方便地创建图形界面文件*.ui,然后将ui文件应用到源代码里面,做到“所见即所得”,大大方便了图形界面的设计。本节就演示一下QtDesigner的简单使用,学习拖拽控件和设置控件属性,并将ui文件应用到Qt程序代码里。使用QtDesigner设计界面在开始菜单中找到「Q
前置步骤我们都操作完了,这篇开始介绍jenkins的集成。话不多说,看操作1、登录进入jenkins后会让你选择安装插件,选择第一个默认的就行。安装完成后设置账号密码,重新登录。2、配置JDK和Git都需要执行路径,所以需要先把执行路径找到,先进入服务器的docker容器,2.1JDK的路径root@69eef9ee86cf:/usr/bin#echo$JAVA_HOME/usr/local/openjdk-82.2Git的路径root@69eef9ee86cf:/#whichgit/usr/bin/git3、先配置JDK和Git。点击:ManageJenkins>>GlobalToolCon
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称