目的:实现动态的定时任务脚本框架(增删改定时脚本无需重启服务)
基础:J2SE、Groovy、cron表达式
首先贴出解析cron表达式的类,本人对自己写的这个类并不满意,如果大神有更好的实现还请告诉我一下。
package com.hdb.schedule.common /** * @author MwXx * @version 1.0 * @date 2014-04-21 */ class CronExpression { private Set<Integer> minuteSet private Set<Integer> hourSet private Set<Integer> dateSet private Set<Integer> monthSet private Set<Integer> weekSet private Set<Integer> yearSet String error private crontab public CronExpression(crontab){ this.crontab = crontab this.buildExpression(this.crontab) } private void buildExpression(crontab) throws Exception{ minuteSet = new HashSet<Integer>() hourSet = new HashSet<Integer>() dateSet = new HashSet<Integer>() monthSet = new HashSet<Integer>() weekSet = new HashSet<Integer>() yearSet = new HashSet<Integer>() try{ int size = crontab.size() 6.times {index-> def val if(size > index){ val = crontab[index].toString().trim() }else{ val = '*' } val.split(',').each { addToSet(index, it) } } }catch(Exception e){ } } private void addValue(int index,int val){ switch(index){ case 0: minuteSet.add(val) break case 1: hourSet.add(val) break case 2: dateSet.add(val) break case 3: monthSet.add(val) break case 4: weekSet.add(val) break case 5: yearSet.add(val) break } } private void addAllValue(int index,int perSize){ switch(index){ case 0: for(int i=0;i<60;i+=perSize){ minuteSet.add(i) } break case 1: for(int i=0;i<24;i+=perSize){ hourSet.add(i) } break case 2: for(int i=1;i<=31;i+=perSize){ dateSet.add(i) } break case 3: for(int i=1;i<=12;i+=perSize){ monthSet.add(i) } break case 4: for(int i=0;i<7;i+=perSize){ weekSet.add(i) } break case 5: for(int i=2014;i<=2999;i+=perSize){ yearSet.add(i) } break } } private void addToSet(int index,String val) throws Exception{ if(val == '*'){ this.addAllValue(index, 1) return } if(val.matches(/\d+/)){ this.addValue(index, val.toInteger()) return } String[] per = val.split('/') int perSize = 1 if(per.size() == 2){ if(per[1].matches(/\d+/)){ perSize = per[1].toInteger() }else if(per[1]!='*'){ error = "${crontab}[${index}]" throw new Exception(error) } } String[] between = per[0].split('-') if(between.size() == 1){ if(between[0] == '*'){ this.addAllValue(index, perSize) }else if(between[0].matches(/\d+/)){ this.addValue(index, between[0].toInteger()) }else{ error = "${crontab}[${index}]" throw new Exception(error) } return } if(between.size() != 2 || !between[0].matches(/\d+/) || !between[1].matches(/\d+/)){ error = "${crontab}[${index}]" throw new Exception(error) } int start = between[0].toInteger() int end = between[1].toInteger() int max = 0 int min = 0 switch(index){ case 0: max = 59 break case 1: max = 23 break case 2: max = 31 min = 1 break case 3: max = 12 min = 1 break case 4: max = 6 break case 5: max = 2999 min = 2014 break } if(end >= start){ while(start <= end){ addValue(index, start) start += perSize } }else{ while(min <= end){ addValue(index, min) min += perSize } while(start <= max){ addValue(index, start) start += perSize } } } boolean valide(Calendar calendar){ int minute = calendar.get(Calendar.MINUTE) if(!minuteSet.contains(minute)){ return false } int hour = calendar.get(Calendar.HOUR_OF_DAY) if(!hourSet.contains(hour)){ return false } int date = calendar.get(Calendar.DATE) if(!dateSet.contains(date)){ return false } //获取到的月份需要加1,如1月获取到的是0 int month = calendar.get(Calendar.MONTH) + 1 if(!monthSet.contains(month)){ return false } //获取到的周需要-1 如周五获取到的是6 int week = calendar.get(Calendar.DAY_OF_WEEK) - 1 if(!weekSet.contains(week)){ return false } int year = calendar.get(Calendar.YEAR) if(!yearSet.contains(year)){ return false } true } }
下面这个类的功能是每间隔1分钟,扫描编译指定文件夹下的Groovy脚本,解析脚本的crontab属性,判断是否执行该脚本。
package com.hdb.schedule import org.apache.log4j.Logger import com.hdb.schedule.common.CronExpression import com.hdb.util.FileUtils /** * @author MwXx * @version 1.0 * @date 2014-04-18 18:46:23 cron 表达式含义 第1列分钟1~59 第2列小时0~23 第3列日1~31 第4列月1~12 第5列星期0~6(0表示星期天) */ class GroovyTask extends TimerTask{ private static final String[] rootDirs = ['crontab\\monitor\\', 'crontab\\report\\', 'crontab\\task\\'] private static Logger log = Logger.getLogger(GroovyTask.class) public void run() { try { Calendar calendar = Calendar.getInstance() GroovyScriptEngine engine = new GroovyScriptEngine(rootDirs) Binding binding = new Binding(); binding.setVariable("language", "Groovy"); rootDirs.each {rootDir-> try{ File rootPath = new File(FileUtils.getProjectDir()) rootPath = new File(rootPath,rootDir) rootPath.eachFile {schFile -> if(!schFile.isDirectory() && schFile.getName().endsWith('.groovy')){ def schClass = engine.loadScriptByName(schFile.getName()) def crontab = schClass.getMetaClass().getProperties().find { it.name == 'crontab' } if(crontab){ CronExpression cronExp = new CronExpression(schClass.getAt('crontab')) if(cronExp.error){ log.error "Task: ${schClass.toString()}'s crontab \"${cronExp.error}\" is not compliance." }else if(cronExp.valide(calendar)){ def info = '\n' + (' -'*50) + "\nTask:${schClass.toString()} will be invoke." log.info(info) Thread.start { schClass.getMetaClass().invokeMethod(schClass.newInstance(), "execute", null) } } } } } } catch (Exception e) { e.printStackTrace(); } } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args){ Timer timer = new Timer() //每分钟执行一次,动态加载 Groovy 脚本,得到crontab属性,从而决定是否该执行 execute 方法 timer.schedule(new GroovyTask(), 0, 60000) } }
忘了在后面附上定时任务的例子……现在补上
/** * @author MwXx * @version 1.0 * @date 2014-03-28 */ class TaskDemo{ /** 每个小时的第10分钟执行 */ static crontab = [10] void execute(){ println '我执行啦...' } }
定时任务脚本的格式要求:
1.文件名以.groovy结尾
2.类中有static crontab = [] 变量的定义
3.类中有void execute(){}方法的实现
crontab属性的用法在GroovyTask类的注释中说明了。再附上几个例子。
/** 每周五0点10分执行 */ static crontab = [10, 0, '*', '*', 5] /** 每月1号10点执行 */ static crontab = [0, 10, 1] /** 每个小时的第10分钟执行 */ static crontab = [10] /** 每天9点执行 */ static crontab = [0, 9] /** 8点-18点之间每10分钟执行一次 */ static crontab = ['*/10','8-18'] /** 每天8点、13点、17点20分执行 */ static crontab = [20, '8,13,17'] /** 每周一到周五13点、18点执行 */ static crontab = [0,'13,18','*','*','1-5']
不会Groovy也不用担心,有JAVA基础的话,学习Groovy语言特别容易。
而且只需要在项目中加上Groovy的jar包就能使用Groovy语言的各种特性了。
相关推荐
藏区特产销售平台--论文.zip
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
该单片机项目可作为课程设计和期末大作业或者毕设,项目完整,有原理图和代码,需要的自行下载即可!
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载