如何动态修改quartz的执行时间

如何动态修改quartz的执行时间,第1张

Spring Quartz如何动态配置时间

1. 目的:动态设置时间,触发相应的任务

2. 系统架构为 struts + spring + hibernate

3. 实现步骤:

在页面上设置时间;

将时间转换为Unix Cron Expression;

将转换后的时间规则表达式记录到数据库中(也可以写入xml文件中,这里是项目需要记录入数据库中);

从数据库中得到相应的时间规则表达式;

更新您的任务触发器的时间设置;

RESCHEDULE THE JOB。- )

4. 具体实现细节:

1) 在页面上设置时间

根据具体的业务需求,设置时间规则,下面以某一项目为例,需要 按每月、每周、自定义分为三种规则。

1 <tr >

2<th >执行这个任务 </ th >

3<td style ="font-weight:bold" >

4 <html:radio property ="everyWhat" styleClass ="InputBorderNone" value ="monthly" onclick ="changeStatus(this.value)" >每月 </ html:radio >

5 <html:radio property ="everyWhat" styleClass ="InputBorderNone" value ="weekly" onclick ="changeStatus(this.value)" >每周 </ html:radio >

6 <html:radio property ="everyWhat" styleClass ="InputBorderNone" value ="userDefined" onclick ="changeStatus(this.value)" >自定义 </ html:radio >

7 <html:hidden property ="jobName" value ="compare" />

8</ td >

9 </ tr >

10

每月则需要选择该月的第几个星期的星期几

1 <tr style ="display:" id ="whichWeek" >

2<th >选择第几个星期 </ th >

3<td style ="font-weight:bold" >

4 <html:select property ="week" >

5 <html:option value ="1" >一 </ html:option >

6 <html:option value ="2" >二 </ html:option >

7 <html:option value ="3" >三 </ html:option >

8 <html:option value ="4" >四 </ html:option >

9 </ html:select >

10 <html:select property ="dayOfMonth" >

11 <html:option value ="1" >星期日 </ html:option >

12 <html:option value ="2" >星期一 </ html:option >

13 <html:option value ="3" >星期二 </ html:option >

14 <html:option value ="4" >星期三 </ html:option >

15 <html:option value ="5" >星期四 </ html:option >

16 <html:option value ="6" >星期五 </ html:option >

17 <html:option value ="7" >星期六 </ html:option >

18 </ html:select >

19 </ td >

20 </ tr >

21

每周则需要选择星期几

1 <tr style ="display:none" id ="whichDay" >

2<th >选择星期 </ th >

3<td style ="font-weight:bold" >

4 <html:select property ="dayOfWeek" >

5 <html:option value ="1" >星期日 </ html:option >

6 <html:option value ="2" >星期一 </ html:option >

7 <html:option value ="3" >星期二 </ html:option >

8 <html:option value ="4" >星期三 </ html:option >

9 <html:option value ="5" >星期四 </ html:option >

10 <html:option value ="6" >星期五 </ html:option >

11 <html:option value ="7" >星期六 </ html:option >

12 </ html:select >

13 </ td >

14</ tr >

15

自定义则选择具体的日期,如 2007-1-10

三种规则都需要设定时间点

1 <tr >

2<th >起始时间 </ th >

3<td style ="font-weight:bold" >

4 <html:select property ="timeType" styleId ="type" onchange ="changeStatus2(this.value)" >

5 <html:option value ="AM" >上午 </ html:option >

6 <html:option value ="PM" >下午 </ html:option >

7 </ html:select >

8 <html:select property ="hour" styleId ="amHours" >

9 <html:option value ="1" >1 </ html:option >

10 <html:option value ="2" >2 </ html:option >

11 <html:option value ="3" >3 </ html:option >

12 <html:option value ="4" >4 </ html:option >

13 <html:option value ="5" >5 </ html:option >

14 <html:option value ="6" >6 </ html:option >

15 <html:option value ="7" >7 </ html:option >

16 <html:option value ="8" >8 </ html:option >

17 <html:option value ="9" >9 </ html:option >

18 <html:option value ="10" >10 </ html:option >

19 <html:option value ="11" >11 </ html:option >

20 <html:option value ="12" >12 </ html:option >

21 </ html:select >

22 <html:select property ="hour" styleId ="pmHours" style ="display:none" >

23 <html:option value ="13" >13 </ html:option >

24 <html:option value ="14" >14 </ html:option >

25 <html:option value ="15" >15 </ html:option >

