• spring的定时更新


    1. 技术概述

    服务器经常需要进行定时的数据更新,比如重置状态、重置计数、定时清空数据等,比如简时需要凌晨更新待办的状态,所以找到了@Scheduled来进行定时执行任务。

    2. 技术详述

    使用方式:

    如果pom.xml中没有导入web依赖,请导入(这个就不多说啦)。
    在入口程序(@SpringBootApplication注解的类)加上注解@EnableScheduling。

    @Controller
    @SpringBootApplication
    @EnableScheduling
    public class IndexControler {
        @RequestMapping("/index")
        @ResponseBody
        public String index() {
            return "helloword!";
        }
    }
    

    编写专门控制定时任务的Bean(@Component注解的),利用@Scheduled注解定时方法,下图(下面讲解注解参数的具体功能和使用)。

    @Component
    @EnableScheduling
    public class ScheduleUtil {
        @Autowired
        private UserTodoService userTodoService;
    
        @Autowired
        private TeamTodoService teamTodoService;
    
        @Scheduled(cron = "0 0 0 * * ?")
        public void updateStatus() {
            userTodoService.updateSchedule();
            teamTodoService.updateSchedule();
        }
    }
    

    具体参数使用讲解:

    1. cron

    时间表达式,可以通过简单的配置就能完成各种时间的配置,我们通过CRON表达式几乎可以完成任意的时间搭配,它包含了七个域:

    表达式参数 必填 允许填写的值 允许的通配符
    second 0-59 , - * /
    minute 0-59 , - * /
    hour 0-23 , - * /
    day 1-31 , - * ? / L W
    month 1-12 / JAN-DEC , - * /
    week 1-7 or SUN-SAT , - * ? / L #
    year 1970-2099 , - * /
    /**
    * 通配符说明
    * * 表示所有值,代表每次。
    * ? 表示不指定值,即跳过
    * - 表示区间,1-5代表1、2、3、4、5
    * , 表示指定多个值,1,2,3代表就是1、2、3触发
    * / 用于递增触发,start/jump,start开始jump间隔
    * L 表示最后,在日字段设置最后一天,比如年、月、周最后一天
    * W 表示离指定日期的最近那个工作日(周一至周五),例如3W三号最近的工作日,且不能为区间必须数字(例如前面的3)
    * # 序号(表示每月的第几个周几),例如在周字段上设置”6#3”表示在每月的第三个周六
    */
    /**
    * 样例
    * "0 0 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分每分钟一次触发
    * "0 0/5 14 * * ?"    每天从下午2点开始到2:55分结束每5分钟一次触发
    * "0 0/5 14,18 * * ?"    每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发
    * "0 0-5 14 * * ?"    每天14:00至14:05每分钟一次触发
    * "0 10,44 14 ? 3 WED"    三月的每周三的14:10和14:44触发
    * "0 15 10 ? * MON-FRI"    每个周一、周二、周三、周四、周五的10:15触发
    */
    @Scheduled(cron = "0 0 0 * * ?")
    void testPlaceholder() {
          System.out.println("Execute at " + System.currentTimeMillis());
    }
    

    2. zone

    时区,接收一个java.util.TimeZone#ID。cron表达式会基于该时区解析。默认是一个空字符串,即取服务器所在地的时区。比如我们一般使用的时区Asia/Shanghai。该字段我们一般留空。

    3. fixedDelay

    @Scheduled(fixedDelay = 1000) //上一次执行完毕之后5秒再执行
    

    4. fixedRate

    @Scheduled(fixedRate = 1000) //上一次项目启动之后1秒再执行
    

    5. initialDelay

    @Scheduled(initialDelay = 1000) //延迟1秒后开始执行
    

    代码实例

    /**
    * index 入口程序
    * 需要@SpringBootApplication、@EnableScheduling注解
    */
    @Controller
    @SpringBootApplication
    @EnableScheduling
    public class IndexControler {
        @RequestMapping("/index")
        @ResponseBody
        public String index() {
            return "helloword!";
        }
    }
    
    /**
    * 管理定时任务的Bean
    * 需要@Component注解
    */
    @Component
    @EnableScheduling
    public class ScheduleUtil {
        @Autowired
        private UserTodoService userTodoService;
    
        @Autowired
        private TeamTodoService teamTodoService;
        
        //注解定时任务,这里是每天0点0分0秒开始执行userTodo的state更新
        @Scheduled(cron = "0 0 0 * * ?")
        public void updateStatus() {
            userTodoService.updateSchedule();
            teamTodoService.updateSchedule();
        }
    
        //注解定时任务,上一次项目启动5s后执行
        @Scheduled(fixedRate = 50000)
        public void updateStatus() {
            System.out.println("fixedRate: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
    
        }
    
        //注解定时任务,上次执行结束后10s执行
        @Scheduled(fixedDelay = 100000)
        public void updateStatus() {
            System.out.println("fixedDelay: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    
        //注解定时任务,第一次延迟5s后开始执行,往后按照fixedRate参数规则执行
        @Scheduled(initialDelay = 50000,fixedRate = 6000)
        public void updateStatus() {
            System.out.println("fixedRate after initialDelay: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
        }
    }
    
    /**
    * userTodoDAO 用于处理userTodo的DAO实现类
    */
    @Repository(value = "userTodoDAO")
    @Transactional(rollbackFor = Exception.class)
    public class UserTodoDAOImpl extends BaseDAOImpl<UserTodo> implements UserTodoDAO {
    
        @Override
        public void updateSchedule() {
            Session session = getSession();
            String hqlUpdate = "update UserTodo as obj set todoStatusId = :status where todoStatusId != :oldStatus";
            int updatedEntities = session.createQuery(hqlUpdate)
                    .setParameter("status", 1)
                    .setParameter("oldStatus", 1)
                    .executeUpdate();
        }
    }
    
    /**
    * userTodoService 用于处理userTodo的service实现类
    */
    @Service("userTodoService")
    @Transactional(rollbackFor = Exception.class)
    public class UserTodoServiceImpl implements UserTodoService {
        @Autowired
        private UserTodoDAO userTodoDAO;
        @Override
        public void updateSchedule() {
            userTodoDAO.updateSchedule();
        }
    }
    

    3. 技术使用中遇到的问题和解决过程

    问题1:如果对于cron的通配符不够熟练记忆使用,导致cron表达式写不出来,或者出现编写的cron表达式无法准确的定位自己需要的定时时间

    解决方法:在线生成cron表达式

    问题2:没有效果,未能在设置的时间执行定时任务

    解决方法:

    /**
    * 1、可能原因没有@EnableScheduling注解,需要在启动入口或者任务配置类进行注解开启定时任务
    * 2、定时任务并未至于Bean中,Spring无法接管,导致定时任务没有执行
    */
    
    /**
    * 第一种方法配置
    */
    @Service
    public class ScheduledTaskService {
        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
     
        @Scheduled(fixedRate = 5000)
        public void reportCurrentTime(){
              ......
        }
    }
    
    @Configuration
    @ComponentScan("")
    @EnableScheduling //通过@EnableScheduling注解开启对计划任务的支持
    public class TaskScheduleConfig {
    }
    
    public class Main {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TaskScheduleConfig.class);
        }
    }
    
    /**
    * 第二种方法配置
    */
    @Controller
    @SpringBootApplication
    @EnableScheduling
    public class IndexControler {
    }
    
    @Component
    @EnableScheduling
    public class ScheduleUtil {
        ......//任务
    }
    

    4. 总结

    @Scheduled注解可以满足我们基本全部的定时任务,使用@Schedule不必熟练记住具体的cron编写,但是需要记住参数作用和参数名(cron、fixedRate、fixedDelay、initialDelay),利用在线生成corn表达式可以生成所需的corn表达式非常方便,掌握@Schedule对spring的使用有很大的帮助。

    5. 参考文献

    参考博客1参考博客2

  • 相关阅读:
    馒头国家标准公布:应是圆形或椭圆形(图)
    完全用C#写的SharpOS 0.0.1版发布
    c#操作c/c++的Dll文件
    研究发现GSM信号影响睡眠
    解决QQ与360的终极解决方案
    分享一个参数检查的类
    问题是问题,可是出路呢?
    读《码斗士修炼之路》有感
    我看博客园之争论
    关于ORM的一点思考
  • 原文地址:https://www.cnblogs.com/wjchen/p/13181488.html
Copyright © 2020-2023  润新知