spring boot 应用-定时任务

之前写过Oracle定时任务的脚本,当时对于Windows server 服务器是将脚本添加到任务计划中,但是 我就在实际中遇到过无法将脚本添加到任务计划中(试过了各种方法就是无法添加),这是我想到了是不是可以写个定时任务来调用脚本呢? 确实可以。源码地址 GitHub

2019年6月2日21:51更新(动态调整定时任务时间,之前的定时任务是写死在注解上的,新修改为 调用h2表中的字段)

spring boot 主程序中添加 @EnableScheduling 注解

使用 @Component 定义组件

在组件中使用 @Scheduled 定义定时任务

JavaRunBatApplication.java

package cn.geoary;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class JavaRunBatApplication {
    public static void main(String[] args) {
        SpringApplication.run(JavaRunBatApplication.class, args);
    }
}

JavaRunBat.java

package cn.geoary.util;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @program: java-run-bat
 * @description: Java定时执行bat文件
 * @author: geoary
 * @create: 2019-05-06 14:41
 **/
@Component
public class JavaRunBat {
    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
    /**
     * @description 创建定时任务
     * @param
     * @return
     * @author geoary
     * @date 2019/5/6 
     */
    // 每天1点执行
    @Scheduled(cron = "0 0 1 * * ?")
    // 3分钟执行一次
    //@Scheduled(cron = "0 0/3 * * * ?")
    public void timingBat(){
        runBat();
    }
    /**
     * @description 执行bat文件 
     * @param  
     * @return  
     * @author geoary
     * @date 2019/5/6 
     */
    public static void runBat(){
        String batPath = "E:/backup/data/autobackup.bat";
        execBat(batPath);
        //execBat("1", batPath);
    }
    /**
     * @description 执行bat 
     * @param
     * @return  
     * @author geoary
     * @date 2019/5/6 
     */
    public static void execBat(String ways, String batPath){
        String cmdPre;
        switch (ways){
            case "1":
                // 是执行完dir命令后关闭命令窗口
                cmdPre =  "cmd /c ";
                break;
            case "2":
                // 是执行完dir命令后不关闭命令窗口
                cmdPre = "cmd /k ";
                break;
            case "3":
                // 会打开一个新窗口后执行dir指令,原窗口会关闭
                cmdPre = "cmd /c start ";
                break;
            default:
                // 会打开一个新窗口后执行dir指令,原窗口不会关闭
                cmdPre = "cmd /k start ";
        }
        String cmd = cmdPre + batPath;
        try{
            Process ps = Runtime.getRuntime().exec(cmd);
            InputStream in = ps.getInputStream();
            int c;
            while ((c = in.read()) !=  -1){

            }
            in.close();
            try {
                ps.waitFor();
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println("执行完成"+dateFormat.format(new Date()));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void execBat(String batPath){
        try{
            Process ps = Runtime.getRuntime().exec("cmd /c start "+ batPath);
            InputStream in = ps.getInputStream();
            int c;
            while ((c = in.read()) !=  -1){
            }
            in.close();
            try {
                ps.waitFor();
            }catch (Exception e){
                e.printStackTrace();
            }
            System.out.println("执行完成"+dateFormat.format(new Date()));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

定时任务cron表达式:

表达式一般时这样的:

每天凌晨1点执行 @Scheduled(cron = "0 0 1 * * ?")

每隔3分钟执行 @Scheduled(cron = "0 0/3 * * * ?")

那么这到底时怎么写出来的呢?

官方api

其实cron表达式后面一般有6个字符用空格分隔开,每一个域标识一个含义:
second minuters hours dayOfMonth month dayOfWeek

序号 可出现的字符
1 second , - * / 0到59的整数
2 minuters , - * / 0到59的整数
3 hours , - * / 0到23的整数
4 dayOfMonth , - * / ? L W C 0到31的整数
5 month , - * / 1到12的整数
6 dayOfWeek , - * / ? L #1到7的整数(或者SUN到SAT,1表示星期天,2表示星期一)
序号 字符 含义
1 , 表示枚举值例如:在minuters域中使用2,10 表示在2分钟和10分中各触发一次
2 - 表示范围 例如:在minuters 域中使用2-10 表示从2分钟到10分钟每分钟出发一次
3 * 表示任意值 例如:在minuters域中使用* 则表示每分钟都会触发
4 / 表示 开始/步长 例如:在minuters域中使用2/10 表示从2分钟开始 每个十分钟触发一次(2、12、22、32、42、52), 若开始值设置为*等效于0
5 ? 表示 不设置 通常出现在两个相互影响的域中(dayOfMonth、dayOfWeek),当日期设置了那么星期只能是?
6 L 表示 最后值 例如:在日期中表示本月的最后一天 30号、31号、29号、28号;在星期中6L表示 本月最后一个星期五
7 W 表示有效工作日(及周一至周五) 只能出现在日期域中,系统将在离指定日期的最近的有效工作日触发事件。例如: 5W,如果是星期六,则会在最近的工作日即星期五触发即4号,如果5号是星期日,则会在下个星期一触发即6号。注意,不会跨月
8 # 表示第几个星期几 只能用在星期中。例如: 4#2 表示某个月第2个星期三

示例:

cron表达式 含义
0 0 10,14,16 * * ? 每天上午10点,下午2点,4点
0 0/30 9-17 * * ? 上午九点到下午5点间每30分钟
0 0 12 ? * WED 表示每个星期三中午12点
0 0 12 * * ? 每天中午12点
0 15 10 ? * * 每天上午10:15
0 15 10 * * ? 2005 2005年的每天上午10:15(一般不用带年的)
0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟
0 0/5 14 * * ? 在每天下午2点到下午2:59期间的每5分钟
0 0/5 14,18 * * ? 在每天下午2点到2:59期间和下午6点到6:59期间的每5分钟
0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟

posted @ 2022-03-06 17:44  Geoary  阅读(46)  评论(0)    收藏  举报