1. 程式人生 > 其它 >spring boot 應用-定時任務

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分鐘