zoukankan      html  css  js  c++  java
  • Quartz集成springMVC 的方案二(持久化任务、集群和分布式)

    阿里的面试官问,如果现在很多调度任务,如何优化,可以使用调度池参考:ScheduledExecutor,

    参考:Java 几种调度任务的Timer、ScheduledExecutor、 开源工具包 Quartz、开源工具包 JCronTab

    言归正传:

    Quartz是一个开放源码项目,专注于任务调度器,提供了极为广泛的特性如持久化任务,集群和分布式任务等。 Quartz核心是调度器,还采用多线程管理。 

    1.持久化任务:当应用程序停止运行时,所有调度信息不被丢失,当你重新启动时,调度信息还存在,这就是持久化任务。 

    2.集群和分布式处理:当在集群环境下,当有配置Quartz的多个客户端时(节点),采用Quartz的集群和分布式处理时,我们要了解几点好处

     1) 一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。

    2) Quartz调度是通过触发器的类别来识别不同的任务,在不同的节点定义相同的触发器的类别,这样在集群下能稳定的运行,一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。

    3)分布式 体现在 当相同的任务定时在一个时间点,在那个时间点,不会被两个节点同时执行。 

     Quartz的 Task(11 张表)实例化采用数据库存储,基于数据库引擎及 High-Available 的策略(集群的一种策略)自动协调每个节点的 Quartz。  

    delete from qrtz_fired_triggers;  
    delete from qrtz_simple_triggers;  
    delete from qrtz_simprop_triggers;  
    delete from qrtz_cron_triggers;  
    delete from qrtz_blob_triggers;  
    delete from qrtz_triggers;  
    delete from qrtz_job_details;  
    delete from qrtz_calendars;  
    delete from qrtz_paused_trigger_grps;  
    delete from qrtz_locks;  
    delete from qrtz_scheduler_state;  
       
       
       
    CREATE TABLE qrtz_job_details  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        JOB_NAME  VARCHAR2(200) NOT NULL,  
        JOB_GROUP VARCHAR2(200) NOT NULL,  
        DESCRIPTION VARCHAR2(250) NULL,  
        JOB_CLASS_NAME   VARCHAR2(250) NOT NULL,   
        IS_DURABLE VARCHAR2(1) NOT NULL,  
        IS_NONCONCURRENT VARCHAR2(1) NOT NULL,  
        IS_UPDATE_DATA VARCHAR2(1) NOT NULL,  
        REQUESTS_RECOVERY VARCHAR2(1) NOT NULL,  
        JOB_DATA BLOB NULL,  
        CONSTRAINT QRTZ_JOB_DETAILS_PK PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)  
    );  
    CREATE TABLE qrtz_triggers  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        TRIGGER_NAME VARCHAR2(200) NOT NULL,  
        TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
        JOB_NAME  VARCHAR2(200) NOT NULL,   
        JOB_GROUP VARCHAR2(200) NOT NULL,  
        DESCRIPTION VARCHAR2(250) NULL,  
        NEXT_FIRE_TIME NUMBER(13) NULL,  
        PREV_FIRE_TIME NUMBER(13) NULL,  
        PRIORITY NUMBER(13) NULL,  
        TRIGGER_STATE VARCHAR2(16) NOT NULL,  
        TRIGGER_TYPE VARCHAR2(8) NOT NULL,  
        START_TIME NUMBER(13) NOT NULL,  
        END_TIME NUMBER(13) NULL,  
        CALENDAR_NAME VARCHAR2(200) NULL,  
        MISFIRE_INSTR NUMBER(2) NULL,  
        JOB_DATA BLOB NULL,  
        CONSTRAINT QRTZ_TRIGGERS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
        CONSTRAINT QRTZ_TRIGGER_TO_JOBS_FK FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)   
          REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)   
    );  
    CREATE TABLE qrtz_simple_triggers  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        TRIGGER_NAME VARCHAR2(200) NOT NULL,  
        TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
        REPEAT_COUNT NUMBER(7) NOT NULL,  
        REPEAT_INTERVAL NUMBER(12) NOT NULL,  
        TIMES_TRIGGERED NUMBER(10) NOT NULL,  
        CONSTRAINT QRTZ_SIMPLE_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
        CONSTRAINT QRTZ_SIMPLE_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
    REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
    );  
    CREATE TABLE qrtz_cron_triggers  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        TRIGGER_NAME VARCHAR2(200) NOT NULL,  
        TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
        CRON_EXPRESSION VARCHAR2(120) NOT NULL,  
        TIME_ZONE_ID VARCHAR2(80),  
        CONSTRAINT QRTZ_CRON_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
        CONSTRAINT QRTZ_CRON_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
          REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
    );  
    CREATE TABLE qrtz_simprop_triggers  
      (            
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        TRIGGER_NAME VARCHAR2(200) NOT NULL,  
        TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
        STR_PROP_1 VARCHAR2(512) NULL,  
        STR_PROP_2 VARCHAR2(512) NULL,  
        STR_PROP_3 VARCHAR2(512) NULL,  
        INT_PROP_1 NUMBER(10) NULL,  
        INT_PROP_2 NUMBER(10) NULL,  
        LONG_PROP_1 NUMBER(13) NULL,  
        LONG_PROP_2 NUMBER(13) NULL,  
        DEC_PROP_1 NUMERIC(13,4) NULL,  
        DEC_PROP_2 NUMERIC(13,4) NULL,  
        BOOL_PROP_1 VARCHAR2(1) NULL,  
        BOOL_PROP_2 VARCHAR2(1) NULL,  
        CONSTRAINT QRTZ_SIMPROP_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
        CONSTRAINT QRTZ_SIMPROP_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
          REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
    );  
    CREATE TABLE qrtz_blob_triggers  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        TRIGGER_NAME VARCHAR2(200) NOT NULL,  
        TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
        BLOB_DATA BLOB NULL,  
        CONSTRAINT QRTZ_BLOB_TRIG_PK PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),  
        CONSTRAINT QRTZ_BLOB_TRIG_TO_TRIG_FK FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)   
            REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)  
    );  
    CREATE TABLE qrtz_calendars  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        CALENDAR_NAME  VARCHAR2(200) NOT NULL,   
        CALENDAR BLOB NOT NULL,  
        CONSTRAINT QRTZ_CALENDARS_PK PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)  
    );  
    CREATE TABLE qrtz_paused_trigger_grps  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        TRIGGER_GROUP  VARCHAR2(200) NOT NULL,   
        CONSTRAINT QRTZ_PAUSED_TRIG_GRPS_PK PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)  
    );  
    CREATE TABLE qrtz_fired_triggers   
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        ENTRY_ID VARCHAR2(95) NOT NULL,  
        TRIGGER_NAME VARCHAR2(200) NOT NULL,  
        TRIGGER_GROUP VARCHAR2(200) NOT NULL,  
        INSTANCE_NAME VARCHAR2(200) NOT NULL,  
        FIRED_TIME NUMBER(13) NOT NULL,  
        SCHED_TIME NUMBER(13) NOT NULL,  
        PRIORITY NUMBER(13) NOT NULL,  
        STATE VARCHAR2(16) NOT NULL,  
        JOB_NAME VARCHAR2(200) NULL,  
        JOB_GROUP VARCHAR2(200) NULL,  
        IS_NONCONCURRENT VARCHAR2(1) NULL,  
        REQUESTS_RECOVERY VARCHAR2(1) NULL,  
        CONSTRAINT QRTZ_FIRED_TRIGGER_PK PRIMARY KEY (SCHED_NAME,ENTRY_ID)  
    );  
    CREATE TABLE qrtz_scheduler_state   
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        INSTANCE_NAME VARCHAR2(200) NOT NULL,  
        LAST_CHECKIN_TIME NUMBER(13) NOT NULL,  
        CHECKIN_INTERVAL NUMBER(13) NOT NULL,  
        CONSTRAINT QRTZ_SCHEDULER_STATE_PK PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)  
    );  
    CREATE TABLE qrtz_locks  
      (  
        SCHED_NAME VARCHAR2(120) NOT NULL,  
        LOCK_NAME  VARCHAR2(40) NOT NULL,   
        CONSTRAINT QRTZ_LOCKS_PK PRIMARY KEY (SCHED_NAME,LOCK_NAME)  
    );  
       
    create index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);  
    create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);  
       
    create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);  
    create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);  
    create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);  
    create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);  
    create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);  
    create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
    create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
    create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);  
    create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);  
    create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);  
    create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);  
    create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);  
       
    create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);  
    create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);  
    create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);  
    create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);  
    create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);  
    create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);
    View Code

    我在新建一个张表,为了方便页面能对每个任务进行管理,能对具体某个任务设置开始时间、结束时间、执行的方法、删除等, 如下面图所示: 

     在这边可以管理开始时间和结束时间和cronExpression值,方便管理对应表的设计: 

      

    表都设计好了,整理Quartz集成springMVC的具体的实现。

    spring的@component 的说明:@component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>) 

    1.举例两个任务具体实现功能,列如quartzJobA和quartzJobB任务要做什么,新建了两个类和方法。  

    import org.springframework.stereotype.Component;    
    @Component("quartzJobA")  
    public class Data2ServiceImpl {    
        public void run() {  
            System.out.println("=============Data2ServiceImpl=========");            
        }  
    }    
    @Component("quartzJobB")  
    public class DataServiceImpl {      
        public void test() {  
            System.out.println("=============DataServiceImpl=========");            
        }    
    }  

      2.Quartz 调度任务所需的配置文件 quartz-job.properties

      

    #Main Scheduler Settings  
    org.quartz.scheduler.instanceName=quartzScheduler    
    org.quartz.scheduler.instanceId=AUTO  
    org.quartz.scheduler.threadsInheritContextClassLoaderOfInitializer=true  
    org.quartz.scheduler.skipUpdateCheck=true  
    org.quartz.scheduler.batchTriggerAcquisitionMaxCount=100  
      
    org.quartz.threadPool.threadCount=10  
      
    #Configure JDBC-JobStoreTX  
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX  
    org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate  
    org.quartz.jobStore.dataSource=myDS  
    org.quartz.jobStore.tablePrefix=QRTZ_  
    org.quartz.jobStore.isClustered=true  
    org.quartz.jobStore.acquireTriggersWithinLock=true  
    org.quartz.jobStore.clusterCheckinInterval = 30000  
      
    #Configure DataSources  
    org.quartz.dataSource.myDS.driver=com.alibaba.druid.proxy.DruidDriver  
    org.quartz.dataSource.myDS.URL=jdbc:wrap-jdbc:filters=default:name=dragoon:jdbc:oracle:thin:@127.0.0.1:1521:test  
    org.quartz.dataSource.myDS.user=  
    org.quartz.dataSource.myDS.password=  
    org.quartz.dataSource.myDS.maxConnections=5  
    org.quartz.dataSource.myDS.validationQuery=select 1 from dual  

    org.quartz.scheduler.instanceName 属性可为任何值,用在 JDBC JobStore 中来唯一标识实例,但是所有集群节点中必须相同 

    org.quartz.jobStore.class属性为 JobStoreTX,将任务持久化到数据中。因为集群中节点依赖于数据库来传播 Scheduler 实例的状态,你只能在使用 JDBC JobStore 时应用 Quartz 集群。这意味着你必须使用 JobStoreTX 或是 JobStoreCMT 作为 Job 存储;你不能在集群中使用 RAMJobStore

    3.实现任务的创建和管理

    @Component("schedulerHelper")  
    public class SchedulerHelper  
    {  
      
        private static final String CONFIG_FILE="quartz-job.properties";  
        private static final String IDENTITY_JOB_PREFIX="job_";  
        private static final String IDENTITY_TRIGGER_PREFIX="trigger_";  
              
           @Autowired  
        private JobService jobService;//jobService 这个服务是实现管理任务的页面的服务实现  
        private Scheduler scheduler;  
          
          
      
        @Autowired  
        private StartJobSchedulerListener startJobSchedulerListener;//实现自己的Scheduler监听器,程序启动时,任务没创建时就创建  
      
          
          
          
           /** 
         * tomcat一启动时,类实例化时就执行 
         */  
        public void  init()  
        {  
            try{  
                   
                 // 创建一个定时器工厂  
                StdSchedulerFactory sf = new StdSchedulerFactory();  
                            //初始化quartz-job.properties配置文件  
                sf.initialize(Thread.currentThread().getContextClassLoader().getResource(CONFIG_FILE).getFile());  
                scheduler = sf.getScheduler();  
                //把jobService放到scheduler上下文,job执行是可以获取并访问。  
                scheduler.getContext().put(SCHEDULER_KEY_JOBSERVICE,jobService);  
                startJobSchedulerListener.setSchedulerHelper(this);  
                             //设置自己的监听器  
                scheduler.getListenerManager().addSchedulerListener(startJobSchedulerListener);  
                           // 启动定时器  
                scheduler.start();  
                logger.info("====================job scheduler start");           
            }catch(SchedulerException e){  
                logger.error("error",e);              
            }  
              
        }  
          
              
             /** 
         * 根据jobentity创建并开始任务 
         */  
       public boolean createAndStartJob(JobEntity job)  
        {  
            JobDetail jobDetail=generateJobDetail(job);  
            Trigger trigger=generateTriggerBuilder(job).build();  
              
            try {  
                scheduler.scheduleJob(jobDetail, trigger);  
                return true;  
            } catch (SchedulerException e) {  
                logger.error("scheduler.scheduleJob",e);  
                return false;  
            }  
        }  
            /** 
         * 清除 
         */  
        public void clearAllScheduler()  
        {  
            try {  
                scheduler.clear();  
            } catch (SchedulerException e) {  
                logger.error("clearAllScheduler",e);  
            }  
        }  
          
              
             /** 
         * 根据jobId和类型删除 
         */  
        public boolean removeJob(Long jobId,String jobType)   
        {  
            try {  
                scheduler.deleteJob(getJobKey(jobId,jobType));  
                return true;  
            } catch (SchedulerException e) {  
                logger.error("removeJob",e);  
                return false;  
            }         
        }  
              
             /** 
         * 暂停任务 
         */  
        public boolean pauseJob(Long jobId,String jobType)  
        {  
            try {  
                scheduler.pauseJob(getJobKey(jobId,jobType));  
                return true;  
            } catch (SchedulerException e) {  
                logger.error("resumeJob",e);  
                return false;  
            }  
        }  
           
            /** 
         * 马上只执行一次任务 
         */  
        public boolean executeOneceJob(Long jobId,String jobType)  
        {  
            try {  
                Calendar end=Calendar.getInstance();              
                TriggerBuilder<SimpleTrigger> simpleTriggerBuilder=TriggerBuilder.newTrigger()  
                                                    .withIdentity(getTriggerKey(jobId,jobType))  
                                                    .forJob(getJobKey(jobId,jobType))  
                                                    .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(2));  
                end.add(Calendar.SECOND, 2);  
                simpleTriggerBuilder.startAt(end.getTime());  
                end.add(Calendar.SECOND, 5);  
                simpleTriggerBuilder.endAt(end.getTime());  
                JobEntity job=jobService.getJobById(jobId);  
                  
                JobDataMap jobDataMap=new JobDataMap();  
                jobDataMap.put("jobEntity", job);  
                simpleTriggerBuilder.usingJobData(jobDataMap);  
                Trigger trigger=simpleTriggerBuilder.build();  
                  
                scheduler.scheduleJob(trigger);  
                return true;  
            } catch (SchedulerException e) {  
                logger.error("executeOneceJob",e);  
                return false;  
            }  
        }  
            /** 
         * 启动一些scheduler里没有的active的jobDetail 
         */  
        public void createActiveJobFromDB() throws SchedulerException  
        {  
            List<JobEntity> jobs=jobService.getActiveJob();  
            for(JobEntity job:jobs)  
            {  
                if(scheduler.getJobDetail(getJobKey(job))==null)  
                    createAndStartJob(job);  
            }  
        }  
              
           /** 
         * 获得任务的jobKey 
         */  
        public static JobKey getJobKey(Long jobId,String jobType)  
        {  
            return new JobKey(IDENTITY_JOB_PREFIX+jobId,IDENTITY_JOB_PREFIX+jobType);  
        }  
          
          /** 
         * 获得任务的jobKey 
         */  
      
        public static JobKey getJobKey(JobEntity job)  
        {  
            return new JobKey(IDENTITY_JOB_PREFIX+job.getJobId(),IDENTITY_JOB_PREFIX+job.getJobType());  
        }  
          
        /** 
         * 获得trigger的triggerkey 
         */  
        public static TriggerKey getTriggerKey(JobEntity job)  
        {  
            return new TriggerKey(IDENTITY_TRIGGER_PREFIX+job.getJobId()+"_"+System.currentTimeMillis(), IDENTITY_TRIGGER_PREFIX+job.getJobType());  
        }  
          
      
            /** 
         * 获得trigger的triggerkey 
         */  
        public static TriggerKey getTriggerKey(Long jobId,String jobType)  
        {  
            return new TriggerKey(IDENTITY_TRIGGER_PREFIX+jobId+"_"+System.currentTimeMillis(), IDENTITY_TRIGGER_PREFIX+jobType);  
        }  
          
        public static JobDetail generateJobDetail(JobEntity job)  
        {  
            JobDataMap jobDataMap=new JobDataMap();  
            jobDataMap.put("jobEntity", job);  
            Class<? extends Job> clazz=null;  
             clazz=BeanJob.class;  
            return JobBuilder.newJob(clazz)  
                            .withIdentity(getJobKey(job))  
                            .usingJobData(jobDataMap)  
                            .requestRecovery(true).storeDurably(true)  
                            .build();  
        }  
          
          
           /** 
         * 根据jobEntity获得trigger 
         */  
      
        public static TriggerBuilder<CronTrigger> generateTriggerBuilder(JobEntity job)  
        {  
            TriggerBuilder<CronTrigger> triggerBuilder= TriggerBuilder.newTrigger()  
                    .withIdentity(getTriggerKey(job))  
                    .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpr())  
                                                    .withMisfireHandlingInstructionDoNothing());  
            if(job.getSyncBeginTime()!=null)  
                triggerBuilder.startAt(job.getSyncBeginTime());  
            else  
                triggerBuilder.startNow();  
              
            if(job.getSyncEndTime()!=null)  
                triggerBuilder.endAt(job.getSyncEndTime());  
          
            return triggerBuilder;  
        }  
          
        public static JobService getJobService(JobExecutionContext context)  
        {  
            try {  
                return (JobService) context.getScheduler().getContext().get(SchedulerHelper.SCHEDULER_KEY_JOBSERVICE);  
            } catch (SchedulerException e) {  
                logger.error("SchedulerHelper.getJobService",e);  
                return null;  
            }  
        }  

    4.实现自己的Scheduler监听器,程序启动时,创建scheduler里没有的active的jobDetail

       

    @Component(value="startJobSchedulerListener")  
    public class StartJobSchedulerListener extends SchedulerListenerSupport   
    {  
        private SchedulerHelper schedulerHelper;  
          
        @Override  
        public void schedulerStarted()  
        {  
            try {  
                schedulerHelper.createActiveJobFromDB();  
            } catch (SchedulerException e) {  
                logger.error("createActiveJobFromDB",e);  
            }  
        }    
        public SchedulerHelper getSchedulerHelper() {  
            return schedulerHelper;  
        }    
        public void setSchedulerHelper(SchedulerHelper schedulerHelper) {  
            this.schedulerHelper = schedulerHelper;  
        }               
    } 

    5.实现的是一个job实例对应一个线程并实现页面配置对应的哪个类和方法

    public abstract class AbstractEdiJob implements Job   
    {  
        protected JobEntity jobEntity;   
        protected static final Logger logger=LoggerFactory.getLogger(AbstractEdiJob.class);  
        private Long beginTime;  
              
        @Override  
        public void execute(JobExecutionContext context) throws JobExecutionException   
        {  
            JobService jobService=SchedulerHelper.getJobService(context);  
            preExcute(jobService,context);  
            exeucuteInternal(context);  
            postExcute(jobService,context);  
        }  
          
        abstract public void exeucuteInternal(JobExecutionContext context);  
          
        public void preExcute(JobService jobService,JobExecutionContext context)  
        {  
            beginTime=System.currentTimeMillis();  
        }  
          
        public void postExcute(JobService jobService,JobExecutionContext context)  
        {  
            //获得最新的jobEntiry  
            jobEntity=jobService.getJobById(jobEntity.getJobId());  
            if(jobEntity==null)  
            {  
                logger.warn(jobEntity.getJobId()+"job不能存在");  
                return;  
            }  
            if(context.getFireTime()!=null)  
                jobEntity.setRuntimeLast(context.getFireTime());  
            if(context.getNextFireTime()!=null)  
                jobEntity.setRuntimeNext(context.getNextFireTime());  
        /*  else 
                jobEntity.setJobStatus();*/  
            Long times=jobEntity.getRunTimes();  
            jobEntity.setRunTimes((times==null?0l:times)+1);  
            Long duration=jobEntity.getRunDuration();  
            jobEntity.setRunDuration((duration==null?0l:duration)+(System.currentTimeMillis()-beginTime));  
            jobService.updateJob(jobEntity);  
            //jobEntity这里的改变不能改变JobDetail里的JobEntity,因为生产的job是JobDetail的JobEntity的复制  
        }   
        public void setJobEntity(JobEntity jobEntity) {  
            this.jobEntity = jobEntity;  
        }   
    }  
    /** 
     *执行具体类中的方法 
     **/  
    public class BeanJob extends AbstractEdiJob   
    {  
        private static Logger logger=LoggerFactory.getLogger(BeanJob.class);  
        @Override  
        public void exeucuteInternal(JobExecutionContext context)   
        {  
            Object obj=SpringContextUtil.getBean(jobEntity.getJobObject());  
            try {  
                Method method=obj.getClass().getMethod(jobEntity.getJobMethod());  
                method.invoke(obj);  
            } catch (SecurityException e) {  
                logger.error("error",e);  
            } catch (NoSuchMethodException e) {  
                logger.error("error",e);  
            } catch (IllegalArgumentException e) {  
                logger.error("error",e);  
            } catch (IllegalAccessException e) {  
                logger.error("error",e);  
            } catch (InvocationTargetException e) {  
                logger.error("error",e);  
            }  
        }  
      
    }  

    6.新增一个任务时,数据库就保存对应的触发器,变成持久化任务,如图所示:

      

        1.用StdSchedulerFactory来获取Scheduler的实例,scheduler有启动(start)、中止(stop)和暂停(pause)方法。
        2.JobDataMap实例,JobDataMap jobDataMap=new JobDataMap();jobDataMap.put("jobEntity", job);在同一任务的多次执行之间传递数据
        3.创建JobDetail实例。JobBuilder.newJob(clazz).withIdentity(getJobKey(job)).usingJobData(jobDataMap).requestRecovery(true).storeDurably(true).build();返回JobDetail实例,newJob(clazz)是要执行特定任务的类;withIdentity(getJobKey(job))是job的任务名和组名;usingJobDatausingJobData(jobDataMap)传输数据;

        4.创建Trigger实例。TriggerBuilder<CronTrigger> triggerBuilder= TriggerBuilder.newTrigger()
                                                                                                     .withIdentity(getTriggerKey(job))
                                                                                         .withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpr())
                          .withMisfireHandlingInstructionDoNothing());

       withIdentity有标示了触发器的名称和组(Quartz调度是通过触发器的类别来识别不同的任务),和withSchedule标示执行的时间表达式 

        5.最后通过scheduler.scheduleJob()方法调度任务。    

     参考:Quartz集成springMVC 的方案二(持久化任务、集群和分布式)

  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/aspirant/p/6814211.html
Copyright © 2011-2022 走看看