首页 > 技术文章 > spring3.1.3+quartz1.8 集群 (spring3+quartz2.2试验)

limiracle 2014-09-12 14:25 原文

我们系统中原有的基于spring3自带的task,并使用注解方式制定调度策略。单由于需求需要动态定制添加、修改、删除任务。spring自带的task无法满足需求。所以考虑使用spring+quartz。网上很多人说spring3+才能使用quartz2.+的版本,正好我们使用的spring版本为spring 3+,所以兴冲冲的使用了quartz-2.2.1的最新版本。通过搭建环境测试完美解决了动态定制任务的需求。参考(http://www.meiriyouke.net/?p=140),本文不详细叙述这种方式。只贴出源码

quartz对于集群方式采取数据库同步方式。以上方式使用spring 3+quartz2.2只能采用单机环境执行,所有调度都保存在内存中无法进行集群,所以考虑将dataSource注入到schedulerFactoryBean中,但是悲剧的是报“序列化”的错误。在网上找到解决方式是替换两个类,但是只有针对于quartz1版本的替换方式,针对于2版本的替换还没有~~~

无奈之使用了spring 3.1.3+quartz1.8 数据库方式搭建了动态定制任务。

1 spring3+quartz2.2

spring配置文件

<bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" />

任务运行入口,即Job实现类

public class QuartzJobFactory implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("任务成功运行");
        ScheduleJob scheduleJob = (ScheduleJob)context.getMergedJobDataMap().get("scheduleJob");
        System.out.println("任务名称 = [" + scheduleJob.getJobName() + "]");
 }
}

既然要动态的创建任务,我们的任务信息当然要保存在某个地方了,这里我们新建一个保存任务信息对应的实体类

package com.adtec.moia.rsp.engine;

import java.io.Serializable;

public class ScheduleJob implements Serializable{
    
    /** 任务id */
    private String jobId;
    
    /** 任务名称 */
    private String jobName;
    
    /** 任务分组 */
    private String jobGroup;
    
    /** 任务状态 0禁用 1启用 2删除*/
    private String jobStatus;
    
     /** 任务运行时间表达式 */
    private String cronExpression;
    
     /** 任务描述 */
    private String desc;
    
    /**任务调用实现*/
    private String classFullName;

    public String getJobId() {
        return jobId;
    }

    public void setJobId(String jobId) {
        this.jobId = jobId;
    }

    public String getJobName() {
        return jobName;
    }

    public void setJobName(String jobName) {
        this.jobName = jobName;
    }

    public String getJobGroup() {
        return jobGroup;
    }

    public void setJobGroup(String jobGroup) {
        this.jobGroup = jobGroup;
    }

    public String getJobStatus() {
        return jobStatus;
    }

    public void setJobStatus(String jobStatus) {
        this.jobStatus = jobStatus;
    }

    public String getCronExpression() {
        return cronExpression;
    }

    public void setCronExpression(String cronExpression) {
        this.cronExpression = cronExpression;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getClassFullName() {
        return classFullName;
    }

    public void setClassFullName(String classFullName) {
        this.classFullName = classFullName;
    }
    
}

动态创建任务的驱动类

package com.adtec.moia.rsp.engine;

import java.util.Date;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import com.adtec.moia.base.exception.ServiceException;
import com.adtec.moia.rsp.task.QuartzJobFactory;

public class TaskEngineService {
    
    private SchedulerFactoryBean schedulerFactoryBean;
    
    public void addTask(ScheduleJob job1)
            throws ServiceException, Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(),job.getJobGroup());
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        if(null==trigger){
            Class<?> class1=Class.forName(job.getClassFullName());
            Class<? extends Job> jobClass = (Class<? extends Job>) class1;

            JobBuilder jobBuilder= JobBuilder.newJob(jobClass);
            JobDetail jobDetail =jobBuilder.withIdentity(job.getJobName(),job.getJobGroup()).build();
            jobDetail.getJobDataMap().put(job.getClassFullName(), job);
            //表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
            //按新的cronExpression表达式构建一个新的trigger
            trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
            scheduler.start();
        }
        JobDetail job = JobBuilder.newJob(QuartzJobFactory.class).withIdentity("job1", "group1").build();
        Date runTime = DateBuilder.evenMinuteDate(new Date());
         CronTrigger trigger = (CronTrigger)TriggerBuilder.newTrigger().withIdentity("trigger1", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

        scheduler.scheduleJob(job, trigger);
        scheduler.start();

    }
    
