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

本文介绍了一种基于Quartz的定时任务管理系统的设计与实现,包括如何动态添加、查询、暂停及重启任务等关键功能。此外,还提供了具体的代码示例和配置文件,帮助读者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

定时任务管理(一)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.youkuaiyun.com/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"
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="dataSource" 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值