首先配置spring-context.xml文件
在xmlns 下加如下代碼
xmlns:task="http://www.springframework.org/schema/task"
在xsi:schemaLocation里添加如下代碼
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.xsd
還有任務掃描
<task:annotation-driven />
以上配置完成,新建java類寫定時任務
package com.test.job; import java.util.Date; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import lombok.extern.log4j.Log4j2; /** * 定時任務測試 * @author ljl * */ @Log4j2 @Component public class TestJob { @Scheduled(cron = "0 */5 * * * ?") public void test1() { log.info("每5分鍾執行一次"+ new Date()); } @Scheduled(cron = "0 0 12 * * ?") private void test2() { log.info("每天中午12點執行"+ new Date()); } }
以上定時任務完成。
思考:如果多台服務器部署同一個項目,就會出現一個定時任務多次執行的問題,如何解決?
網上找了以下四種方法,可以作為參考。
1、設置執行定時任務的機器名,在代碼中判斷,只讓某一台機器執行。
2、如果有可能,將定時任務獨立出來,成為一個單獨的項目工程,單一部署。
3、將任務的定時觸發模塊、任務的執行模塊分離。任務的定時觸發模塊每台機器都允許觸發任務,但是任務的執行模塊,只要收到一個執行任務,那么下一個執行任務就被忽略掉。任務開始執行設置running = true,任務執行完畢設置running = false,當running
為ture時候,下一個任務不允許執行。需要注意的是,一定要在finally中加上running = false,要不然任務異常的話,下一次任務永遠不會再執行了。
4、在數據庫建一個表:timerT,表里面有三個字段:status(表當前定時器是否處於可運行狀態)、timestamp(時間戳)、serverIP(正在運行定時器的服務器IP)。當兩台服務器,都運行起來后,服務器A開始執行定時器,這時,A會去讀取表timerT的status字段,當為0時,則執行定時器的業務邏輯,此時A定時器,需要把status改為1,以便讓另一台服務器的定時器B不去執行業務邏輯並把當前服務器的IP記錄到表中,同時修改啟動一個新的線程,在XXX長的時間間隔內不斷去修改timestamp的值,當A執行完業務邏輯時,就把status的值改為0,這樣B定時器就可以執行。這樣做可以解決一個問題,就是:當其中一個定時器A掛掉后,我們另一個定時器B,可以比對timestap的值與當前時間是否超過XXX時長,如果超過,則證明定時器A已經掛掉,這時B就會把status的值改成1,把serverIP改成B定時器所在的服務器IP,並執行業務邏輯。