首先我要记录两种quartz集成的方式
第一种是只有一个任务,定时执行即可,不需要动态管理
第二种是通过程序去控制定时任务的管理
不管哪种,首先导入依赖
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.3</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency>
然后第一种很简单
首先创建配置类
package com.hqjl.classcard.quartz; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.quartz.CronTriggerFactoryBean; import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean; import org.springframework.scheduling.quartz.SchedulerFactoryBean; /** * @author chunying * @Date: 2018/11/13 0013 */ public class WechatConfiguration { @Bean(name = "detailFactoryBean_") //参数是执行定时任务的类 public MethodInvokingJobDetailFactoryBean detailFactoryBean(AddSendMessageConfig wechatQuartz) { MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean(); //对应job对象 bean.setTargetObject(wechatQuartz); //设置对应执行方法 bean.setTargetMethod("refresh"); bean.setConcurrent(false); return bean; } @Bean(name = "cronTriggerBean_") public CronTriggerFactoryBean cronTriggerBean(MethodInvokingJobDetailFactoryBean detailFactoryBean_){ CronTriggerFactoryBean trigger = new CronTriggerFactoryBean (); trigger.setJobDetail(detailFactoryBean_.getObject()); try { trigger.setCronExpression("0 0 2 * * ?"); // trigger.setCronExpression ("0/5 * * ? * *");//每5秒执行一次 }catch(Exception e) { throw new RuntimeException("定时刷新数据出错----------------------------------------------" + e); } return trigger; } @Bean public SchedulerFactoryBean schedulerFactory(CronTriggerFactoryBean cronTriggerBean_){ SchedulerFactoryBean schedulerFactory = new SchedulerFactoryBean (); schedulerFactory.setTriggers(cronTriggerBean_.getObject()); return schedulerFactory; } }
这里有三个方法,
第一个配置MethodInvokingJobDetailFactoryBean 这里要传入我们job对象,也就是要执行任务的对象
第二个配置CronTriggerFactoryBean 这里要配置cron表达式 来控制job什么时候执行 传入上面的MethodInvokingJobDetailFactoryBean
第三个配置SchedulerFactoryBean 调度器传入我们上面配置的CronTriggerFactoryBean
这里的job对象我就不创建了 有一个AddSendMessageConfig对象 有一个refresh 方法就可以了 方法里面就是具体的需要执行的定时业务逻辑
第二种:
首先定义一个定时任务管理者
package com.hqjl.classcard.quartz; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.util.HashMap; import java.util.Map; /** * @author chunying * @Date: 2018/11/12 0012 */ @Component @Scope("singleton") public class QuartzManager implements ApplicationContextAware { private static SchedulerFactory schedulerFactory = new StdSchedulerFactory(); private static final String JOB_DEFAULT_GROUP_NAME = "JOB_DEFAULT_GROUP_NAME"; private static final String TRIGGER_DEFAULT_GROUP_NAME = "TRIGGER_DEFAULT_GROUP_NAME"; private Log logger = LogFactory.getLog(QuartzManager.class); private ApplicationContext applicationContext; private static Scheduler scheduler; static { try { scheduler = schedulerFactory.getScheduler(); } catch (SchedulerException e) { e.printStackTrace(); } } ; @Autowired private AutowiringSpringBeanJobFactory autowiringSpringBeanJobFactory; public void start() { //启动所有任务 try { scheduler.setJobFactory(autowiringSpringBeanJobFactory); //启动所有任务,这里获取AbstractTask的所有子类 Map<String, AbsTractTask> tasks = applicationContext.getBeansOfType(AbsTractTask.class); tasks.forEach((k, v) -> { String cronExpression = v.getCronExpression(); if (cronExpression != null) { addJob(k, v.getClass().getName(), cronExpression , new HashMap()); } }); logger.info("start jobs finished."); } catch (SchedulerException e) { logger.error(e.getMessage(), e); throw new RuntimeException("init Scheduler failed"); } } public boolean addJob(String jobName, String jobClass, String cronExp, Map data) { boolean result = false; if (!CronExpression.isValidExpression(cronExp)) { return result; } try { JobDetail jobDetail = JobBuilder.newJob().withIdentity(new JobKey(jobName, JOB_DEFAULT_GROUP_NAME)) .ofType((Class<Job>) Class.forName(jobClass)) .build(); //这里进行外部向job里面传递参数 JobDataMap jobDataMap = jobDetail.getJobDataMap(); jobDataMap.putAll(data); Trigger trigger = TriggerBuilder.newTrigger() .forJob(jobDetail) .withSchedule(CronScheduleBuilder.cronSchedule(cronExp)) .withIdentity(new TriggerKey(jobName, TRIGGER_DEFAULT_GROUP_NAME)) .build(); scheduler.setJobFactory(autowiringSpringBeanJobFactory); scheduler.scheduleJob(jobDetail, trigger); scheduler.start(); } catch (Exception e) { logger.error(e.getMessage(), e); logger.error("QuartzManager add job failed"); } return result; } public boolean updateJob(String jobName, String cronExp) { boolean result = false; if (!CronExpression.isValidExpression(cronExp)) { return result; } JobKey jobKey = new JobKey(jobName, JOB_DEFAULT_GROUP_NAME); TriggerKey triggerKey = new TriggerKey(jobName, TRIGGER_DEFAULT_GROUP_NAME); try { if (scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) { JobDetail jobDetail = scheduler.getJobDetail(jobKey); Trigger newTrigger = TriggerBuilder.newTrigger() .forJob(jobDetail) .withSchedule(CronScheduleBuilder.cronSchedule(cronExp)) .withIdentity(new TriggerKey(jobName, TRIGGER_DEFAULT_GROUP_NAME)) .build(); scheduler.rescheduleJob(triggerKey, newTrigger); result = true; } else { } } catch (SchedulerException e) { logger.error(e.getMessage(), e); } return result; } public boolean deleteJob(String jobName) { boolean result = false; JobKey jobKey = new JobKey(jobName, JOB_DEFAULT_GROUP_NAME); try { if (scheduler.checkExists(jobKey)) { result = scheduler.deleteJob(jobKey); } else { } } catch (SchedulerException e) { logger.error(e.getMessage(), e); } return result; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
这里面用到了一个自定义的AutowiringSpringBeanJobFactory 说一下这个类,quartz在启动定时任务的时候,是自己新开启一个线程的,里面的对象是类似一个jobContext来管理的,所以如果job的具体实现需要用到我们的业务对象,会发现用spring注入为空,所以需要把quartz的job对象放到spring容器里进行管理。
package com.hqjl.classcard.quartz; import org.quartz.spi.TriggerFiredBundle; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.scheduling.quartz.SpringBeanJobFactory; import org.springframework.stereotype.Service; /** * @author chunying * @Date: 2018/11/12 0012 */ @Service public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware { private transient AutowireCapableBeanFactory beanFactory; @Override public void setApplicationContext(final ApplicationContext context) { beanFactory = context.getAutowireCapableBeanFactory(); } @Override protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception { final Object job = super.createJobInstance(bundle); beanFactory.autowireBean(job); return job; } }
之后的就很简单的 定义一个抽象类实现job
package com.hqjl.classcard.quartz; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.springframework.stereotype.Component; import java.text.ParseException; /** * @author chunying * @Date: 2018/11/12 0012 */ public abstract class AbsTractTask implements Job { protected abstract void executeInternal(JobExecutionContext context) throws ParseException; protected String cronExpression; @Override public void execute(JobExecutionContext context) { try { executeInternal(context); } catch (Exception e) { e.printStackTrace(); } } public String getCronExpression() { return cronExpression; } }
我们定义的job对象来继承这个类
package com.hqjl.classcard.quartz; import com.hqjl.classcard.bean.WechatData; import com.hqjl.classcard.bean.WechatQuartzMessage; import com.hqjl.classcard.bean.response.AdminClassCheck; import com.hqjl.classcard.bean.response.ClassCheck; import com.hqjl.classcard.bean.response.SettingBean; import com.hqjl.classcard.dao.WechatQuartzMessageDao; import com.hqjl.classcard.data.check.DataResultService; import com.hqjl.classcard.data.check.SchoolData; import com.hqjl.classcard.service.CheckingInfoService; import com.hqjl.classcard.service.SettingService; import com.hqjl.classcard.service.StudentInfoService; import com.hqjl.classcard.utils.CronUtil; import com.hqjl.classcard.utils.DateUtil; import com.hqjl.common.framework.spring.SpringContextUtil; import com.hqjl.scheduler.bean.classcard.*; import com.hqjl.scheduler.classcard.IScheduleClassCardService; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.quartz.DisallowConcurrentExecution; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.stream.Collectors; /** * @author chunying */ @Component @Service @DisallowConcurrentExecution public class WechatQuartz extends AbsTractTask{ @Autowired private SendThread sendThread; @Autowired private CheckingInfoService checkingInfoService; @Autowired private StudentInfoService studentInfoService; @Autowired private QuartzManager quartzManager; @Autowired private WechatMessageConfig wechatMessageConfig; @Autowired private WechatQuartzMessageDao wechatQuartzMessageDao; @Autowired private IScheduleClassCardService iScheduleClassCardService; @Autowired private SettingService settingService; @Autowired private DataResultService dataResultService; public WechatQuartz(){}; private static final Log LOG = LogFactory.getLog(WechatQuartz.class); //具体job实现 @Override protected void executeInternal(JobExecutionContext context){ //这里可以拿到它进行job参数的传递 使用和map大体相同
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap(); } }