`
mwxx
  • 浏览: 12197 次
  • 性别: Icon_minigender_1
  • 来自: 山东
社区版块
存档分类
最新评论

基于Groovy的动态定时任务

阅读更多

目的:实现动态的定时任务脚本框架(增删改定时脚本无需重启服务)

基础: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语言的各种特性了。

分享到:
评论

相关推荐

    hugo110-java_run_groovy-master_java_

    综上所述,这个项目可能是为了帮助开发者理解和实践如何在Java项目中集成和运行Groovy,以便更好地利用Groovy的动态性和简洁性,同时为实现定时任务和动态代码执行场景做准备。通过学习和实践这个项目,你可以掌握...

    Hubitat高程应用程序和驱动程序_Groovy_下载

    这些文件的命名通常会反映它们的功能,比如“LightController.groovy”可能是一个管理灯光设备的驱动,而“SmartSchedule.groovy”可能是实现智能定时任务的应用程序。 为了正确使用这些资源,你需要有一定的Groovy...

    SSM定时访问某个接口

    上述配置启用了基于注解的定时任务,并定义了一个名为`scheduler`的调度器,其线程池大小为10。 在Spring MVC中,你可以通过在Controller方法上使用`@Scheduled`注解来创建定时任务,该任务会定期调用指定的接口。...

    grails和groovy的电子书-4

    - Grails框架包含了SiteMesh(用于布局)、Quartz(用于定时任务)、AJAX框架等组件。 Grails的“约定优于配置”的理念意味着开发人员可以专注于业务逻辑,而不需要花费太多时间来配置或连线。 #### Grails的安装...

    基于 SpringBoot 的调度框架

    3. **Gradle**:Gradle是一种基于Groovy的构建工具,它的灵活性和强大的插件系统使其成为大型项目的选择。在`build.gradle`文件中,你可以声明项目依赖,包括Spring Boot和Quartz或Spring Task,以及设置构建任务。 ...

    Java任务调度 jconch.7z

    Spring Task支持基于cron表达式的定时任务,这使得任务调度更加灵活。 在Java任务调度中,常常会用到一些库来辅助实现,如文件名所示的groovy-1.5.4.jar、commons-collections-3.2.jar和commons-lang-2.3.jar。 ...

    springMVC和Quartz定时

    而Quartz是Java领域内广泛应用的定时任务库,能够实现定时调度任务,广泛应用于大数据处理、定时报告生成、邮件发送等各种场景。 在Spring MVC项目中集成Quartz定时器,可以实现应用的自动执行任务,比如定期清理...

    企业后台管理基础框架 hsweb.zip

    定时任务: 配置定时任务,使用动态脚本编写任务内容.系统监控: 监控系统资源使用情况.缓存监控: 监控缓存情况.访问日志: 记录用户每次操作情况未来:组织架构管理: 地区-机构-部门-职务-人员.工作流管理: activiti...

    基于Java的开发的SHELL CRaSH.zip

    CRaSH的核心是基于Groovy语言构建的,Groovy是一种动态、灵活的Java平台语言,它具有简洁的语法和强大的脚本能力。通过CRaSH,你可以用Groovy编写命令,这些命令可以在运行时解析并执行,为Java应用程序添加了一层...

    spring-boot-quartz

    Quartz 是一个开源的作业调度框架,常被用来执行定时任务。当我们结合 Spring Boot 和 Quartz,我们可以构建一个强大的定时任务管理系统,这在许多业务场景中非常有用,比如数据清理、报告生成、定期发送邮件等。 ...

    ofbiz开发文档

    4. **调度器**:定时执行任务,如定期生成报告、清理数据等。 5. **事件驱动系统**:通过事件和监听器机制,实现组件间的解耦通信。 6. **Web服务接口**:允许与其他系统进行集成,提供服务消费和提供能力。 **...

    工作流Activiti的学习总结(八)Activiti自动执行的应用

    Activiti支持使用Cron表达式来设置定时任务,这使得任务可以在特定时间点自动触发,比如每天的某个时间执行某个流程实例。 5. **事件触发器**: 通过事件触发器,流程中的任务可以在满足特定条件时自动开始或结束...

    grails-quartz-0.4.1

    `Grails` 是一个基于 `Groovy` 语言的敏捷开发框架,它简化了构建基于Java平台的Web应用。而`Quartz` 是一个功能丰富的开源作业调度框架,用于执行定时任务。在`Grails` 中,`Grails-Quartz` 插件提供了集成`Quartz`...

    基于JBI的ServiceMix服务总线.

    - **Quartz**:提供定时任务服务,用于实现周期性的业务操作。 - **Cache**:提供缓存服务,优化数据访问性能。 - **JCA**:实现与企业信息系统(EIS)的连接,提高系统的集成能力。 - **Groovy**:利用Groovy...

    spring jar 包2

    这些组件的组合表明,这个"spring jar 包2"可能是为了开发一个功能丰富的Spring应用程序,涵盖了日志、数据库、PDF处理、定时任务、ORM、动态语言支持以及portlet应用等多个方面。开发者可以利用这些工具来构建复杂...

    基于linux下Jenkins+gradle+gitlab+Android studio实现APP自动打包详细教程.docx

    - 支持多种构建触发机制,包括定时任务、代码提交等。 - 提供丰富的插件生态系统以扩展功能。 **1.2 Jenkins安装方法** - **方法一**: 直接下载WAR包安装 - **步骤**: - 访问Jenkins官方网站 ...

    Android studio下的quartz工程

    - 定时器:可以设置定时任务,如每隔一段时间执行一次。 - 触发器:控制任务何时开始。 - 作业:实际要执行的任务。 - 调度器:管理触发器和作业,负责调度任务的执行。 ### 2. 集成Quartz到Android项目 要在...

    autod-lab

    4. **任务调度**:该平台可能会包含一个任务调度器,让用户能够设置定时任务,自动执行特定时间的实验或测试。 5. **结果可视化**:实验和测试的结果可能通过图表、日志或其他形式进行可视化展示,帮助用户更好地...

    Gradle创建的SpringBoot小项目

    它集成了大量的常用组件,如数据源、定时任务、缓存、消息等,提供了自动配置,使得开发者可以快速地构建一个独立运行的Spring应用程序。 **Gradle介绍** Gradle是一个基于Apache Ant和Maven概念的项目自动化构建...

Global site tag (gtag.js) - Google Analytics