版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chenbetter1996/article/details/82831536
监听器需求原因:
有时候希望不需要用户发起请求而后台定时处理某种事务。如签到功能模块,每天凌晨00:00自动将用户数据库的所有签到状态自动更新为未签到,这是不需要用户发请求的,是后台自动定时触发处理的。
实现方法:
定义一个 extends HttpServlet implements ServletContextListener 的监听类
package io.bbc13.controller;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import io.bbc13.service.DateTimerTask;
import io.bbc13.service.WeekTimerTask;
/**
* @Lin
* @每天每周定时任务监听器
* @每天凌晨零点更新签到状态为非
* @每周日凌晨零点更新矿工数-10
*/
public class TimeContextListener extends HttpServlet implements ServletContextListener {
private ServletContext context = null;
/* 监听开始销毁 */
public void contextDestroyed(ServletContextEvent sce) {
this.context.log("定时器销毁");
}
/* 监听开始执行 */
public void contextInitialized(ServletContextEvent sce) {
this.context= sce.getServletContext();
this.context.log("定时器开始");
// 当监听开始执行时,设置一个TIME
Timer timer = new Timer(true); // 是否为守护进程danemon
// 获取当前时间到00:00:00(24:00:00)的时间差
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String now = sdf.format(new Date());
long gap = 0;
try {
Date toM = sdf.parse("24:00:00");
Date fromM = sdf.parse(now);
long from = fromM.getTime();
long to = toM.getTime();
gap = to - from;
System.out.println("距离24:00:00时间差 " + gap + "ms");
} catch(Exception e) {
e.printStackTrace();
}
System.out.println("-------DateTimerTask开始进行执行--------------");
// 定时任务
DateTimerTask dtt = new DateTimerTask(this.context);
WeekTimerTask wtt = new WeekTimerTask(this.context);
// 开始执行dtt对象的,第二参数为开始时间,第三个参数为间隔时间,单位毫秒
timer.schedule(dtt, gap, 24 * 60 * 60 * 1000); // 定时每天的更新签到
timer.schedule(wtt, gap, 7 * 24 * 60 * 60 * 1000); // 定时每周日的减矿工
System.out.println("-------DateTimerTask已经在执行--------------");
}
}
ServletContextListener所属的线程会在容器启动时就开始执行,一直不中断。
利用其特性和结合TimerTask(一个对象创建一条线程)定时任务类, 可以实现。
package io.bbc13.service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimerTask;
import javax.servlet.ServletContext;
import org.apache.ibatis.session.SqlSession;
import io.bbc13.util.MybatisUtil;
public class DateTimerTask extends TimerTask {
private ServletContext context = null;
public DateTimerTask(ServletContext context) {
this.context = context;
}
/* 执行对象的任务函数 */
@Override
public void run() {
String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
System.out.println("service.DateTimeTask" + now + " 被执行了 DateTimerTask");
// 开始每天签到更新操作
}
}
任务类继承TimerTask抽象类,重写run方法即可。
监听器注册:
和Servlet等注册一样,在web.xml中(按首字母排序)
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>bobo</display-name>
<!-- 注册过滤器 -->
<!-- 注册监听器 -->
<listener>
<listener-class>io.bbc13.controller.TimeContextListener</listener-class>
</listener>
<!-- 注册servlet -->
</web-app>