26 <html:option value ="16" >16 </ html:option >

27 <html:option value ="17" >17 </ html:option >

28 <html:option value ="18" >18 </ html:option >

29 <html:option value ="19" >19 </ html:option >

30 <html:option value ="20" >20 </ html:option >

31 <html:option value ="21" >21 </ html:option >

32 <html:option value ="22" >22 </ html:option >

33 <html:option value ="23" >23 </ html:option >

34 <html:option value ="0" >0 </ html:option >

35 </ html:select > 点

36 <html:text property ="minute" name ="minute" style ="width:20px" value ="0" onchange ="valTime(this.value)" /> 分

37 <html:text property ="second" name ="second" style ="width:20px" value ="0" onchange ="valTime(this.value)" /> 秒(0-59之间的整数)

38</ td >

39 </ tr >

40

OK. 这样我们的页面设置就完成了。: - )

上回说到,我们的设置页面已经做好了,接下来就是将时间转换为Unix Cron Expression。

2) 将时间转换为Unix Cron Expression

需要ActionForm将页面表单数据映射到Action中,然后在Action中转换为cron expression:

1 SchedulerForm schedulerForm = (SchedulerForm) form

2 String jobName = schedulerForm.getJobName()

3 String cronExpression = ""

4 String[] commonNeeds = {schedulerForm.getSecond(), schedulerForm.getMinute(), schedulerForm.getHour()}

5 String[] monthlyNeeds = {schedulerForm.getWeek(), schedulerForm.getDayOfMonth()}

6 String weeklyNeeds = schedulerForm.getDayOfWeek()

7 String userDefinedNeeds = schedulerForm.getDate()

8 String everyWhat = schedulerForm.getEveryWhat()

9 // 得到时间规则

10 cronExpression = CronExpConversion.getCronExpression(everyWhat, commonNeeds,

11 monthlyNeeds, weeklyNeeds, userDefinedNeeds)

12

我定义了一个 规则类来处理转换规则(写得不是很好 能用就行 嘿嘿)

1

2 /**

3 * 页面设置转为UNIX cron expressions 转换类

4 * CronExpConversion

5 */

6 public class CronExpConversion {

7

8 /**

9 * 页面设置转为UNIX cron expressions 转换算法

10 * @param everyWhat

11 * @param commonNeeds 包括 second minute hour

12 * @param monthlyNeeds 包括 第几个星期 星期几

13 * @param weeklyNeeds 包括 星期几

14 * @param userDefinedNeeds 包括具体时间点

15 * @return cron expression

16 */

17 public static String convertDateToCronExp(String everyWhat,

18 String[] commonNeeds, String[] monthlyNeeds, String weeklyNeeds,

19 String userDefinedNeeds) {

20 String cronEx = ""

21 String commons = commonNeeds[ 0 ] + " " + commonNeeds[ 1 ] + " "

22 + commonNeeds[ 2 ] + " "

23 String dayOfWeek = ""

24 if ( " monthly " .equals(everyWhat)) {

25 // eg.: 6#3 (day 6 = Friday and "#3" = the 3rd one in the

26 // month)

27 dayOfWeek = monthlyNeeds[ 1 ]

28 + CronExRelated.specialCharacters

29 .get(CronExRelated._THENTH) + monthlyNeeds[ 0 ]

30 cronEx = (commons

31 + CronExRelated.specialCharacters.get(CronExRelated._ANY)

32 + " "

33 + CronExRelated.specialCharacters.get(CronExRelated._EVERY)

34 + " " + dayOfWeek + " " ).trim()

35 } else if ( " weekly " .equals(everyWhat)) {

36 dayOfWeek = weeklyNeeds // 1

37 cronEx = (commons

38 + CronExRelated.specialCharacters.get(CronExRelated._ANY)

39 + " "

40 + CronExRelated.specialCharacters.get(CronExRelated._EVERY)

41 + " " + dayOfWeek + " " ).trim()

42 } else if ( " userDefined " .equals(everyWhat)) {

43 String dayOfMonth = userDefinedNeeds.split( " - " )[ 2 ]

44 if (dayOfMonth.startsWith( " 0 " )) {

45 dayOfMonth = dayOfMonth.replaceFirst( " 0 " , "" )

46 }

47 String month = userDefinedNeeds.split( " - " )[ 1 ]

48 if (month.startsWith( " 0 " )) {

49 month = month.replaceFirst( " 0 " , "" )

50 }

51 String year = userDefinedNeeds.split( " - " )[ 0 ]

52 // FIXME 暂时不加年份 Quartz报错

53 /* cronEx = (commons + dayOfMonth + " " + month + " "

54 + CronExRelated.specialCharacters.get(CronExRelated._ANY)

55 + " " + year).trim()*/

56 cronEx = (commons + dayOfMonth + " " + month + " "

57 + CronExRelated.specialCharacters.get(CronExRelated._ANY)

58 + " " ).trim()

59 }

60 return cronEx

61 }

62 }

