首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

定时任务管理(1)quartz了解

2012-11-13 
定时任务管理(一)quartz了解定时任务管理(一)quartz了解最近公司需要做个quartz定时任务管理的单独项目,需

定时任务管理(一)quartz了解
定时任务管理(一)quartz了解

最近公司需要做个quartz定时任务管理的单独项目,需求是可以调度本省项目中的groovy文件操作数据库来统计出数据放置到XML等文件中;或者调用其他业务模块的jar包里面的业务manager方法去查询,得到结果存放到XML等文件中。

quartz首页
http://www.quartz-scheduler.org/
详细文档
file:///E:/book/opensource/quartz/quartz-1.6.6/docs/wikidocs/index.html

我参考了如下文章:
容器启动时就装在用户定的时间设置
http://blog.csdn.net/vvggsky/archive/2007/03/01/1517744.aspx
实现了动态设定任务时间
(一)http://allen-zhe.iteye.com/blog/48305
(二)http://allen-zhe.iteye.com/blog/48304
(三)http://allen-zhe.iteye.com/blog/48303
实现了动态任务设置
http://devbbs.doit.com.cn/thread-10948-1-1.html

按照这些文章上的,部署了实例,并开始查看代码和数据库
添加一个Job在表qrtz_job_details插入一条记录
添加一个Simple Trigger在表qrtz_simple_triggers插入一条记录
添加一个Cron Trigger 在表qrtz_cron_triggers插入一条记录
添加Simple Trigger和Cron Trigger都会同进在表qrtz_triggers插入一条记录,开始看的第一个页面调度任务列表数据就是从qrtz_triggers表获取的

