zoukankan      html  css  js  c++  java
  • 在Java Web项目中添加定时任务

    在Java Web程序中加入定时任务,这里介绍两种方式:1.使用监听器注入;2.使用Spring注解@Scheduled注入。
    推荐使用第二种形式。


    一、使用监听器注入

    ①:创建监听器类:
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    public class TimerDataTaskListener implements ServletContextListener {
    	
    	@Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            new TimerManager();
        }
    	
    	@Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
    
        }
    }
    
    ②:创建定时任务类:
    
    import java.util.Calendar;
    import java.util.Date;
    import java.util.Timer;
    
    public class TimerManager {
        //时间间隔:24h
        private static final long PERIOD_DAY = 24 * 60 * 60 * 1000;
        public TimerManager() {
            Calendar calendar = Calendar.getInstance();
    
            //定制每日12:30:30执行
            calendar.set(Calendar.HOUR_OF_DAY, 12);
            calendar.set(Calendar.MINUTE, 30);
            calendar.set(Calendar.SECOND, 30);
    
            Date date = calendar.getTime();     //第一次执行定时任务的时间
            //如果当前时间已经过去所定时的时间点,则在第二天时间点开始执行
            if (date.before(new Date())) {
                date = this.addDay(date, 1);
            }
            Timer timer = new Timer();
            TimerTaskService task = new TimerTaskService();
            //安排指定的任务在指定的时间开始进行重复的固定延迟执行。
            timer.schedule(task, date, PERIOD_DAY);
        }
    
        // 增加或减少天数
        private Date addDay(Date date, int num) {
            Calendar startDT = Calendar.getInstance();
            startDT.setTime(date);
            startDT.add(Calendar.DAY_OF_MONTH, num);
            return startDT.getTime();
        }
    }
    
    ③:创建TimerTask类:
    import java.util.TimerTask;
    
    public class TimerTaskService extends TimerTask {
    
        @Override
        public void run() {
            try {
            	//要执行的任务逻辑写在这里
                System.out.println("插入密码成功!");
            } catch (Exception e) {
                System.out.println("插入密码失败!");
            }
        }
    }
    
    ④:在web.xml注册监听器
    <!-- TimerDataTaskListener 监听器 -->
        <listener>
          <listener-class>com.jsiqi.resume.service.TimerDataTaskListener</listener-class>
        </listener> 
    

    二、使用spring注解注入

    我项目的框架是Spring + SpringMVC + Mybatis

    代码示例:

    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component
    public class TimerTask {
    	
    	@Scheduled(cron="*/30 * * * * *")  	 // 间隔30秒执行
    	public void test(){
            try {
            	//要执行的任务逻辑写在这里
                System.out.println("插入密码成功!");
            } catch (Exception e) {
                System.out.println("插入密码失败!");
            }
    	}
    }
    
    

    关于定时时间的设置方式如下:

    CronTrigger配置完整格式为: [秒] [分] [小时] [日] [月] [周] [年]
    示例:
    0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
    0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
    0 0 12 ? * WED 表示每个星期三中午12点 
    "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触发 
    
    序号 说明 是否必填 允许填写的值 允许的通配符
    1 0-59 , - * /
    2 0-59 , - * /
    3 0-23 , - * /
    4 1-31 , - * ? / L W
    5 1-12或JAN-DEC , - * /
    6 1-7或SUN-SAT , - * ? / L W
    7 empty 或1970-2099 , - * /

    通配符说明:

    * 表示所有值. 例如:在分的字段上设置 "*",表示每一分钟都会触发

    ? 表示不指定值。使用的场景为不需要关心当前设置这个字段的值。

    例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为"?" 具体设置为 0 0 0 10 * ?

    - 表示区间。例如 在小时上设置 "10-12",表示 10,11,12点都会触发。

    , 表示指定多个值,例如在周字段上设置 "MON,WED,FRI" 表示周一,周三和周五触发

    / 用于递增触发。如在秒上面设置"5/15" 表示从5秒开始,每增15秒触发(5,20,35,50)。 在月字段上设置'1/3'所示每月1号开始,每隔三天触发一次。

    L 表示最后的意思。在日字段设置上,表示当月的最后一天(依据当前月份,如果是二月还会依据是否是润年[leap]), 在周字段上表示星期六,相当于"7"或"SAT"。如果在"L"前加上数字,则表示该数据的最后一个。例如在周字段上设置"6L"这样的格式,则表示“本月最后一个星期五"

    W 表示离指定日期的最近那个工作日(周一至周五). 例如在日字段上设置"15W",表示离每月15号最近的那个工作日触发。如果15号正好是周六,则找最近的周五(14号)触发, 如果15号是周未,则找最近的下周一(16号)触发.如果15号正好在工作日(周一至周五),则就在该天触发。如果指定格式为 "1W",它则表示每月1号往后最近的工作日触发。如果1号正是周六,则将在3号下周一触发。(注,"W"前只能设置具体的数字,不允许区间"-").

    # 序号(表示每月的第几个周几),例如在周字段上设置"6#3"表示在每月的第三个周六.注意如果指定"#5",正好第五周没有周六,则不会触发该配置(用在母亲节和父亲节再合适不过了) ;

    小提示:
    'L'和 'W'可以组合使用。如果在日字段上设置"LW",则表示在本月的最后一个工作日触发;
    周字段的设置,若使用英文字母是不区分大小写的,即MON 与mon相同;

    参考:

    https://www.cnblogs.com/liaojie970/p/5913272.html
    http://prisonbreak.iteye.com/blog/2247216


    个人使用总结:
    我在自己的小项目里使用第一种注册监听器方式时获取到dao层的bean始终为null;第二种注解方式可行。
    但对于第一种监听器类bean注入失败的原因未找到答案,有明白的大牛指点一二。

  • 相关阅读:
    973. K Closest Points to Origin
    919. Complete Binary Tree Inserter
    993. Cousins in Binary Tree
    20. Valid Parentheses
    141. Linked List Cycle
    912. Sort an Array
    各种排序方法总结
    509. Fibonacci Number
    374. Guess Number Higher or Lower
    238. Product of Array Except Self java solutions
  • 原文地址:https://www.cnblogs.com/dcncy/p/8205065.html
Copyright © 2011-2022 走看看