您好,登錄后才能下訂單哦!
SpringBoot概述
SpringBoot是由Pivotal團隊在2013年開始研發、2014年4月發布第一個版本的全新開源的輕量級框架。它基于Spring4.0設計,不僅繼承了Spring框架原有的優秀特性,而且還通過簡化配置來進一步簡化了Spring應用的整個搭建和開發過程。另外SpringBoot通過集成大量的框架使得依賴包的版本沖突,以及引用的不穩定性等問題得到了很好的解決。
SpringBoot特征
(1)可以創建獨立的Spring應用程序,并且基于其Maven或Gradle插件,可以創建可執行的JARs和WARs;
(2)內嵌Tomcat或Jetty等Servlet容器;
(3)提供自動配置的“starter”項目對象模型(POMS)以簡化Maven配置;
(4)盡可能自動配置Spring容器;
(5)提供準備好的特性,如指標、健康檢查和外部化配置;
(6)絕對沒有代碼生成,不需要XML配置。
在我們平時開發的項目中,定時任務基本屬于必不可少的功能,那大家都是怎么做的呢?但我知道的大多都是靜態定時任務實現。
基于注解來創建定時任務非常簡單,只需幾行代碼便可完成。實現如下:
@Configuration
@EnableScheduling
public class SimpleScheduleTask {
//10秒鐘執行一次
@Scheduled(cron = "0/10 * * * * ?")
private void tasks() {
System.out.println("【定時任務】 每10秒執行一次!");
}
}
Cron表達式參數分別表示(從左到右):
秒(0~59) 如0/5表示每5秒
分(0~59)
時(0~23)
日(0~31) 月的某一天
月(0~11)
周幾( 可填1-7 或 SUN/MON/TUE/WED/THU/FRI/SAT)
就上面幾行代碼,就能搞定一個定時任務。顯然,使用Scheduled 確實特別的方便,但有很大的缺點和局限,就是當我們調整了執行計劃的時間時,需要重啟服務才能生效,這就有些不方便。為了達到實時生效的效果,可以通過數據庫來動態實現定時任務。
基于數據庫的動態定時任務實現
將定時任務配置在數據庫,啟動項目的時候,用mybatis讀取數據庫,實例化對象,并設定定時任務。如果需要新增,減少,修改定時任務,僅需要修改數據庫資料,并重啟項目即可,無需改代碼。
@Lazy(value = false)
@Component
public class ScheduleTask implements SchedulingConfigurer {
protected static Logger logger = LoggerFactory.getLogger(ScheduleTask.class);
private SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Autowired
private ScheduleTaskMapper scheduleTaskMapper;
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
List tasks = getAllScheduleTasks();
logger.info("【定時任務啟動】 啟動任務數:"+tasks.size()+"; time="+sdf.format(new Date()));
//校驗數據
checkDataList(tasks);
//通過校驗的數據執行定時任務
int count = 0;
if(tasks.size()>0) {
for (int i = 0; i < tasks.size(); i++) {
try {
taskRegistrar.addTriggerTask(getRunnable(tasks.get(i)), getTrigger(tasks.get(i)));
count++;
} catch (Exception e) {
logger.error("task start error:" + tasks.get(i).getClassName() + ";" + tasks.get(i).getMethodName() + ";" + e.getMessage());
}
}
}
logger.info("started task number="+count+"; time="+sdf.format(new Date()));
};
/**
* 獲取要執行的所有任務
* @return
*/
private List getAllScheduleTasks() {
ScheduleTaskExample example=new ScheduleTaskExample();
example.createCriteria().andIsDeleteEqualTo((byte) 0);
return scheduleTaskMapper.selectByExample(example);
}
/**
* 獲取Runnable
*
* @param task
* @return
*/
private Runnable getRunnable(ScheduleTask task){
return new Runnable() {
@Override
public void run() {
try {
Object obj = SpringUtil.getBean(task.getClassName());
Method method = obj.getClass().getMethod(task.getMethodName(),null);
method.invoke(obj);
} catch (InvocationTargetException e) {
logger.error("refect exception:"+task.getClassName()+";"+task.getMethodName()+";"+ e.getMessage());
} catch (Exception e) {
logger.error(e.getMessage());
}
}
};
}
/**
* 獲取Trigger
*
* @param task
* @return
*/
private Trigger getTrigger(ScheduleTask task){
return new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
//將Cron 0/1 * * * * ?
CronTrigger trigger = new CronTrigger(task.getCron());
Date nextExec = trigger.nextExecutionTime(triggerContext);
return nextExec;
}
};
}
/**
* 校驗數據
*
* @param list
* @return
*/
private List checkDataList(List list) {
String msg="";
for(int i=0;i
if(!checkOneData(list.get(i)).equalsIgnoreCase("ok")){
msg+=list.get(i).getTaskName()+";";
list.remove(list.get(i));
i--;
};
}
if(!StringUtils.IsEmpty(msg)){
msg="未啟動的任務:"+msg;
logger.error(msg);
}
return list;
}
/**
* 按每一條校驗數據
*
* @param task
* @return
*/
private String checkOneData(ScheduleTask task){
String result="ok";
Class cal= null;
try {
cal = Class.forName(task.getClassName());
Object obj =SpringUtil.getBean(cal);
Method method = obj.getClass().getMethod(task.getMethodName(),null);
String cron=task.getCron();
if(StringUtils.isBlank(cron)){
result="no found the cron:"+task.getTaskName();
logger.error(result);
}
} catch (ClassNotFoundException e) {
result="not found the class:"+task.getClassName()+ e.getMessage();
logger.error(result);
} catch (NoSuchMethodException e) {
result="not found the method:"+task.getClassName()+";"+task.getMethodName()+";"+ e.getMessage();
logger.error(result);
} catch (Exception e) {
logger.error(e.getMessage());
}
return result;
}
}
數據庫配置
運行的結果
這樣我們可以通過直接修改數據庫,執行周期就會改變,并且不需要我們重啟應用,十分方便。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。