• 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 的方案二(持久化任务、集群和分布式)

  • 相关阅读:
    长沙Uber司机奖励政策(8月24日到8月30日)
    苏州Uber优步司机奖励政策(8月31日至9月6日)
    武汉Uber优步司机奖励政策(8月31日~9月6日)
    青岛Uber司机奖励政策(8月31号~9月6号)
    成都Uber优步司机奖励政策(8月31日~9月6日)
    成都UBER优步司机第六组奖励政策
    敏捷软件开发--敏捷开发原则
    UML--对象的介绍
    ip 子网掩码 网关 DNS
    敏捷软件开发--计划
  • 原文地址:https://www.cnblogs.com/aspirant/p/6814211.html
Copyright © 2020-2023  润新知