在参考别人BLOG的基础上,我想让JOB也得到管理,所以我在DAO上增加了一个方法,当然,也没有修改应用使用IBATIS实现,还是使用的它原有的template,QuartzDAOImpl.java如下,其中的两条SQL是核心,是我查询jobs和triggers时使用的:
@SuppressWarnings("unchecked")
//返回所有的任务
public List<Map<String, Object>> getOrtzJobs() {
List<Map<String, Object>> results = getJdbcTemplate().queryForList(
    "select * from QRTZ_JOB_DETAILS");
String temp = null;
for (Map<String, Object> map : results) {
   temp = MapUtils.getString(map, "job_name");
   map.put("display_name", StringUtil.getOrgName(temp));
}
return results;
}
@SuppressWarnings("unchecked")
// 返回所有triggers
public List<Map<String, Object>> getQrtzTriggers() {
List<Map<String, Object>> results = getJdbcTemplate().queryForList(
    "select * from QRTZ_TRIGGERS order by start_time");
long val = 0;
String temp = null;
for (Map<String, Object> map : results) {
   temp = MapUtils.getString(map, "trigger_name");
   map.put("display_name", StringUtil.getOrgName(temp));
   temp = MapUtils.getString(map, "job_name");
   map.put("display_job_name", StringUtil.getOrgName(temp)); 
   val = MapUtils.getLongValue(map, "next_fire_time");
   if (val > 0) {
    map.put("next_fire_time", DateFormatUtils.format(val,
      "yyyy-MM-dd HH:mm:ss"));
   }
   val = MapUtils.getLongValue(map, "prev_fire_time");
   if (val > 0) {
    map.put("prev_fire_time", DateFormatUtils.format(val,
      "yyyy-MM-dd HH:mm:ss"));
   }
   val = MapUtils.getLongValue(map, "start_time");
   if (val > 0) {
    map.put("start_time", DateFormatUtils.format(val,
      "yyyy-MM-dd HH:mm:ss"));
   }
   val = MapUtils.getLongValue(map, "end_time");
   if (val > 0) {
    map.put("end_time", DateFormatUtils.format(val,
      "yyyy-MM-dd HH:mm:ss"));
   }
   map.put("status", Constant.status.get(MapUtils.getString(map,
     "trigger_state")));
}
return results;
}
在原有SchedulerService的基础上,增加了对job的管理的方法,SchedulerServiceImpl.java如下:
// 新增job
public void addJob(String jobName, String groupName, String jobClassName,
   Map<String, Object> paras) {
jobName = StringUtil.getUUIDName(jobName);
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
if (StringUtil.isBlank(jobClassName)) {
   log.error("jobClassName can't be null!");
   throw new RuntimeException("jobClassName can't be null!");
}
Job jobClass = null;
try {
   jobClass = (Job) Class.forName(jobClassName).newInstance();
} catch (ClassNotFoundException e) {
   log.error(e.getMessage());
   throw new RuntimeException(e);
} catch (InstantiationException e) {
   log.error(e.getMessage());
   throw new RuntimeException(e);
} catch (IllegalAccessException e) {
   log.error(e.getMessage());
   throw new RuntimeException(e);
}
JobDetail jobDetail = null;
jobDetail = new JobDetail(jobName, groupName, jobClass.getClass());
if (paras != null && paras.isEmpty()) {
   jobDetail.getJobDataMap().putAll(paras);
}
try {
   scheduler.addJob(jobDetail, true);
} catch (SchedulerException e) {
   log.error(e.getMessage());
   throw new RuntimeException(e);
}
}
// 新增spring job,paras里面是关联bean,用“,”分隔
public void addSpringJob(String jobName, String groupName,
   String springBeanName, Map<String, Object> paras) {
jobName = StringUtil.getUUIDName(jobName);
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
if (StringUtil.isBlank(springBeanName)) {
   log.error("springBeanName can't be null!");
   throw new RuntimeException("springBeanName can't be null!");
}
Job job = null;
ApplicationContext cxt = getApplicationContext();
if (cxt == null) {
   log.error("spring context is null!");
   throw new RuntimeException("spring context is null!");
}
Object jobDetail_obj = cxt.getBean(springBeanName);
if (jobDetail_obj == null) {
   log.error("context has not bean named: " + springBeanName);
   throw new RuntimeException("context has not bean named: "
     + springBeanName);
}
job = (Job) jobDetail_obj;
JobDetail jobDetail = null;
jobDetail = new JobDetailBean();
jobDetail.setName(jobName);
jobDetail.setGroup(groupName);
jobDetail.setJobClass(job.getClass());
if (paras != null && !paras.isEmpty()) {
   JobDataMap jobDataMap = new JobDataMap();
   jobDataMap.putAll(paras);
   Object relateBeans_obj = paras.get("RELATE_BEANS");
   if (relateBeans_obj != null) {
    String relateBeans_str = (String) relateBeans_obj;
    if (StringUtil.isNotBlank(relateBeans_str)) {
     String[] relateBeans = relateBeans_str.split(",");
     if (relateBeans != null && relateBeans.length > 0) {
      for (int i = 0; i < relateBeans.length; i++) {
       String relateBean = relateBeans[i];
       jobDataMap.put(relateBean, cxt.getBean(relateBean));
      }
     }
    }
   }
   jobDetail.setJobDataMap(jobDataMap);
}
try {
   scheduler.addJob(jobDetail, true);
} catch (SchedulerException e) {
   log.error(e.getMessage());
   throw new RuntimeException(e);
}
}
// 新增触发器
public void addTrigger(String triggerName, String cronExpression,
   String groupName, String jobName) {
CronExpression cron = null;
try {
   cron = new CronExpression(cronExpression);
} catch (ParseException e) {
   log.error(e.getMessage());
   throw new RuntimeException(e);
}
addTrigger(triggerName, cron, groupName, jobName);
}
// 触发器真实新增方法
private void addTrigger(String triggerName, CronExpression cronExpression,
   String groupName, String jobName) {
triggerName = StringUtil.getUUIDName(triggerName);
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
if (StringUtil.isBlank(jobName)) {
   log.error("jobName can't be null");
   throw new RuntimeException("jobName can't be null");
}
try {
   CronTrigger cronTrigger = new CronTrigger(triggerName, groupName,
     jobName, groupName);
   cronTrigger.setCronExpression(cronExpression);
   scheduler.scheduleJob(cronTrigger);
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 创建一个触发器,定时启动,每隔n秒启动一次,定时停止
public void addTrigger(String triggerName, long n, String groupName,
   String jobName, Date startTime, Date endTime) {
if (startTime == null) {
   startTime = new Date();
}
addTrigger(triggerName, startTime, endTime,
   SimpleTrigger.REPEAT_INDEFINITELY, n * 1000L, groupName,jobName);
}
// 触发器真实新增方法
private void addTrigger(String triggerName, Date startTime, Date endTime,
   int repeatCount, long repeatInterval, String groupName,
   String jobName) {
triggerName = StringUtil.getUUIDName(triggerName);
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
if (StringUtil.isBlank(jobName)) {
   log.error("jobName can't be null");
   throw new RuntimeException("jobName can't be null");
}
try {
   SimpleTrigger SimpleTrigger = new SimpleTrigger(triggerName,
     groupName, jobName, groupName, startTime, endTime,
     repeatCount, repeatInterval);
   scheduler.scheduleJob(SimpleTrigger);
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 返回所有triggers
public List<Map<String, Object>> getQrtzTriggers() {
return quartzDAO.getQrtzTriggers();
}
// 返回所有jobs
public List<Map<String, Object>> getQrtzJobs() {
return quartzDAO.getOrtzJobs();
}
// 暂停trigger
public void pauseTrigger(String triggerName, String groupName) {
if (StringUtil.isBlank(triggerName)) {
   throw new RuntimeException(
     "triggerName can't be null when pauseTrigger!");
}
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
try {
   scheduler.pauseTrigger(triggerName, groupName);// 停止触发器
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 暂停job
public void pauseJob(String jobName, String groupName) {
if (StringUtil.isBlank(jobName)) {
   throw new RuntimeException("jobName can't be null when pauseJob!");
}
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
try {
   scheduler.pauseJob(jobName, groupName); // 停止任务
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 重启trigger
public void resumeTrigger(String triggerName, String groupName) {
if (StringUtil.isBlank(triggerName)) {
   throw new RuntimeException(
     "triggerName can't be null when resumeTrigger!");
}
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
try {
   scheduler.resumeTrigger(triggerName, groupName);// 重启触发器
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 重启job
public void resumeJob(String jobName, String groupName) {
if (StringUtil.isBlank(jobName)) {
   throw new RuntimeException("jobName can't be null when resumeJob!");
}
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
try {
   scheduler.resumeJob(jobName, groupName); // 重启任务
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 删除trigger
public boolean removeTrigger(String triggerName, String groupName) {
if (StringUtil.isBlank(triggerName)) {
   throw new RuntimeException(
    "triggerName can't be null when removeTrigger!");
}
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
try {
   scheduler.pauseTrigger(triggerName, groupName);// 停止触发器
   return scheduler.unscheduleJob(triggerName, groupName);// 移除触发器
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
// 删除job
public boolean removeJob(String jobName, String groupName) {
if (StringUtil.isBlank(jobName)) {
   throw new RuntimeException("jobName can't be null when removeJob!");
}
if (StringUtil.isBlank(groupName)) {
   groupName = Scheduler.DEFAULT_GROUP;
}
try {
   scheduler.pauseJob(jobName, groupName);// 停止任务
   return scheduler.deleteJob(jobName, groupName);// 删除job
} catch (SchedulerException e) {
   throw new RuntimeException(e);
}
}
在spring的配置文件上,和quartz相关的配置只有如下,quartz-context.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean name="quartzScheduler"
   ref="dataSource" />
   <property name="applicationContextSchedulerContextKey" value="applicationContextKey" />
   <property name="configLocation" value="classpath:quartz.properties" />
   <!-- 延时启动,这个很重要,必须要有足够长的时间让你的应用先启动完成后再让 Scheduler启动,
   这里设置60秒,如果你的应用启动时间较长,要相应增加startupDelay的时间-->
   <property name="startupDelay" value="60"/>
   <property name="overwriteExistingJobs" value="true" />
</bean>
</beans>
另外其中引用到的一个quartz.properties:
org.quartz.scheduler.instanceName=DefaultQuartzScheduler
org.quartz.scheduler.rmi.export=false
org.quartz.scheduler.rmi.proxy=false
org.quartz.scheduler.wrapJobExecutionInUserTransaction=false
org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount=10
org.quartz.threadPool.threadPriority=5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
org.quartz.jobStore.misfireThreshold=60000
#org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#mysql使用如下配置
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#oracle使用如下配置
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.useProperties=true
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.isClustered=false
org.quartz.jobStore.maxMisfiresToHandleAtATime=1
另外,这里例举一些在搜索文档时,看到的cron表达式举例:
"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触发

和quartz相关的东东就是这么多了,主要的新增添加等功能,都是通过SchedulerServiceImpl来完成的,两个搜索是通过自己写的DAO实现去搜索数据库的来的。具体项目请参考tasksupervisor

热点排行