1、编写Job任务
package com.kvt.lbs.alarm.entity;
import java.util.List;
import javax.annotation.Resource;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.kvt.lbs.alarm.dao.AlarmDao;
import com.kvt.lbs.utils.Log;
/**
* 报警定时任务
* <li>文件名称: AlarmJob</li>
* <li>文件描述: $报警定时任务</li>
* <li>内容摘要: 包括任务执行方法和执行频率</li>
* <li>完成日期:2013-6-17</li>
* <li>修改记录1:boonya</li>
*
*/
@Component("alarmJob")
public class AlarmJob implements Job
{
@Resource
private AlarmDao alarmDao;
@Transactional(propagation = Propagation.REQUIRED)
public void execute(JobExecutionContext jbec) throws JobExecutionException
{
// doFlag处理类型:0未处理,1已处理,2过期处理
// operateWay操作方式:1手动过期,2系统过期
int doFlag=2,operateWay=2;
boolean isSuccess=true;
String operator = "定时任务", remark = "系统定时过期处理";
Log.getLogger(this.getClass()).info("==Start====报警数据:系统过期处理-----------开始");
String[] deviceIdToalarmTypeArray = this.getDeviceIdToAlarmTypekeys();
if (deviceIdToalarmTypeArray.length>0)
{
isSuccess= alarmDao.handleAlarmByOvertime(deviceIdToalarmTypeArray,doFlag,operateWay, operator, remark);
}
Log.getLogger(this.getClass()).info("==Results==报警数据:系统过期处理" + (isSuccess ? "成功" : "失败")+" ,处理数据条数: "+deviceIdToalarmTypeArray.length);
Log.getLogger(this.getClass()).info("==End======报警数据:系统过期处理-----------完成");
}
/**
* 获取内存中需要过期处理的报警的Key数组
*
* @return
*/
public String[] getDeviceIdToAlarmTypekeys()
{
String[] deviceIdToalarmTypeArray = new String [0];
long longDeTime = 1 * 24 * 60 * 60 * 1000;// 24小时后过期
List<String> list = alarmDao.getOvertimeDeviceIdToAlarmTypeKeys(longDeTime);
if (list != null)
{
deviceIdToalarmTypeArray = new String[list.size()];
for (int i = 0; i < list.size(); i++)
{
deviceIdToalarmTypeArray[i] = list.get(i);
}
}
return deviceIdToalarmTypeArray;
}
}
2、编写定时调用服务
package com.kvt.lbs.alarm.service;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.TriggerUtils;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Component;
import com.kvt.lbs.alarm.entity.AlarmJob;
import com.kvt.lbs.utils.Log;
/**
* 报警定时任务服务
* <li>文件名称: AlarmJobService</li>
* <li>文件描述: $报警过期处理</li>
* <li>内容摘要: 启动报警过期定时任务</li>
* <li>完成日期:2013-5-29</li>
* <li>修改记录1:boonya</li>
*
*/
@Component("alarmJobService")
public class AlarmJobService
{
public void start()
{
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = null;
try
{
Log.getLogger(this.getClass()).info("==Start==告警过期处理定时任务启动===========");
scheduler = sf.getScheduler();
JobDetail job = new JobDetail("alarmJob", "alarm", AlarmJob.class);
Trigger trigger = TriggerUtils.makeDailyTrigger("alarmTrigger", 23, 59);// 每天23:59分执行任务
scheduler.resumeJob("alarmJob", "alarmJob");
scheduler.resumeJobGroup("alarm");
scheduler.scheduleJob(job, trigger);
scheduler.start();
Log.getLogger(this.getClass()).info("==End==告警过期处理定时任务启动成功========");
} catch (Exception e)
{
try
{
Log.getLogger(this.getClass()).info("==Exception==告警过期处理:"+e.getMessage());
scheduler.shutdown(true);
Log.getLogger(this.getClass()).info("==End==告警过期处理:异常停止!");
} catch (SchedulerException e1)
{
Log.getLogger(this.getClass()).info("==Exception==告警过期处理:"+e1.getMessage());
}
}
}
}
3、启动控制台日志
2013-07-30 14:43:28 [ localhost-startStop-1:6812 ] - [ INFO ] ==Start==告警过期处理定时任务启动===========
2013-07-30 14:43:28 [ localhost-startStop-1:6812 ] - [ INFO ] Job execution threads will use class loader of thread: localhost-startStop-1
2013-07-30 14:43:28 [ localhost-startStop-1:6828 ] - [ INFO ] Quartz Scheduler v.1.6.0 created.
2013-07-30 14:43:28 [ localhost-startStop-1:6828 ] - [ INFO ] RAMJobStore initialized.
2013-07-30 14:43:28 [ localhost-startStop-1:6828 ] - [ INFO ] Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
2013-07-30 14:43:28 [ localhost-startStop-1:6828 ] - [ INFO ] Quartz scheduler version: 1.6.0
2013-07-30 14:43:28 [ localhost-startStop-1:6828 ] - [ INFO ] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
2013-07-30 14:43:28 [ localhost-startStop-1:6828 ] - [ INFO ] ==End==告警过期处理定时任务启动成功========
4、执行任务时错误
2013-07-30 15:09:00 [ DefaultQuartzScheduler_Worker-1:80078 ] - [ INFO ] ==Start====报警数据:系统过期处理-----------开始
2013-07-30 15:09:25 [ DefaultQuartzScheduler_Worker-1:105156 ] - [ ERROR ] Job alarm.alarmJob threw an unhandled Exception:
java.lang.NullPointerException
at com.kvt.lbs.alarm.entity.AlarmJob.getDeviceIdToAlarmTypekeys(AlarmJob.java:55)
at com.kvt.lbs.alarm.entity.AlarmJob.execute(AlarmJob.java:37)
at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:529)
5、去掉AlarmJob中的getDeviceIdToAlarmTypekeys方法后
INFO: Server startup in 13429 ms
2013-07-30 15:42:00 [ DefaultQuartzScheduler_Worker-1:77782 ] - [ INFO ] ==Start====报警数据:系统过期处理-----------开始
2013-07-30 15:42:00 [ DefaultQuartzScheduler_Worker-1:77782 ] - [ INFO ] ==Results==报警数据:系统过期处理成功 ,处理数据条数: 0
2013-07-30 15:42:00 [ DefaultQuartzScheduler_Worker-1:77782 ] - [ INFO ] ==End======报警数据:系统过期处理-----------完成
6、发现问题所在
getDeviceIdToAlarmTypekeys方法内部逻辑有误,但具体不知道是哪一行或那几行,但是可以肯定的是这里出了错,一定是这里。最后测试发现:alarmDao为null,对象注入失败。
7、解决方案
<bean id="helpDao" class="com.kvt.lbs.help.dao.HelpDao"></bean>
<bean id="helpService" class="com.kvt.lbs.help.service.HelpService"></bean>
<bean id="alarmDao" class="com.kvt.lbs.help.dao.AlarmDao"></bean>
<bean id="alarmService" class="com.kvt.lbs.help.service.AlarmService"></bean>
这样就可以注入对象了。
8、注意事项
定时任务不要写在static代码块中。因为服务器启动的时候,jvm启动时static块一起被初始化,此时Spring配置并未调用,对象注入会失败。