`

使用Quartz实现任务调度和任务调度管理

阅读更多

Quartz要求一个任务必须实现接口Job的execute方法,如下一个简单的Job:

import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class SimpleJob implements Job {

    public SimpleJob() {
    }

    public void execute(JobExecutionContext context) throws JobExecutionException {
       
     try {
      
       Thread.sleep(1000*20);
      
     } catch (InterruptedException e) {
      
       e.printStackTrace();
     }

   }
}

Quartz将任务和时间触发分开,因此,你还需要指定时间触发,通常采用Cron方式,如每天早上六点,也可以指定某个固定时间,如2008年8月8号等。

如以下即指定每天早上六点

CronTrigger cronTrigger = new CronTrigger("triggerName", "triggerGroup");
try {
   
    CronExpression cexp = new CronExpression("0 6 * * * ");    
    cronTrigger.setCronExpression(cexp);
} catch (Exception e) {
    e.printStackTrace();
}

Scheduler 类负责将时间触发指定给JobDetail,简单的来说JobDetail封装了你的任务,并可以提供任务名,所属组,以及附加的一些参数,代码如下:

SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
JobDetail job = new JobDetail("jobName", "groupName", SimpleJob.class);
Scheduler.scheduleJob(job, cronTrigger);

Job在被触发的时候,会通过反射实例化SimpleJob.class(因此你的Job必须有一个无参数的构造函数),并调用execute方法。

对于上列的SimpleJob,可以从execute方法输入参数context里获取一些属性,如任务名(如例子里的jobName),所在组(如:groupName).更重要的是,context里可以包含你指定的参数,如我们想让SimpleJob在运行的时候休眠时间为50秒,也可以这么写:

public void execute(JobExecutionContext context) throws JobExecutionException {
       
try {
   
    int sleep = context.getJobDetail().getJobDataMap().getInt("sleep");
    Thread.sleep(1000*sleep);
   
} catch (InterruptedException e) {
   
    e.printStackTrace();
}

}

参数Sleep将由调度框架传入,如下

SchedulerFactory sf = new StdSchedulerFactory();
Scheduler sched = sf.getScheduler();
JobDetail job = new JobDetail("job1", "group1", SimpleJob.class);
job.getJobDataMap().put("sleep", 50);
Scheduler.scheduleJob(job, trigger);

 

对于实际任务调度来说,Quartz只是提供了基本功能,摆在我们面前的仍然有一些需求Quartz并没有内置。如

    任务状态管理:需要查看当前有哪些任务在运行,历史上任务执行情况

    异常处理:任务出现异常需要告警,或者手工强制执行。

    任务依赖关系:任务A执行前,任务B必须执行成功。

    本文的下半部分将介绍如何实现这些功能,这也是我要写的重点.

    首先,我们使用Annotation定义任务,如下一个任务

public class SimpleJob{

@Run
public void doit()
{
    try {   
       Thread.sleep(1000*20);   
    } catch (InterruptedException e) {  
       e.printStackTrace();
    }
}
}

也可以增加Stop,Pause,Resume等Annotation,在此略过

Annoatoin定义如下

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented

public @interface Run {

}

我倾向于用Annotation而不是接口是因为Annotation更灵活。比如一些传统的任务调度程序入口就是static main(String[] args)方法,只需要用Annotation指示一下,而且,Annoation扩展性也好,如给一个任务命名,可以扩展Annoatoin实现,如下;

@Run(name="com.simpleJob")
public void doit(String[] args)
{
    try {   
       Thread.sleep(1000*20);   
    } catch (InterruptedException e) {  
       e.printStackTrace();
    }
}
}

   用Annoaton定义任务后,这任务如何加入到Quartz框架里?可以定义个新的Wrapper类,叫着JobWrapper,它是一个标准的Quartz的任务,即实现了接口Job ,当Quartz调用次类的时候,此类会根据DataMap里的BatchDescription描述来调用正确的任务。

BatchDescription很简单,有三个属性

private String className;
private String cron;
private String[] paramenters=null;

className,即为使用Annotation定义的任务。
cron即为Cron时间表达式
paramenters 为任务的参数.

JobWrapper 是系统的核心,Quartz调用它,它转而调用JobDescription描述的任务,多了这一层,就能很好的管理Job状态,做一些异常处理等更为复杂的任务管理了。代码如下:

 

 

public JobWrapper()
{
   // be used to persist to database or other features
   id = System.currentTimeMillis()+"_"+Thread.currentThread().getId();
stateChanged(id,JobStatus.INIT);
JobManager.instance().reg(this)


}

public void execute(JobExecutionContext context)
    throws JobExecutionException {
   JobDataMap data = context.getJobDetail().getJobDataMap();
    desc = (BatchDescription)data.get("JobData");
    runParameters = desc.getParamenter();  
   try {
    realJob = Class.forName(desc.getClassName()).newInstance();
   
   } catch (Exception e1) {

       e1.printStackTrace();
     return ;
   }
   //look for the method with annotation Run
   runMethod = getRunMethod();
   //reg it ,then can get it later  
   try {
   
    stateChanged(id,JobStatus.RUNNING)   
    runMethod.invoke(realJob, runParameters);   
   stateChanged(id,JobStatus.RUNNING)
    } catch (IllegalArgumentException e) {
      //ignore
      e.printStackTrace();
      return ;
   } catch (IllegalAccessException e) {
     //ignore
      e.printStackTrace();
      return ;
   } catch (InvocationTargetException e) {
     Throwable ex = e.getTargetException();
     // handle exception ,now just put this exception to some queue
       stateChanged(id,JobStatus.EXCEPTOIN,ex.getMessage()) ;
      return ;   
   }
}

private void stateChanged(String id,JobStatus,String msg){

    //此方法可以用来存储任务到数据库,以供查看状态,如:

   JobDao.save(id,name,JobStatus,msg,new Date());

  

}

private Method getRunMethod()
{
   // first look up the method with run annotation,if not find,check the main method
   if(runMethod!=null){
    return runMethod;
   }
   
   Method[] methods = realJob.getClass().getDeclaredMethods();
   for(Method m:methods)
   {
   
    Annotation[] annos = m.getAnnotations();
    if(annos!=null&&annos.length!=0)
    {
     for(Annotation anno:annos)
     {
      //System.out.println(anno.annotationType());
      if(anno.annotationType()==com.joelli.batch.quartz.annotation.Run.class)
      {
      
       return m;
      }
     }
    }
   
   
   }
   // look for the method public static void main,let ignore it   
   return null;
}

最后,然我们看看Quartz如何调用此类

//定义一个任务,类为com.javamonkey.SimpleJob,参数为Null
BatchDescription batchDesc= new BatchDescription("com.javamonkey.SimpleJob","15 0/2 * * * ?",null);

JobDetail job1 = new JobDetail(batchDesc.getClassName()+ ".Job", "joelli", JobWrapper.class);
job1.getJobDataMap().put("JobData", batchDesc);
CronTrigger cronTrigger = new CronTrigger(batchDesc.getClassName()+ ".Trigger");
CronExpression cexp = new CronExpression("0 6 * * * ");    
cronTrigger.setCronExpression(cexp);
Scheduler.scheduleJob(job1, cronTrigger);

如上代码,Quartz在时间触发后,会实例话JobWrapper.class,并调用Execute方法。JobWrapper会根据BatchDescription获得真正要运行的任务并调用,同时,纪录任务状态以供管理。

分享到:
评论
1 楼 bestxiaok 2012-01-11  
你实现jobwarapper了吗?

相关推荐

    利用Quartz实现任务调度的集群

    - **调度任务**:将Jobs和Triggers关联,注册到Scheduler中,然后启动Scheduler以开始执行任务。 - **监控和管理**:Quartz提供了多种工具和API用于监控和管理任务调度,包括查看任务状态、暂停或恢复任务、删除...

    Java使用quartz实现任务调度定时任务

    本篇文章将深入探讨如何使用Quartz在Java应用程序中实现任务调度。 Quartz库提供了一个灵活的API,可以创建、调度和管理任务,这些任务被称为Job。每个Job都与一个Trigger关联,Trigger定义了何时启动Job。在Java...

    Spring+Quartz实现任务调度的小例子

    Spring框架和Quartz是两个广泛使用的工具,它们可以协同工作以实现复杂和灵活的任务调度。本篇文章将深入探讨如何使用Spring与Quartz结合来创建一个任务调度的小例子。 首先,Spring是一个开源的Java企业级应用开发...

    ASP.NET使用Quartz.NET实现定时任务调度

    结合使用Quartz.NET和TopShelf,我们可以构建一个在Windows服务中运行的定时任务调度系统。 Quartz.NET的特性包括: 1. **灵活的调度**:Quartz.NET支持多种调度模式,如简单触发器、cron触发器,可以按照精确时间...

    Java中使用Quartz实现任务自动调度的经典例子!

    Quartz是Java中一个强大的开源任务调度库,它允许开发者定义和执行短时或周期性的任务。...通过学习和实践这个例子,你将能够熟练地在Java项目中使用Quartz进行任务调度,实现复杂的工作流自动化。

    quartz 定时任务调度

    Quartz 是一个开源的作业调度框架,用于在 Java 应用程序中实现复杂的时间调度任务。它允许开发者定义定时任务,这些任务会在指定的时间点自动执行。Quartz 提供了一套丰富的 API 和支持,可以方便地与 Spring 框架...

    Quartz.Net任务调度

    Quartz.Net的设计灵感来源于Java的Quartz库,它允许开发者灵活地定义和管理作业(Jobs)以及触发器(Triggers),实现任务的自动化执行。 1. **Quartz.Net基本概念** - **作业(Jobs)**:作业是实际需要执行的...

    .net Quartz 任务调度平台源码

    Quartz.NET 是开源项目Quartz的.NET版本,它允许开发人员在应用程序中创建、管理和执行定时任务,而无需关注具体的调度细节。 在".NET 简单任务调度平台"中,主要功能包括: 1. **任务挂载**:开发者可以将.NET的...

    Quartz.net作业调度自定义定时执行任务多任务执行c#

    Quartz.NET是一个强大的开源作业调度框架,用于在.NET环境中创建和执行定时任务。它提供了高度灵活的调度功能,使得开发者可以轻松地定义...通过熟练掌握Quartz.NET,开发者可以更好地设计和实现高效、可靠的后台服务。

    Quartz任务调度器

    在与Spring框架整合后,Quartz能更好地融入到现有的应用架构中,实现更高效的资源管理和任务调度。 首先,我们要理解Quartz的核心概念。`Job`是Quartz中的基本工作单元,它代表一个要执行的任务。而`Trigger`则定义...

    quartzDemo任务调度例子

    - **调度任务**:将Job和Trigger关联并添加到Scheduler,然后启动Scheduler。 7. **监控和管理** Quartz提供了一个Web界面JMX(Java Management Extensions)和API,允许我们监控和管理正在运行的任务,如暂停、...

    spring任务调度(Quartz )

    3. **调度器配置**:`SchedulerFactoryBean`是Spring对Quartz调度器的包装,它管理所有的触发器和任务。在这里,我们将`cron`触发器添加到调度器中,使得任务与触发器关联起来。 接下来,我们看下服务类和服务的...

    quartz1.5.0 任务调度demo

    在这个"quartz1.5.0 任务调度demo"中,我们将会探讨如何使用Quartz实现任务的增删改功能,以及其三大核心组件:JobDetail、Trigger和Scheduler。 首先,**JobDetail**是Quartz中的工作类,它定义了一个具体的任务,...

    任务调度开源框架Quartz

    3. **集群支持**:Quartz可以部署在集群环境中,多个节点共享同一份调度信息,当一个节点失败时,其他节点可以接管调度任务,提供高可用性。 4. **插件友好**:Quartz允许开发人员通过插件扩展其功能,例如日志插件...

    Quartz(任务调度)使用培训

    标题和描述中提到的主题是关于Quartz任务调度系统的使用培训。Quartz是一个开源的任务调度库,其主要用途是让开发者能够轻松地安排在特定时间或根据特定规则运行代码的任务,也就是作业(Jobs)。Quartz能够与Java...

    Quartz任务调度管理

    ### Quartz任务调度管理 #### 一、任务调度基础概念 任务调度是指系统按照预先设定的时间规则来自动执行特定任务的功能。这种机制广泛应用于各种场景,例如数据备份、定期检查资源状态、发送邮件通知等。 ##### ...

    java实现任务调度

    要实现一个完整的任务调度系统,除了对Quartz调度器的使用和Spring框架的整合外,还需要考虑安全性、事务管理、错误处理以及性能优化等方面。例如,要保证作业执行的安全性,可以使用Spring Security来管理对作业...

    Spring整合任务调度框架Quartz

    Spring 整合任务调度框架 Quartz ...Spring 整合任务调度框架 Quartz,可以使用配置文件方式或 Quartz 持久化方式来实现任务调度。开发者可以根据实际情况选择合适的方式,从而提高软件系统的自动化和可靠性。

Global site tag (gtag.js) - Google Analytics