63

这样就将页面的时间设置转为了Cron Expression。

书接上回,上回说到,我们已经将页面的时间设置转为了Cron Expression,下面我记录了时间规则。

3) 记录时间规则

我将时间规则存入数据库中,目的是为了生成历史日志,也可以存入XML文件中。当然您也可以省略此步,直接将转换后的规则放入相应的Quartz trigger中。

4) 更新任务触发器的时间设置

到了关键的一步了,也是最简单的一步,一个方法就可以实现了。

首先,我们需要通过trigger的名称得到一个CronTriggerBean;

其次,通过trigger的setCronExpression(String cronExp)方法将新的表达式注入;

最后,RESCHEDULE THE JOB,OK!

第一步:引包

要使用Quartz,必须要引入以下这几个包:

1、log4j-1.2.16

2、quartz-2.1.7

3、slf4j-api-1.6.1.jar

4、slf4j-log4j12-1.6.1.jar

这些包都在下载的Quartz包里面包含着,因此没有必要为寻找这几个包而头疼。

第二步:创建要被定执行的任务类

这一步也很简单,只需要创建一个实现了org.quartz.Job接口的类,并实现这个接口的唯一一个方法execute(JobExecutionContext arg0) throws JobExecutionException即可。如:

import java.text.SimpleDateFormat

import java.util.Date

import org.quartz.Job

import org.quartz.JobExecutionContext

import org.quartz.JobExecutionException

public class myJob implements Job {

@Override

public void execute(JobExecutionContext arg0) throws JobExecutionException {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS")

System.out.println(sdf.format(new Date()))

}

}

import java.text.SimpleDateFormat

import java.util.Date

import org.quartz.Job

import org.quartz.JobExecutionContext

import org.quartz.JobExecutionException

public class myJob implements Job {

@Override

public void execute(JobExecutionContext arg0) throws JobExecutionException {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS")

System.out.println(sdf.format(new Date()))

}

}

这个例子很简单,就不用解说了。

第三步:创建任务调度,并执行

这一步应该算是最难的一步的,但其实是非常简单的,直接上代码

import static org.quartz.CronScheduleBuilder.cronSchedule

import static org.quartz.JobBuilder.newJob

import static org.quartz.TriggerBuilder.newTrigger

import java.text.SimpleDateFormat

import java.util.Date

import org.quartz.CronTrigger

import org.quartz.JobDetail

import org.quartz.Scheduler

import org.quartz.SchedulerFactory

import org.quartz.impl.StdSchedulerFactory

public class Test {

public void go() throws Exception {

// 首先,必需要取得一个Scheduler的引用

SchedulerFactory sf = new StdSchedulerFactory()

Scheduler sched = sf.getScheduler()

//jobs可以在scheduled的sched.start()方法前被调用

//job 1将每隔20秒执行一次

JobDetail job = newJob(myJob.class).withIdentity("job1", "group1").build()

CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build()

Date ft = sched.scheduleJob(job, trigger)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS")

System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: " + trigger.getCronExpression())

// job 2将每2分钟执行一次(在该分钟的第15秒)

job = newJob(myJob.class).withIdentity("job2", "group1").build()

trigger = newTrigger().withIdentity("trigger2", "group1").withSchedule(cronSchedule("15 0/2 * * * ?")).build()

ft = sched.scheduleJob(job, trigger)

System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: "+ trigger.getCronExpression())

// 开始执行,start()方法被调用后,计时器就开始工作,计时调度中允许放入N个Job

sched.start()

try {

//主线程等待一分钟

Thread.sleep(60L * 1000L)

} catch (Exception e) {}

//关闭定时调度,定时器不再工作

sched.shutdown(true)

}

public static void main(String[] args) throws Exception {

Test test = new Test()

test.go()

}

}

import static org.quartz.CronScheduleBuilder.cronSchedule

import static org.quartz.JobBuilder.newJob

import static org.quartz.TriggerBuilder.newTrigger