    public void stopTask(ScheduleJob job)
            throws ServiceException, Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.pauseJob(jobKey);
    }
    
    
    
    public void resumeJob(ScheduleJob job)
            throws ServiceException, Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.resumeJob(jobKey);
    }
    public void removeTask(ScheduleJob job)
            throws ServiceException, Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.deleteJob(jobKey);
    }
    
    public void startNowTask(ScheduleJob job) throws SchedulerException{
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.triggerJob(jobKey);
    }
        
    
    public void refreshTask(ScheduleJob job)
            throws ServiceException, Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        TriggerKey triggerKey = TriggerKey.triggerKey(job.getJobName(),job.getJobGroup());
        //获取trigger,即在spring配置文件中定义的 bean id="myTrigger"
        CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
        //表达式调度构建器
        CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
        //按新的cronExpression表达式构建一个新的trigger
        trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
        //按新的trigger重新设置job执行
        scheduler.rescheduleJob(triggerKey, trigger);
        }
}
//

执行测试主要代码:

//测试任务执行
        ScheduleJob job=new ScheduleJob();
        job.setJobId("10001");
        job.setJobName("data_import");
        job.setJobGroup("dataWork");
        job.setJobStatus("1");
        job.setCronExpression("0/5 * * * * ?");
        job.setDesc("数据导入任务");
        job.setClassFullName("com.adtec.moia.rsp.task.QuartzJobFactory");
        try {
            Class.forName(job.getClassFullName());
            taskEngineService.addTask(job);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

2 spring3+quartz1.8

需要jar包:

spring核心包+quartz需要包。我们项目中的包包括:

image+image

spring配置文件中注入:

<bean id="schedulerFactoryBean"
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="configLocation" value="classpath:quartz.properties" />
        <property name="dataSource" ref="dataSource" />
        <property name="triggers">
            <list>
            </list>
        </property>
    </bean>

其中dataSource是quartz连接数据库的信息,quartz.properties为quartz配置信息。具体如下:标红部分表示使用数据库方式(为了集群)

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================
org.quartz.scheduler.instanceName = RspDefaultQuartzScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
org.quartz.scheduler.wrapJobExecutionInUserTransaction = false

#============================================================================
# Configure ThreadPool  
#============================================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

#============================================================================
# Configure JobStore  
#============================================================================
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.txIsolationLevelSerializable = true

org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 15000

org.quartz.jobStore.dontSetAutoCommitFalse = true

重写MethodInvokingJobDetailFactoryBean类,避免序列化错误

public class MethodInvokingJobDetailFactoryBean implements FactoryBean, BeanNameAware, InitializingBean
{
    private Log logger = LogFactory.getLog(getClass());

    /**
     * The JobDetail produced by the <code>afterPropertiesSet</code> method of this Class will be assigned to the Group specified by this property.  Default: Scheduler.DEFAULT_GROUP 
     * @see #afterPropertiesSet()
     * @see Scheduler#DEFAULT_GROUP
     */
    private String group = Scheduler.DEFAULT_GROUP;

    /**
     * Indicates whether or not the Bean Method should be invoked by more than one Scheduler at the specified time (like when deployed to a cluster, and/or when there are multiple Spring ApplicationContexts in a single JVM<i> - Tomcat 5.5 creates 2 or more instances of the DispatcherServlet (a pool), which in turn creates a separate Spring ApplicationContext for each instance of the servlet</i>) 
     * <p>
     * Used by <code>afterPropertiesSet</code> to set the JobDetail.jobClass to MethodInvokingJob.class or StatefulMethodInvokingJob.class when true or false, respectively.  Default: true 
     * @see #afterPropertiesSet()
     */
    private boolean concurrent = true;
    
    /** Used to set the JobDetail.durable property.  Default: false
     * <p>Durability - if a job is non-durable, it is automatically deleted from the scheduler once there are no longer any active triggers associated with it.
     * @see <a href="http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html">http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html</a> 
     * @see #afterPropertiesSet() 
     */
    private boolean durable = false;
    
    /**
     * Used by <code>afterPropertiesSet</code> to set the JobDetail.volatile property.  Default: false
     * <p>Volatility - if a job is volatile, it is not persisted between re-starts of the Quartz scheduler.
     * <p>I set the default to false to be the same as the default for a Quartz Trigger.  An exception is thrown 
     * when the Trigger is non-volatile and the Job is volatile.  If you want volatility, then you must set this property, and the Trigger's volatility property, to true.
     * @see <a href="http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html">http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html</a>
     * @see #afterPropertiesSet() 
     */
    private boolean volatility = false;
    
    /** 
     * Used by <code>afterPropertiesSet</code> to set the JobDetail.requestsRecovery property.  Default: false<BR>
     * <p>RequestsRecovery - if a job "requests recovery", and it is executing during the time of a 'hard shutdown' of the scheduler (i.e. the process it is running within crashes, or the machine is shut off), then it is re-executed when the scheduler is started again. In this case, the JobExecutionContext.isRecovering() method will return true. 
     * @see <a href="http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html">http://www.opensymphony.com/quartz/wikidocs/TutorialLesson3.html</a> 
     * @see #afterPropertiesSet() 
     */
    private boolean shouldRecover = false;
    
    /**
     * A list of names of JobListeners to associate with the JobDetail object created by this FactoryBean.
     *
     * @see #afterPropertiesSet() 
     **/
    private String[] jobListenerNames;
    
    /** The name assigned to this bean in the Spring ApplicationContext.
     * Used by <code>afterPropertiesSet</code> to set the JobDetail.name property.
     * @see afterPropertiesSet()
     * @see JobDetail#setName(String)
     **/
    private String beanName;
    
    /**
     * The JobDetail produced by the <code>afterPropertiesSet</code> method, and returned by the <code>getObject</code> method of the Spring FactoryBean interface.
     * @see #afterPropertiesSet()
     * @see #getObject()
     * @see FactoryBean
     **/
    private JobDetail jobDetail;
    
    /**
     * The name of the Class to invoke.
     **/
    private String targetClass;

    /**
     * The Object to invoke.
     * <p>
     * {@link #targetClass} or targetObject must be set, but not both.
     * <p>
     * This object must be Serializable when {@link #concurrent} is set to false.
     */
    private Object targetObject;
    
    /**
     * The instance method to invoke on the Class or Object identified by the targetClass or targetObject property, respectfully.
     * <p>
     * targetMethod or {@link #staticMethod} should be set, but not both. 
     **/
    private String targetMethod;
    
    /**
     * The static method to invoke on the Class or Object identified by the targetClass or targetObject property, respectfully.
     * <p>
     * {@link #targetMethod} or staticMethod should be set, but not both. 
     */
    private String staticMethod;

    /**
     * Method arguments provided to the {@link #targetMethod} or {@link #staticMethod} specified.
     * <p>
     * All arguments must be Serializable when {@link #concurrent} is set to false.
     * <p>
     * I strongly urge you not to provide arguments until Quartz 1.6.1 has been released if you are using a JDBCJobStore with
     * Microsoft SQL Server. There is a bug in version 1.6.0 that prevents Quartz from Serializing the Objects in the JobDataMap
     * to the database.  The workaround is to set the property "org.opensymphony.quaryz.useProperties = true" in your quartz.properties file,
     * which tells Quartz not to serialize Objects in the JobDataMap, but to instead expect all String compliant values.
     */
    private Object[] arguments;

    /**
     * Get the targetClass property.
     * @see #targetClass
     * @return targetClass
     */
    public String getTargetClass()
    {
        return targetClass;
    }

    /**
     * Set the targetClass property.
     * @see #targetClass
     */
    public void setTargetClass(String targetClass)
    {
        this.targetClass = targetClass;
    }

    /**
     * Get the targetMethod property.
     * @see #targetMethod
     * @return targetMethod
     */
    public String getTargetMethod()
    {
        return targetMethod;
    }

    /**
     * Set the targetMethod property.
     * @see #targetMethod
     */
    public void setTargetMethod(String targetMethod)
    {
        this.targetMethod = targetMethod;
    }

    /**
     * @return jobDetail - The JobDetail that is created by the afterPropertiesSet method of this FactoryBean
     * @see #jobDetail
     * @see #afterPropertiesSet()
     * @see FactoryBean#getObject()
     */
    public Object getObject() throws Exception
    {
        return jobDetail;
    }

    /**
     * @return JobDetail.class
     * @see FactoryBean#getObjectType()
     */
    public Class getObjectType()
    {
        return JobDetail.class;
    }

    /**
     * @return true
     * @see FactoryBean#isSingleton()
     */
    public boolean isSingleton()
    {
        return true;
    }

    /**
     * Set the beanName property.
     * @see #beanName
     * @see BeanNameAware#setBeanName(String)
     */
    public void setBeanName(String beanName)
    {
        this.beanName = beanName;
    }

    /**
     * Invoked by the Spring container after all properties have been set.
     * <p>
     * Sets the <code>jobDetail</code> property to a new instance of JobDetail
     * <ul>
     * <li>jobDetail.name is set to <code>beanName</code><br>
     * <li>jobDetail.group is set to <code>group</code><br>
     * <li>jobDetail.jobClass is set to MethodInvokingJob.class or StatefulMethodInvokingJob.class depending on whether the <code>concurrent</code> property is set to true or false, respectively.<br>
     * <li>jobDetail.durability is set to <code>durable</code>
     * <li>jobDetail.volatility is set to <code>volatility</code>
     * <li>jobDetail.requestsRecovery is set to <code>shouldRecover</code>
     * <li>jobDetail.jobDataMap["targetClass"] is set to <code>targetClass</code>
     * <li>jobDetail.jobDataMap["targetMethod"] is set to <code>targetMethod</code>
     * <li>Each JobListener name in <code>jobListenerNames</code> is added to the <code>jobDetail</code> object.
     * </ul>
     * <p>
     * Logging occurs at the DEBUG and INFO levels; 4 lines at the DEBUG level, and 1 line at the INFO level.
     * <ul>
     * <li>DEBUG: start
     * <li>DEBUG: Creating JobDetail <code>{beanName}</code>
     * <li>DEBUG: Registering JobListener names with JobDetail object <code>{beanName}</code>
     * <li>INFO: Created JobDetail: <code>{jobDetail}</code>; targetClass: <code>{targetClass}</code>; targetMethod: <code>{targetMethod}</code>;
     * <li>DEBUG: end
     * </ul>
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     * @see JobDetail
     * @see #jobDetail
     * @see #beanName
     * @see #group
     * @see MethodInvokingJob
     * @see StatefulMethodInvokingJob
     * @see #durable
     * @see #volatility
     * @see #shouldRecover
     * @see #targetClass
     * @see #targetMethod
     * @see #jobListenerNames 
     */
    public void afterPropertiesSet() throws Exception
    {
        try
        {
            logger.debug("start");
            
            logger.debug("Creating JobDetail "+beanName);
            jobDetail = new JobDetail();
            jobDetail.setName(beanName);
            jobDetail.setGroup(group);
            jobDetail.setJobClass(concurrent ? MethodInvokingJob.class : StatefulMethodInvokingJob.class);
            jobDetail.setDurability(durable);
            jobDetail.setVolatility(volatility);
            jobDetail.setRequestsRecovery(shouldRecover);
            if(targetClass!=null)
                jobDetail.getJobDataMap().put("targetClass", targetClass);
            if(targetObject!=null)
                jobDetail.getJobDataMap().put("targetObject", targetObject);
            if(targetMethod!=null)
                jobDetail.getJobDataMap().put("targetMethod", targetMethod);
            if(staticMethod!=null)
                jobDetail.getJobDataMap().put("staticMethod", staticMethod);
            if(arguments!=null)
                jobDetail.getJobDataMap().put("arguments", arguments);
            
            logger.debug("Registering JobListener names with JobDetail object "+beanName);
            if (this.jobListenerNames != null) {
                for (int i = 0; i < this.jobListenerNames.length; i++) {
                    this.jobDetail.addJobListener(this.jobListenerNames[i]);
                }
            }
            logger.info("Created JobDetail: "+jobDetail+"; targetClass: "+targetClass+"; targetObject: "+targetObject+"; targetMethod: "+targetMethod+"; staticMethod: "+staticMethod+"; arguments: "+arguments+";");
        }
        finally
        {
            logger.debug("end");
        }
    }

    /**
     * Setter for the concurrent property.
     * 
     * @param concurrent
     * @see #concurrent
     */
    public void setConcurrent(boolean concurrent)
    {
        this.concurrent = concurrent;
    }

    /**
     * setter for the durable property.
     * 
     * @param durable
     * 
     * @see #durable
     */
    public void setDurable(boolean durable)
    {
        this.durable = durable;
    }

    /**
     * setter for the group property.
     * 
     * @param group
     * 
     * @see #group
     */
    public void setGroup(String group)
    {
        this.group = group;
    }

    /**
     * setter for the {@link #jobListenerNames} property.
     * 
     * @param jobListenerNames
     * @see #jobListenerNames
     */
    public void setJobListenerNames(String[] jobListenerNames)
    {
        this.jobListenerNames = jobListenerNames;
    }

    /**
     * setter for the {@link #shouldRecover} property.
     * 
     * @param shouldRecover
     * @see #shouldRecover
     */
    public void setShouldRecover(boolean shouldRecover)
    {
        this.shouldRecover = shouldRecover;
    }

    /**
     * setter for the {@link #volatility} property.
     * 
     * @param volatility
     * @see #volatility
     */
    public void setVolatility(boolean volatility)
    {
        this.volatility = volatility;
    }

    /**
     * This is a cluster safe Job designed to invoke a method on any bean defined within the same Spring
     * ApplicationContext.
     * <p>
     * The only entries this Job expects in the JobDataMap are "targetClass" and "targetMethod".<br>
     * - It uses the value of the <code>targetClass</code> entry to get the desired bean from the Spring ApplicationContext.<br>
     * - It uses the value of the <code>targetMethod</code> entry to determine which method of the Bean (identified by targetClass) to invoke.
     * <p>
     * It uses the static ApplicationContext in the MethodInvokingJobDetailFactoryBean,
     * which is ApplicationContextAware, to get the Bean with which to invoke the method.
     * <p>
     * All Exceptions thrown from the execute method are caught and wrapped in a JobExecutionException.
     * 
     * @see MethodInvokingJobDetailFactoryBean#applicationContext
     * @see #execute(JobExecutionContext)
     * 
     * @author Stephen M. Wick
     */
    public static class MethodInvokingJob implements Job
    {
        protected Log logger = LogFactory.getLog(getClass());
        
        /**
         * When invoked by a Quartz scheduler, <code>execute</code> invokes a method on a Class or Object in the JobExecutionContext provided.
         * <p>
         * <b>Implementation</b><br>
         * The Class is identified by the "targetClass" entry in the JobDataMap of the JobExecutionContext provided.  If targetClass is specified, then targetMethod must be a static method.<br>
         * The Object is identified by the 'targetObject" entry in the JobDataMap of the JobExecutionContext provided.  If targetObject is provided, then targetClass will be overwritten.  This Object must be Serializable when <code>concurrent</code> is set to false.<br>
         * The method is identified by the "targetMethod" entry in the JobDataMap of the JobExecutionContext provided.<br>
         * The "staticMethod" entry in the JobDataMap of the JobExecutionContext can be used to specify a Class and Method in one entry (ie: "example.ExampleClass.someStaticMethod")<br>
         * The method arguments (an array of Objects) are identified by the "arguments" entry in the JobDataMap of the JobExecutionContext.  All arguments must be Serializable when <code>concurrent</code> is set to false.
         * <p>
         * Logging is provided at the DEBUG and INFO levels; 8 lines at the DEBUG level, and 1 line at the INFO level.
         * @see Job#execute(JobExecutionContext)
         */
        public void execute(JobExecutionContext context) throws JobExecutionException
        {
            try
            {
                logger.debug("start");
                String targetClass = context.getMergedJobDataMap().getString("targetClass");
                logger.debug("targetClass is "+targetClass);
                Class targetClassClass = null;
                if(targetClass!=null)
                {
                    targetClassClass = Class.forName(targetClass); // Could throw ClassNotFoundException
                }
                Object targetObject = context.getMergedJobDataMap().get("targetObject");
                logger.debug("targetObject is "+targetObject);
                String targetMethod = context.getMergedJobDataMap().getString("targetMethod");
                logger.debug("targetMethod is "+targetMethod);
                String staticMethod = context.getMergedJobDataMap().getString("staticMethod");
                logger.debug("staticMethod is "+staticMethod);
                Object[] arguments = (Object[])context.getMergedJobDataMap().get("arguments");
                logger.debug("arguments are "+arguments);
                
                logger.debug("creating MethodInvoker");
                MethodInvoker methodInvoker = new MethodInvoker();
                methodInvoker.setTargetClass(targetClassClass);
                methodInvoker.setTargetObject(targetObject);
                methodInvoker.setTargetMethod(targetMethod);
                methodInvoker.setStaticMethod(staticMethod);
                methodInvoker.setArguments(arguments);
                methodInvoker.prepare();
                logger.info("Invoking: "+methodInvoker.getPreparedMethod().toGenericString());
                methodInvoker.invoke();
            }
            catch(Exception e)
            {
                throw new JobExecutionException(e);
            }
            finally
            {
                logger.debug("end");
            }
        }
    }

    public static class StatefulMethodInvokingJob extends MethodInvokingJob implements StatefulJob
    {
        // No additional functionality; just needs to implement StatefulJob.
    }

    public Object[] getArguments()
    {
        return arguments;
    }

    public void setArguments(Object[] arguments)
    {
        this.arguments = arguments;
    }

    public String getStaticMethod()
    {
        return staticMethod;
    }

    public void setStaticMethod(String staticMethod)
    {
        this.staticMethod = staticMethod;
    }

    public void setTargetObject(Object targetObject)
    {
        this.targetObject = targetObject;
    }
}

具体任务

public class RspRunUserRightJob implements Serializable,Job {

    public void execute(JobExecutionContext jobexecutioncontext)
            throws JobExecutionException {
        System.out.println(":Job 执行~开始~");
        System.out.println();        
        
    }
}

任务管理公共类

/**
 * 功能/模块 :任务管理公共类
 */

@Service("taskEngineService")
public class TaskEngineService {
    @Resource(name = "schedulerFactoryBean")
    private StdScheduler schedulerFactoryBean;

    public void standbyTask(String triggerName, String execClass)
            throws ServiceException {
        try {
            schedulerFactoryBean.pauseTrigger(triggerName,
                    Scheduler.DEFAULT_GROUP);
            schedulerFactoryBean.pauseJob(execClass, Scheduler.DEFAULT_GROUP);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

    }

    public void stopTask(String triggerName, String execClass)
            throws ServiceException {
        try {
            schedulerFactoryBean.pauseTrigger(triggerName,
                    Scheduler.DEFAULT_GROUP);
            schedulerFactoryBean.deleteJob(execClass, Scheduler.DEFAULT_GROUP);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

    }

    public void startTask(JobDetail jobDetail, CronTriggerBean cronTriggerBean)
            throws ServiceException {
        try {
            schedulerFactoryBean.scheduleJob(jobDetail, cronTriggerBean);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }

    public void startTask(JobDetail jobDetail,
            SimpleTriggerBean simpleTriggerBean) throws ServiceException {

        try {
            schedulerFactoryBean.scheduleJob(jobDetail, simpleTriggerBean);
        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }
    }


    public void startTask(SysTaskInfo sysTaskInfo) throws ServiceException {

        MethodInvokingJobDetailFactoryBean test = new MethodInvokingJobDetailFactoryBean();
        if (SYS_TASK_INFO.TASK_STATUS_STOP.equals(sysTaskInfo.getTaskStatus())) {
            JobDetail jobDetail = null;
            try {
                jobDetail = new JobDetail();
                jobDetail.setName(sysTaskInfo.getTaskId());
                jobDetail.setGroup(sysTaskInfo.getTaskId());
                jobDetail.setJobClass(Class.forName("com.adtec.moia.rsp.job.RspRunUserRightJob"));
                jobDetail.setDurability(false);
                jobDetail.setVolatility(false);
                jobDetail.setRequestsRecovery(false);
                jobDetail.getJobDataMap().put("targetClass", Class.forName("com.adtec.moia.rsp.job.RspRunUserRightJob"));
                jobDetail.getJobDataMap().put("targetMethod", "execute");
                
            } catch (Exception e) {
                throw new ServiceException(e.getMessage());
            }
            SysTriggerInfo sysTriggerInfo = sysTaskInfo.getSysTriggerInfo();
            scheduJob(sysTaskInfo.getStartTime(), sysTaskInfo.getEndTime(),
                    jobDetail, sysTriggerInfo, Scheduler.DEFAULT_GROUP);
        } else if ( SYS_TASK_INFO.TASK_STATUS_STANDBY.equals(sysTaskInfo.getTaskStatus())) {
            try {
                schedulerFactoryBean.resumeTrigger(sysTaskInfo.getTriggerId(),
                        Scheduler.DEFAULT_GROUP);
                schedulerFactoryBean.resumeJob(sysTaskInfo.getExecClass(),
                        Scheduler.DEFAULT_GROUP);
            } catch (Exception e) {
                throw new ServiceException(e.getMessage());
            }
        }

    }

    private void scheduJob(Date startTime, Date endTime, JobDetail jobDetail,
            SysTriggerInfo sysTriggerInfo, String group)
            throws ServiceException {
        try {
            if (SYS_TRIGGER_INFO.TRIGGER_TYPE_CRON.equals(sysTriggerInfo.getTriggerType())) {
                CronTriggerBean cronTriggerBean = new CronTriggerBean();
                if (startTime != null) {
                    cronTriggerBean.setStartTime(startTime);
                }
                if (endTime != null) {
                    cronTriggerBean.setEndTime(endTime);
                }

                cronTriggerBean.setCronExpression(sysTriggerInfo
                        .getCronExpression());

                cronTriggerBean.setBeanName(sysTriggerInfo.getTriggerId());
                cronTriggerBean.setJobDetail(jobDetail);
                cronTriggerBean.setGroup(group);
                cronTriggerBean.afterPropertiesSet();

                schedulerFactoryBean.scheduleJob(jobDetail, cronTriggerBean);
            } else {
                SimpleTriggerBean simpleTriggerBean = new SimpleTriggerBean();
                simpleTriggerBean.setBeanName(sysTriggerInfo.getTriggerId());
                if (startTime != null) {
                    simpleTriggerBean.setStartTime(startTime);
                }
                if (endTime != null) {
                    simpleTriggerBean.setEndTime(endTime);
                }
                simpleTriggerBean.setRepeatCount(sysTriggerInfo
                        .getRepeatCount());
                simpleTriggerBean.setStartDelay(sysTriggerInfo.getStartDelay());
                simpleTriggerBean.setRepeatInterval(sysTriggerInfo
                        .getRepeatInterval());
                simpleTriggerBean.setBeanName(sysTriggerInfo.getTriggerId());
                simpleTriggerBean.setJobDetail(jobDetail);
                simpleTriggerBean.setGroup(group);
                simpleTriggerBean.afterPropertiesSet();
                schedulerFactoryBean.scheduleJob(jobDetail, simpleTriggerBean);
            }
        } catch (ParseException e) {
            throw new ServiceException(e.getMessage());
        } catch (SchedulerException e) {
            throw new ServiceException(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

推荐阅读