quartz的总结

    技术2022-05-12  11

    对quartz的总结
      Quartz 是一个强大的企业级 Schedule 工具,也是目前最好的开源 Schedule 工具。Spring中也集成了quartz的应用,下面就讲一下如何在spring中使用quartz。 spring的配置: <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger"/> <ref bean="cornTrigger"/> </list> </property> </bean> <bean id="schedulerControl" class="com.pheh.scheduler.Schedule"> <property name="scheduler"> <ref bean="schedulerFactoryBean"/> </property> </bean> <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail"> <ref bean="methodInvokingJobDetail"/> </property> <property name="startDelay"> <value>1000</value> </property> <property name="repeatInterval"> <value>3000</value> </property> </bean> <bean id="cornTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail"> <ref bean="methodInvokingJobDetail"/> </property> <property name="cronExpression"> <value>0 0 */1 * * ?</value> </property> </bean> Job:   org.quartz.Job是一个接口,只定义了void execute(JobExecutionContext context)throws JobExecutionException; 一个方法。当定时任务被触发后,系统会自动调用实现了该接口的方法。在spring 中,org.springframework.scheduling.quartz.QuartzJobBean对其进行了封装,使用了Template Method模式。主要是为了在使用jobDataMap时更加方便。QuartzJobBean有两个方法, public final void execute(JobExecutionContext context) throws JobExecutionException Job接口中定义的,spring在该方法里进行了些处理,将jobDataMap中的值注入到该Job的实现者中 protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException 这是一个抽象方法,用户在扩展了QuartzJobBean后,要自己实现该方法,在其中添加相应的业务逻辑 JobDetail: JobDetail描述了一个任务具体的信息。在Spring中,JobDetailBean对JobDetail进行了封装(继承了JobDetail)。 private String name; //名称 private String group = Scheduler.DEFAULT_GROUP; //组 private String description; //描述 private Class jobClass; //定时任务触发时,回调的class,该class要实现Job接口或继承QuartzJobBean private JobDataMap jobDataMap; //该任务存储的数据,在回调的时候也可以使用 private boolean volatility = false; //是否持久化到org.quartz.spi.JobStore中 private boolean durability = false; //当该任务完成后,是否还在JobStore中继续保留该任务 private boolean shouldRecover = false; //当系统重新启动后,是否再次执行该任务 对于jobDataMap,它是是一个封装过的Map,使用方法同Map,如 jobDetailBean.getJobDataMap().put(target,value); 如果使用了QuartzJobBean,在使用jobDetailBean时,可将target的值设成QuartzJobBean的子类的属性名称,这 样,在定时触发时,spring会自动将与target对应的value值注入到QuartzJobBean的子类中去。如。 java 代码 ... public class ReminderManager extends QuartzJobBean{ private String reminderStr = ""; } ... jobDetailBean.getJobDataMap().put(reminderStr,"abcdefg"); ... 这样当该任务被触发后,在ReminderManager中,reminderStr的值就会被注入为"abcdefg"。 Trigger: trigger就是触发器。Quartz有个很好的想法就是分离了任务和任务执行的条件。Trigger就是控制任务执行条件的类,当Trigger认为执行条件满足的时刻,Trigger会通知相关的Job去执行。分离的好处是: 1.你可以为某个Job关联多个Trigger,其中任何一个条件满足都可以触发job执行,这样可以完成一些组合的高级触发条件 2.当Trigger失效后(比如:一个永远都不能满足的条件),你不必去声明一个新的job,代替的是你可以为job关联一个新的Trigger让job可以继续执行。 目前的Quartz实现中,存在两种Trigger,SimpleTrigger和CronTrigger,在spring中分别用 SimpleTriggerBean和CronTriggerBean对其进行封装。SimpleTrigger是简单触发器,如从某日到某日,每个一定 时间进行一次提醒,在这段时间内进行多少次提醒;CronTrigger是复杂触发器,用来执行calendar-like的任务,可设定一些复杂的触发 规则,如每年的x月的第y个星期五,或是每个星期天的几点进行提醒。后面附加一个日常语义与cronTrigger的转化 Trigger private String name; //名称 private String group = Scheduler.DEFAULT_GROUP; //组 private String jobName; //所关联的jobDetail的名称 private String jobGroup = Scheduler.DEFAULT_GROUP; //所关联的jobDetail的组 private String description; //描述 private JobDataMap jobDataMap; //该触发器存储的数据,在回调的时候也可以使用 private boolean volatility = false; //是否持久化到org.quartz.spi.JobStore中 SimpleTrigger private Date startTime = null; //开始日期 private Date endTime = null; //结束日期 private Date nextFireTime = null; //下次的触发时间 private Date previousFireTime = null; //上次的触发时间 private int repeatCount = 0; //重复次数 private long repeatInterval = 0; //重复间隔 private int timesTriggered = 0; /已触发的次数 SimpleTriggerBean private JobDetail jobDetail; //所关联的JobDetail,方便在配置文件中使用 CornTrigger private CronExpression cronEx = null; //触发条件表达式,它有一个String型的setter private Date startTime = null; //开始日期 private Date endTime = null; //结束日期 private Date nextFireTime = null; //下次的触发时间 private Date previousFireTime = null; //上次的触发时间 private transient TimeZone timeZone = null; //所在时区 CronTriggerBean private JobDetail jobDetail; //所关联的JobDetail,方便在配置文件中使用 Scheduler的常用方法 添加一个定时任务: Date scheduleJob(JobDetail jobDetail,Trigger trigger) 修改一个定时任务,主要是更改trigger: Date rescheduleJob(String triggerName, String groupName, Trigger newTrigger) 删除一个定时任务,同时也会将于该jobDetail关联的trigger一并删除: boolean deleteJob(String jobName,String jobGroup) 取得所有的jobDetail组 String[] getJobGroupNames() 取得某个group下的所有的jobDetail String[] getJobNames(String groupName) 取得指定的jobDetail JobDetail getJobDetail(String jobName, String jobGroup) 取得指定的jobDetail的所有的Trigger Trigger[] getTriggersOfJob(String jobName, String groupName) 取得指定的Trigger Trigger getTrigger(String triggerName, String triggerGroup) Quartz的存储: Quartz默认的是使用RAM存储所有的信息,但是这样的话,当我们重启服务器后,之前的所有的定时任务就全消失了。为了让服务器重启以后,我们的定时任务仍不丢失,我们可采用数据库持久化定时任务。 首先要先建立数据库,在quartz-1.6.0/docs/dbTables下,选择自己使用的数据库的sql脚本,建立相应的数据库表。 在WEB-INF下加一个quartz.properties。我们可以在 quartz-1.6.0/examples/example10 中找到该文件的样例 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX #表明使用JDBC进行持久化 org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.useProperties = false org.quartz.jobStore.dataSource = myDS org.quartz.jobStore.tablePrefix = QRTZ_ #该值尽量不要改动,如改动,还要相应的修改sql脚本 org.quartz.jobStore.isClustered = false org.quartz.dataSource.myDS.driver = net.sourceforge.jtds.jdbc.Driver org.quartz.dataSource.myDS.URL = jdbc:jtds:sqlserver://192.168.1.101:1433/Northwind; autoReconnect=true org.quartz.dataSource.myDS.user = sa org.quartz.dataSource.myDS.password = org.quartz.dataSource.myDS.maxConnections = 5 日常语义与cronTrigger的转化,以下setter,getter省略 java 代码 public class TDateRange{ private int startType = 2; //开始类型。默认的使用2表示使用开始日期 private Date startDate = new Date(); //开始日期 private int endType = 0; //结束类型。0表示无结束时间;1表示重复n次后结束;2表示使用结束日期 private Date endDate = new Date(); //结束日期 private int occurrences; //执行次数 } public class TFrequency{ //0:无重复提醒 //1:每every //2:每个工作日detail=1,2,3,4,5 //3:每every周后的星期detail日 //4:每every月的detail日 //5:每every月的第num1个星期num2 //6:每年num1月num2日 //7:每年every月的第num1个月的星期num2 private int type = 0; //频率类型 private int every = 0; private String detail = ""; private String num1 = ""; private String num2 = ""; } private String formatQuartzString(){ String quartzStr = ""; tiggernote=""; //秒 分 时 quartzStr = "0 "+this.dateRange.getStartDate().getMinutes()+" "+this.dateRange.getStartDate().getHours()+" "; switch(this.frequency.getType()){ case 0://无重复提醒 quartzStr += this.dateRange.getStartDate().getDate()+" "+(this.dateRange.getStartDate().getMonth()+1)+" ? "+(this.dateRange.getStartDate().getYear()+1900); tiggernote+="起始时间:"+quartzStr; break; case 1://每XX天提醒 quartzStr += "*/"+this.frequency.getEvery()+" * ? "; tiggernote+="每"+this.frequency.getEvery()+"提醒"; break; case 2://每个工作日detail=1,2,3,4,5 //quartzStr += "? * 2-6"; quartzStr ="0 */1 * * * ?"; //测试 tiggernote+="每个工作日1,2,3,4,5提醒"; break; case 3://每every周后的星期detail日 quartzStr += "? * "+this.frequency.getDetail()+"/"+this.frequency.getEvery(); tiggernote+="每"+this.frequency.getEvery()+"周星期"+this.frequency.getDetail()+"日"; break; case 4://每every个月的detail日 quartzStr += this.frequency.getDetail()+" */"+this.frequency.getEvery()+" ?"; tiggernote+="每"+this.frequency.getEvery()+"月"+this.frequency.getDetail()+"日"; break; case 5://每every个月的第num1个星期num2 quartzStr += "? */"+this.frequency.getEvery()+" "+this.frequency.getNum2(); //星期 if(Integer.valueOf(this.frequency.getNum1()).intValue()>0){ quartzStr += "#"+this.frequency.getNum1(); tiggernote+="每"+this.frequency.getEvery()+"月第"+this.frequency.getNum1()+"个星期"+this.frequency.getNum2()+"日"; }else{ quartzStr += "L"; tiggernote+="每"+this.frequency.getEvery()+"月星期"+this.frequency.getNum2(); } break; case 6://每年num1月num2日 quartzStr += this.frequency.getNum2()+" "+this.frequency.getNum1()+" ?"; tiggernote+="每年"+this.frequency.getNum1()+"月"+this.frequency.getNum2()+"日"; break; case 7://每年every月的第num1个星期num2 quartzStr += "? "+this.getFrequency().getEvery()+" "+this.getFrequency().getNum2(); //星期 if(Integer.valueOf(this.frequency.getNum1()).intValue()>0){ quartzStr += "#"+this.frequency.getNum1(); tiggernote+="每年"+this.getFrequency().getEvery()+"月的第"+this.frequency.getNum1()+"个星期"+this.getFrequency().getNum2()+"日"; }else{ quartzStr += "L"; tiggernote+="每年"+this.getFrequency().getEvery()+"月的"+this.getFrequency().getNum2()+"日"; } break; default : } log.debug("quartzStr="+quartzStr); return quartzStr; } Scheduler: Scheduler 是一个计划集,其中可以包含多个 JobDetail 和 Trigger 组成的计划任务。 在Quartz中,我们可以通过 SchedulerFactory scheduleFactory = new StdSchedulerFactory(); Scheduler scheduler = scheduleFactory.getScheduler(); 来取得scheduler,通过调用scheduler.start()来启动quartz。 在spring中,org.springframework.scheduling.quartz.SchedulerFactoryBean是对 Quartz的org.quartz.Scheduler的封装,通过上面的配置,在spring启动的时候,quartz就会跟随着启动,不需要再用 scheduler.start()来启动。在spring中,如果要取得scheduler,可通过上面的配置文件那样,将 SchedulerFactoryBean注入到schdeuler中。

    最新回复(0)