首页 > 代码库 > spring3.1.3+quartz1.8 集群 (spring3+quartz2.2试验)

spring3.1.3+quartz1.8 集群 (spring3+quartz2.2试验)

我们系统中原有的基于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="http://www.mamicode.com/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 = RspDefaultQuartzSchedulerorg.quartz.scheduler.instanceId = AUTOorg.quartz.scheduler.rmi.export = falseorg.quartz.scheduler.rmi.proxy = falseorg.quartz.scheduler.wrapJobExecutionInUserTransaction = false#============================================================================# Configure ThreadPool  #============================================================================org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPoolorg.quartz.threadPool.threadCount = 10org.quartz.threadPool.threadPriority = 5org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true#============================================================================# Configure JobStore  #============================================================================org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTXorg.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegateorg.quartz.jobStore.misfireThreshold = 60000org.quartz.jobStore.useProperties = falseorg.quartz.jobStore.tablePrefix = QRTZ_org.quartz.jobStore.txIsolationLevelSerializable = trueorg.quartz.jobStore.isClustered = trueorg.quartz.jobStore.clusterCheckinInterval = 15000org.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.mamicode.com/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.mamicode.com/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.mamicode.com/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();        }    }}

spring3.1.3+quartz1.8 集群 (spring3+quartz2.2试验)