import java.text.SimpleDateFormat

import java.util.Date

import org.quartz.CronTrigger

import org.quartz.JobDetail

import org.quartz.Scheduler

import org.quartz.SchedulerFactory

import org.quartz.impl.StdSchedulerFactory

public class Test {

public void go() throws Exception {

// 首先,必需要取得一个Scheduler的引用

SchedulerFactory sf = new StdSchedulerFactory()

Scheduler sched = sf.getScheduler()

//jobs可以在scheduled的sched.start()方法前被调用

//job 1将每隔20秒执行一次

JobDetail job = newJob(myJob.class).withIdentity("job1", "group1").build()

CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build()

Date ft = sched.scheduleJob(job, trigger)

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS")

System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: " + trigger.getCronExpression())

// job 2将每2分钟执行一次(在该分钟的第15秒)

job = newJob(myJob.class).withIdentity("job2", "group1").build()

trigger = newTrigger().withIdentity("trigger2", "group1").withSchedule(cronSchedule("15 0/2 * * * ?")).build()

ft = sched.scheduleJob(job, trigger)

System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + ",并且以如下重复规则重复执行: "+ trigger.getCronExpression())

// 开始执行,start()方法被调用后,计时器就开始工作,计时调度中允许放入N个Job

sched.start()

try {

//主线程等待一分钟

Thread.sleep(60L * 1000L)

} catch (Exception e) {}

//关闭定时调度,定时器不再工作

sched.shutdown(true)

}

public static void main(String[] args) throws Exception {

Test test = new Test()

test.go()

}

}

OK了,Job1和Job2就会被安排为定时执行了。此时程序是可以执行的了,但是可能会输出WARN级别日志,这是因为没有加log4j的配置文件,加上配置文件,就OK了。这里需要说明的地方只有一个,其它的可以直接Copy到您的项目里面。看代码:

CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build()

CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("0/20 * * * * ?")).build()

CronTrigger 支持比 SimpleTrigger 更具体的调度,而且也不是很复杂。基于 cron 表达式,CronTrigger 支持类似日历的重复间隔,而不是单一的时间间隔 —— 这相对 SimpleTrigger 而言是一大改进。

Cron 表达式包括以下 7 个字段

小时

月内日期

周内日期

年(可选字段)

特殊字符

Cron 触发器利用一系列特殊字符,如下所示:

反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。

问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。

在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。

井号(#)字符为给定月份指定具体的工作日实例。把“MON#2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。

星号(*)字符是通配字符,表示该字段可以接受任何可能的值。

所有这些定义看起来可能有些吓人,但是只要几分钟练习之后,cron 表达式就会显得十分简单。

清单 3 显示了 CronTrigger 的一个示例。请注意 SchedulerFactory、Scheduler 和 JobDetail 的实例化,与 SimpleTrigger 示例中的实例化是相同的。在这个示例中,只是修改了触发器。这里指定的 cron 表达式(“0/5 * * * * ?”)安排任务每 5 秒执行一次。

0 12/20 9-19 * * ?

每天从上午9:12分开始到下午19点,每20分钟执行一次.

关于cronExpression表达式,这里讲解一下:

字段 允许值 允许的特殊字符

秒 0-59 , - * /

分 0-59 , - * /

小时 0-23 , - * /

日期 1-31 , - * ? / L W C

月份 1-12 或者 JAN-DEC , - * /

星期 1-7 或者 SUN-SAT , - * ? / L C #

年(可选) 留空, 1970-2099 , - * /

表达式意义

"0 0 12 * * ?" 每天中午12点触发

"0 15 10 ? * *" 每天上午10:15触发

"0 15 10 * * ?" 每天上午10:15触发

"0 15 10 * * ? *" 每天上午10:15触发

"0 15 10 * * ? 2005" 2005年的每天上午10:15触发

"0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发

"0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发

"0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

"0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发

"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发

"0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发

"0 15 10 15 * ?" 每月15日上午10:15触发

"0 15 10 L * ?" 每月最后一日的上午10:15触发

"0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发

"0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发

每天早上6点

0 6 * * *

每两个小时

0 */2 * * *

晚上11点到早上8点之间每两个小时,早上八点

0 23-7/2,8 * * *

每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点

0 11 4 * 1-3

1月1日早上4点

0 4 1 1 *


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/6779535.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-03-28
下一篇2023-03-28

发表评论

登录后才能评论

评论列表(0条)

    保存