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);
我在新建一个张表,为了方便页面能对每个任务进行管理,能对具体某个任务设置开始时间、结束时间、执行的方法、删除等, 如下面图所示:
在这边可以管理开始时间和结束时间和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()方法调度任务。
相关推荐
该项目为基于Java语言的蓝牙遥控器设计源码,包含539个文件,涵盖307个Java源文件、120个XML配置文件、34个PNG图片文件、16个Gradle构建文件、12个Git忽略文件、9个文本文件、6个JAR包文件、5个JSON配置文件、5个JPG图片文件。该遥控器支持键盘、鼠标和影音控制功能,适用于多种场合。
数据手册-74HC573-datasheet.zip
那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
关于C++的资源描述和项目源码,以下是一些关键信息: 资源描述 C++是一种广泛应用于开发高性能应用程序的编程语言,既有高级语言的特性,也有低级语言的效率。以下是C++学习资源的简要描述: 在线课程:如优达学城提供的C++中级课程,以及北京大学提供的C++程序设计和C++程序设计进阶课程,这些课程适合从零开始系统学习C++,涵盖从基础到高级的编程内容。 书籍:如《C++ Primer》、《Effective C++》和《C++标准库》等,这些书籍详细介绍了C++语言的基本概念和编程技术,适合作为自学或课堂教学的参考资料。 在线社区:如CSDN博客和Stack Overflow等,这些社区提供了丰富的C++编程教程、示例代码和问题解决方案,是学习和交流C++编程技术的重要平台。 开发工具:如Visual C++(VC)等集成开发环境(IDE),提供了编译器、调试器和其他工具,方便开发者进行Windows平台上的C++应用程序开发。 项目源码 由于项目源码通常包含大量的代码文件和资源文件,且涉及版权和知识产权问题,因此无法在此直接提供完整的项目源码。不过,以下是一些获取C++项目源码的
锻压成型机_三维3D设计图纸.zip
mmexport1728042361260.mp4
谷歌浏览器Linux版本google-chrome-stable-current-amd64.deb
那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
该项目是一款基于Python编写的运输车辆风险预估算法设计源码,包含20个文件,其中9个为Python源代码文件,5个为XML配置文件,2个为Git忽略文件,2个为Excel工作簿文件,以及其余文件类型各1个。该系统旨在通过GPS定位数据对运输车辆的风险进行有效预估,为运输安全管理提供技术支持。
本项目是一款瑞吉外卖点餐系统,采用HTML/CSS/JavaScript进行开发,并集成了Java后端支持。整个项目源码共包含196个文件,其中Java文件73个,PNG图片文件43个,JavaScript文件22个,HTML文件21个,CSS文件18个,字体文件6个,图标文件2个,JSON文件2个以及其他格式文件。该系统旨在提供流畅的点餐体验,满足用户在线点餐需求。
那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
该项目为基于Java语言的BasketBallDemo约战篮球设计源码,包含488个文件,其中包含433个PNG图片文件、23个XML配置文件、13个Java源文件、9个JPG图片文件、5个aar库文件、1个Markdown文档、1个Git忽略文件、1个Gradle构建文件、1个批处理文件和1个属性文件。该系统专注于篮球爱好者的约战管理功能。
那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
buck双闭环控制仿真降压电路PI调节器设计降压斩波电路建模和数学模型建模 建模方法有状态空间平均法,开关元件平均模型法,开关网络平均模型法提供双闭环调节器设计方案 从滤波器设计到pi调节器设计再到仿真。 从滤波器设计到建模,得到被控对象的传递函数,再根据传递函数设计pi调节器,最后把计算出来的pi参数带入仿真验证。
该项目是一款基于Java语言开发的掌上英雄联盟能力分析效果模拟应用,源码包含44个文件,涵盖9个XML配置文件、8个Java源文件、6个JSON配置文件、4个Gradle构建文件、3个Git忽略文件、3个属性文件以及其他相关文件,旨在重现英雄联盟能力分析的用户界面和交互体验。
那些年,与你同分同位次的同学都去了哪里?全国各大学在辽宁2020-2024年各专业最低录取分数及录取位次数据,高考志愿必备参考数据
该项目是一款基于Java语言的Android智能家居系统设计源码,共计75个文件,其中包含24个XML配置文件、17个Java源文件、11个PNG图片文件、10个JPG图片文件、3个Git忽略文件、3个Gradle构建文件、2个属性文件以及1个LICENSE文件。该系统设计简单实用,适用于智能家居场景。
系统级电路 10 100Mbps 10BASE-T ETHERENT-PHY以太网 cadence官方教程和文件,足够专业 有电路,有工艺库,有版图 有两个版本,一份是工艺是Gpdk90nm(主要),一份是Gpdk180nm,都是有版图(TOP,cell都有),Cadence自己家的电路 如图,保姆级操作教程,从导入库启动cadence开始的那种 内容: 有两个锁相环,模拟均衡器eq pi相位差值 flash ADC,带triming bg LDO,比较器 电平移位,译码电路 数字电路,偏置电流源 运放,trans DAC,滤波器 有很多仿真tb,非常的详细 两个子模块PLL仿真,ADC仿真,bg ldo 模块仿真,TOP整体ams仿真,有版图,没流片,不是反向电路。 有几份RAK讲解文件,有讲top的,然后有几份pdf是讲里面的子模块的。
棉花自动灌装缝纫机_三维3D设计图纸.zip