在做项目时经常用遇到在指定的时间段执行某个操作,比如说项目中要求每天的00:00分计算当天的剩于库存数或要求02:00开始清理某一个表中的数据,如何实现呢?下面我们就分几步来完成这个任务。
1. 增加一个ServletContextListener监听器,在服务器启动时执行ServletContextListener。
具体代码如下:
a. 实现ServletContextListener接口,实现接口中的方法。
public class TimerTaskListener implements ServletContextListener {
private static final Logger logger = LogManager.getLogger(TimerTaskListener.class);
@Override
public void contextDestroyed(ServletContextEvent arg0) {
logger.info("TimerTaskListener Destoryed!");
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
// code written in here ...
}
}
b. 在web.xml中配置listener,这样在服务器启动时就可以调用TimerTaskListener监听类了。
<listener>
<listener-class>com.jelly.commons.listener.TimerTaskListener</listener-class>
</listener>
2. 设计系统任务表,用于存放要执行的任务。
表结构如下:
TASK_ID | FIRST_TIME | PERIOD | TASK_CLASS | SERVICE_NAME |
10001 | 2011-11-04 00:00:00 | 200000 | com.jelly.service.task.TimerTaskServices1 | 任务1 |
10002 | 2011-11-03 02:00:00 | 500000 | com.jelly.service.task.TimerTaskServices2 | 任务2 |
TASK_ID(任务ID)
FIRST_TIME(首次执行时间)
PERIOD(执行频率,单位毫秒,1天=24*60*60*1000)
TASK_CLASS(任务的所在的类)
SERVICE_NAME(任务名称)
3. 新建一个TimerTask抽象类,该类主要是为了让用户继承使用(TASK_CLASS所指的父类),代码如下:
public abstract class TimerTask {
private static final Logger logger = LogManager.getLogger(TimerTaskListener.class);
public abstract void execute(SystemTask task);
public void start(final SystemTask task){
// code written in here...
}
}
4. 编写TimerTaskListener类中需要书写的代码。
public void contextInitialized(ServletContextEvent arg0) {
new Thread(new Runnable() {
@Override
public void run() {
DBHelper dbHelper = null;
List<SystemTask> tasks = FastList.newInstance();
try {
Thread.sleep(30000);
// query tasks
dbHelper = DBHelper.getInstance();
StringBuffer sql = new StringBuffer();
sql.append("SELECT * FROM SYSTEM_TASK");
tasks = dbHelper.select(sql.toString(), new BeanListHandler<SystemTask>(SystemTask.class));
dbHelper.close();
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
} catch (SQLException e) {
logger.error(e.getMessage(), e);
} finally {
if(dbHelper != null){
dbHelper.freeConnection();
}
}
// execute task
for (SystemTask task : tasks) {
String className = task.getTaskClass();
try {
Class<?> clzz = Class.forName(className);
TimerTask service = (TimerTask)clzz.newInstance();
service.start(task);
} catch (ClassNotFoundException e) {
logger.error(e.getMessage(), e);
} catch (InstantiationException e) {
logger.error(e.getMessage(), e);
} catch (IllegalAccessException e) {
logger.error(e.getMessage(), e);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
}).start();
}
5. TimerTask类中的主要代码。
public void start(final SystemTask task){
final String taskId = task.getId();
final long period = task.getPeriod();
final Date firstTime = task.getFirstTime();
Calendar c = Calendar.getInstance();
c.setTime(firstTime);
long dayMillisecond = c.getTimeInMillis();
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
int millisecond = c.get(Calendar.MILLISECOND);
Calendar runtime = Calendar.getInstance();
runtime.setTime(new Date());
runtime.set(Calendar.HOUR_OF_DAY, hour);
runtime.set(Calendar.MINUTE, minute);
runtime.set(Calendar.SECOND, second);
runtime.set(Calendar.MILLISECOND, millisecond);
long nowMillisecond = runtime.getTimeInMillis();
if(nowMillisecond >= dayMillisecond){
if(nowMillisecond < new Date().getTime())
runtime.add(Calendar.DAY_OF_MONTH, 1);
}else{
runtime.setTime(firstTime);
}
final String assignTime = UtilDateTime.toDateString(firstTime, UtilDateTime.FORMAT_DATE_TIME);
final String executeTime = UtilDateTime.toDateString(runtime.getTime(), UtilDateTime.FORMAT_DATE_TIME);
logger.info("task id (" + taskId + ") assign time : " + assignTime);
logger.info("task id (" + taskId + ") execute time: " + executeTime);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new java.util.TimerTask() {
@Override
public void run() {
try {
execute(task);
} catch (Throwable e) {
logger.error(e.getMessage(),e);
}
}
}, runtime.getTime(), period);
}
(未完)