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需要包。我们项目中的包包括:

+

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();
        }
    }

}
时间: 2024-10-29 04:20:55

spring3.1.3+quartz1.8 集群 (spring3+quartz2.2试验)的相关文章

结合Apache和Tomcat实现集群和负载均衡 JK 方式

本文基本参考自 轻松实现Apache,Tomcat集群和负载均衡,经由实操经历记录而成,碰到些出入,以及个别地方依据个人的习惯,所以在一定程度上未能保持原文的完整性,还望原著者海涵. 因原文中有较多的贴图,如若各位读者一时不想亲自动手而直想看到配置效果,可查看原文. 一:软件环境 1. Apache: apache 2.0.55 (由http://httpd.apache.org/进入下载)(点击下载apache 2.0.55) 2. Tomcat: Tomcat 5.5.25 (由http:/

项目中使用Quartz集群分享--转载

项目中使用Quartz集群分享--转载 在公司分享了Quartz,发布出来,希望大家讨论补充. CRM使用Quartz集群分享  一:CRM对定时任务的依赖与问题  二:什么是quartz,如何使用,集群,优化  三:CRM中quartz与Spring结合使用 1:CRM对定时任务的依赖与问题  1)依赖  (1)每天晚上的定时任务,通过sql脚本 + crontab方式执行 Xml代码   #crm 0 2 * * * /opt/***/javafiles/***/shell/***_dail

Spring+Quartz框架实现定时任务(集群,分布式)

1.定时任务的必要性: 定时任务在应用中的重要性不言而喻,大多是应用,特别是金融应用更是离不开定时任务,能用定时任务来处理异常订单,完成跑批,定时活动(双11)等.在初期应用的访问量并不是那么大,一台服务器完全满足使用,但是随着用户量.业务量的逐日增加,应用中会有很多定时任务需要执行,一台服务器已经不能满足使用,因此需要把应用给部署到集群中,前端通过nginx代理实现访问. 2.集群使用定时任务的问题:目前大部分在集群中处理定时任务的方式不是正真的分布式处理方式,而是一种伪分布式,这种方式存在一

Quartz集群配置

Quartz集群配置(100%成功) 先看看quartz的持久化基本介绍: 引用 1 大家都清楚quartz最基本的概念就是job,在job内调用具体service完成具体功能,quartz需要把每个job存储起来,方便调度,quartz存储job方式就分三种,我们最常用的也是quartz默认的是RAMJobStore,RAMJobStore顾名思义就是把job的相关信息存储在内存里,如果用spring配置quartz的job信息的话,所有信息是配置在xml里,当spirng context启动

原!总结 quartz集群 定时任务 测试运行ok

由于项目优化重构,想将定时任务从quartz单机模式变成集群或分布式的方式.于是,百度了一圈....修修改改...用集群的方式部署定时任务,测试可以... 集群?分布式?什么区别? 集群:同一个业务,部署在多个服务器上 分布式:一个业务分拆多个子业务,部署在不同的服务器上 或者说 集群:是指在多台不同的服务器中部署相同应用或服务模块,构成一个集群,通过负载均衡设备对外提供服务. 分布式:是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务. 平时常用的quartz单机模

Spring整合Quartz定时任务 在集群、分布式系统中的应用(Mysql数据库环境)

Spring整合Quartz定时任务 在集群.分布式系统中的应用(Mysql数据库环境) 转载:http://www.cnblogs.com/jiafuwei/p/6145280.html 单个Quartz实例能给予你很好的Job调度能力,但它不能满足典型的企业需求,如可伸缩性.高可靠性满足.假如你需要故障转移的能力并能运行日益增多的 Job,Quartz集群势必成为你应用的一部分了.使用 Quartz 的集群能力可以更好的支持你的业务需求,并且即使是其中一台机器在最糟的时间崩溃了也能确保所有的

部署AlwaysOn第一步:搭建Windows服务器故障转移集群

在Windows Server 2012 R2 DataCenter 环境中搭建集群之前,首先要对Windows服务器故障转移集群(Windows Server Failover Cluster,简称WSFC)有基本的了解.WSFC必须部署在域管理环境中,由多台服务器组成,每台服务器称作一个"结点"(Node),每个结点上都运行了Windows服务器故障转移集群服务,整个集群系统允许部分结点掉线.故障或损坏而不影响整个系统的正常运作.集群自动检测结点的健康状态,一旦活跃结点发生异常,变

MySQL集群(二)之主主复制

前面介绍了主从复制,这一篇我将介绍的是主主复制,其实听名字就可以知道,主主复制其实就是两台服务器互为主节点与从节点.接下来我将详细的给大家介绍,怎么去配置主主复制! 一.主从复制中的问题 1.1.从节点占用了主节点的自增id 环境: 主节点:zyhserver1=1.0.0.3 从节点:udzyh1=1.0.0.5 第一步:我们在主节点中创建一个数据库db_love_1,在创建一个表tb_love(里面有id自增和name属性). create database db_love_1; use d

MongoDB 搭建分片集群

在MongoDB(版本 3.2.9)中,分片是指将collection分散存储到不同的Server中,每个Server只存储collection的一部分,服务分片的所有服务器组成分片集群.分片集群(Sharded Clustered)的服务器分为三中类型:Router(mongos),Config Server 和 Shard(Replica Set 或 Standalone mongod).使用分片集群,不需要使用强大的计算机,就能存储更多的数据,处理更大的负载.分布式数据库系统的设计目的是: