您好,登錄后才能下訂單哦!
定時任務在項目中經常會使用到,本文主要根據博主自己使用定時的經驗分如下幾點介紹定時任務:
1、Quartz定時任務簡介及Spring配置Quartz定時任務
2、SchedulerFactory對定時任務進行增刪改查
3、總結
Quartz定時任務簡介:
Quartz是項目中經常用到的定時任務之一,是一個完全由java編寫的開源作業調度框架,可以與J2EE與J2SE應用程序相結合也可以單獨使用,其主要組成部分包括Job、Scheduler、CronExpression,這里就不一一介紹了,下面介紹Spring如何配置Quartz。
配置Quartz需要明白的一點是配置Quartz即配置Job、Scheduler和CronExpression,這三部分配置完成后,就是一個完整的定時任務,配置如下:
<bean id= "TestJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="xx.TestQuartzJob"/> <!-- 可以封裝各種數據到JobExecutionContext里,包括接口、類,其中testServiceImpl是Spring管理的Bean,需要什么聲明 --> <property name="jobDataAsMap"> <map> <entry key="test" value="test"/> <entry key ="testServiceImpl" value-ref="testServiceImpl"/> </map> </property> </bean> <bean id= "TestTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="TestJobDetail" /> <property name="cronExpression" value="0 0/1 * * * ?" /> </bean> <bean id= "testSchedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers" > <list> <ref bean="TestTrigger" /> </list> </property> </bean> <bean id="testServiceImpl" class="xx.service.impl.TestServiceImpl">
配置完成后,就是增加一個為你執行一個任務的Java類。每一個Quartz Job必須有一個 實現了org.quartz.Job接口的具體類,代碼如下:
public class TestQuartzJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException { // 獲取Job配置的接口 TestServiceImpl testServiceImpl = (TestServiceImpl) arg0.getJobDetail().getJobDataMap().get("testServiceImpl"); // 執行業務方法 quartzStart(); } public void quartzStart(){ // 業務方法... } }
當然,在Job中其實不用特意的配置接口,使用Spring的注入即可,這里只是把這個配置接口的方法進行說明。
到這里,簡單的配置Quartz定時任務已經完成,下面附加一個我在項目中使用Quartz的情形:cronExpression表達式從數據庫讀取。
當時,我解決這個問題的方法是繼承org.springframework.scheduling.quartz.CronTriggerBean,設置cronExpression,具體代碼如下:
Trigger的配置要改:
<bean id="TestTrigger" class="xx.InitCronTriggerFactoryBean"> <property name="jobDetail" ref="TestJobDetail" /> <property name="key" value="key" /> </bean>
xx.InitCronTriggerFactoryBean代碼:
public class InitCronTriggerFactoryBean extends CronTriggerFactoryBean implements Serializable { private static final long serialVersionUID = 1L; @Resource private SysParamService sysParamService; private String key; public void setKey(String key) { this.key = key; setCronExpression(getCronExpressionFromDB()); } private String getCronExpressionFromDB() { if(StringUtils.isEmpty(key)) return "0 0/5 * * * ?"; SysParam sysParam = new SysParam(); try { sysParam = sysParamService.getNameByKey(key); } catch (Exception e) { e.printStackTrace(); } if(sysParam != null && !StringUtils.isEmpty(sysParam.getParamValue())) return sysParam.getParamValue(); return "0 0/5 * * * ?"; } }
其中,SysParamService是根據key到數據庫查詢對應的cronExpression表達式的接口,這個接口除了使用Spring注入,也可以使用set方法設置,如下:
<bean id="TestTrigger" class="xx.InitCronTriggerFactoryBean"> <property name="jobDetail" ref="TestJobDetail" /> <property name="key" value="key" /> <property name="sysParamService" ref="sysParamService" /> </bean> <bean id="sysParamService" class="xx.service.impl.SysParamServiceImpl">
這樣,在xx.InitCronTriggerFactoryBean就要加入sysParamService的set方法,此時的xx.InitCronTriggerFactoryBean代碼為:
public class InitCronTriggerFactoryBean extends CronTriggerFactoryBean implements Serializable { private static final long serialVersionUID = 1L; private SysParamServiceImpl sysParamService; private String key; public void setKey(String key) { this.key = key; } public void setSysParamService(SysParamServiceImpl sysParamService) { this.sysParamService = sysParamService; setCronExpression(getCronExpressionFromDB()); } private String getCronExpressionFromDB() { if(StringUtils.isEmpty(key)) return "0 0 0/1 * * ?"; SysParam sysParam = new SysParam(); try { sysParam = sysParamServiceImpl.getNameByKey(key); } catch (Exception e) { e.printStackTrace(); } if(sysParam != null && !StringUtils.isEmpty(sysParam.getParamValue())) return sysParam.getParamValue(); return "0 0 0/1 * * ?"; } }
Quartz定時任務到這里就差不多了,基本的配置和使用就是上面將的,想要深入了解Quartz可以在網上查找更多的資料,并在實踐中使用。接下來將講解在項目中使用的可以隨時對定時任務進行增刪改查操作的實例。
定時任務的增刪改查,其實可以看做是對數據進行增刪改查。不過,定時任務的增刪改查是操作Job和Trigger,具體代碼如下:
定時任務管理器代碼:
public class QuartzManager { private static final Logger logger = LogPresident.getRootLogger(); private static SchedulerFactory schedulerFactory = new StdSchedulerFactory(); private static Map<String, JobKey> jobKeyMap = new HashMap<String, JobKey>(); /** * 增加一個定時任務 * @author zhiyuan.wu * @date 2017年3月30日 * @param jobName * @param triggerName * @param cls * @param date */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void addJob(String jobName, String triggerName, Class cls, Date date) { try { Scheduler scheduler = schedulerFactory.getScheduler(); // job JobDetail jobDetail = JobBuilder.newJob(cls).withIdentity(jobName, Scheduler.DEFAULT_GROUP).build(); // 觸發器 SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger().withIdentity(triggerName, Scheduler.DEFAULT_GROUP).startAt(date).build(); scheduler.scheduleJob(jobDetail, trigger); // 啟動 scheduler.start(); jobKeyMap.put(jobDetail.getKey().getName(), jobDetail.getKey()); } catch (Exception e) { logger.error("--------添加定時任務出錯:" + e.getMessage(), e); } } /** * 刪除對應的定時任務 * @author zhiyuan.wu * @date 2017年3月29日 * @param jobKey */ public static void removeJob(JobKey jobKey) { Scheduler scheduler; try { scheduler = schedulerFactory.getScheduler(); scheduler.deleteJob(jobKey); jobKeyMap.remove(jobKey.getName()); } catch (SchedulerException e) { logger.error("--------刪除定時任務出錯:" + e.getMessage(), e); } } /** * 啟動所有定時任務 * @author zhiyuan.wu * @date 2017年3月29日 */ public static void startJobs() { try { Scheduler sched = schedulerFactory.getScheduler(); sched.start(); } catch (Exception e) { logger.error("--------啟動所有定時任務出錯:" + e.getMessage(), e); } } /** * 停止所有定時任務 * @author zhiyuan.wu * @date 2017年3月29日 */ public static void shutdownJobs() { try { Scheduler sched = schedulerFactory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { logger.error("--------停止所有定時任務出錯:" + e.getMessage(), e); } } /** * 修改定時任務 * @author zhiyuan.wu * @date 2017年3月29日 * @param jobKey * @param jobName * @param triggerName * @param cls * @param date */ @SuppressWarnings("rawtypes") public static void modifyJobTime(JobKey jobKey, String jobName, String triggerName, Class cls, Date date) { try { removeJob(jobKey); addJob(jobName, triggerName, cls, date); } catch (Exception e) { logger.error("--------修改定時任務出錯:" + e.getMessage(), e); } } /** * 打印當前定時任務的jobName * @author zhiyuan.wu * @date 2017年3月29日 * @throws SchedulerException */ public static void printJobName() throws SchedulerException { for (String jobName : jobKeyMap.keySet()) { logger.info("--------jobName:" + jobName); } } }
Job代碼:
public class TestJob implements Job { private static final Logger logger = LogPresident.getRootLogger(); public void execute(JobExecutionContext context) throws JobExecutionException { JobKey jobKey = context.getJobDetail().getKey(); logger.info("--------定時任務開始執行:" + jobKey.getName()); // 業務方法... // 移除定時任務 QuartzManager.removeJob(jobKey); } }
增加一個定時任務代碼:
QuartzManager.addJob(JobName, TriggerName , TestJob.class, Date);
這樣,在到達時間Date時,定時任務將會執行。不過這樣增加的任務是保存在內存中,項目重啟將會丟失定時任務,所以,最好增加一個類,在項目啟動時將會掃描數據庫,將未執行的定時任務重新加載到內存中去。
定時任務在項目中運用需要根據業務具體調整,但只要弄清楚定時任務的原理和實現,那么就可以在項目中靈活運它用來具體的業務,希望這篇文章可以讓大家快速了解和運用定時任務,并運用到實踐中。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。