最近公司应用quartz,自己就看了下,做了个小demo
springboot整合quartz核心的依赖如下。这个依赖会自动包括spring-context-support包和quartz包(如果用的吧㐊springboot那么就需要导入这两个包)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-quartzartifactId>
dependency>
quartz的配置属性请参考quartz配置
配置参数有两种方法,一种是用额外的配置文件配置,然后在配置代码里面导入。
另一种直接在java代码中用工厂设置。这里我用的是直接java代码配置
工厂配置代码如下
@Bean
public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource,MyAdaptableJobFactory myAdaptableJobFactory) {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setDataSource(dataSource);
// quartz参数
Properties prop = new Properties();
prop.put("org.quartz.scheduler.instanceName", "MyScheduler");//设置调度器的名字
prop.put("org.quartz.scheduler.instanceId", "AUTO");
// 线程池配置
prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");//线程池的名字
//prop.put("org.quartz.threadPool.threadCount", "20");//线程数量默认25
//prop.put("org.quartz.threadPool.threadPriority", "5");//优先级默认是5
// JobStore配置
prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");//持久化到数据库
// // 集群配置
prop.put("org.quartz.jobStore.isClustered", "true");
prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
prop.put("org.quartz.jobStore.misfireThreshold", "6000");//
prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
bean.setQuartzProperties(prop);
bean.setWaitForJobsToCompleteOnShutdown(true);
// 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
bean.setOverwriteExistingJobs(true);
// 设置自动启动,默认为true
bean.setAutoStartup(true);
bean.setJobFactory(myAdaptableJobFactory);
return bean;
}
@Bean()
public Scheduler scheduler(SchedulerFactoryBean bean) {
return bean.getScheduler();
}
job即定时任务,job中可能会注入service对象,为了防止service注入为空,一般有两种方法
第一种是创建job类并且继承QuartzJobBean类
@Component
public class MyJob extends QuartzJobBean {
@Autowired
QuartzService qs;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
qs.excuteJob();
}
}
这个方法在使用的时候需要通过jobfactory来进行实例化,所以需要给SchedulerFactory设置这个JobFactory.(根据QuartzJobBean文档)而spring帮我们实现了这个JobFactory
实现类为AdaptableJobFactory,我们只需要继承这个类即可
具体写法参考网上很容易找到的
@Component
public class MyAdaptableJobFactory extends AdaptableJobFactory {
@Autowired
private AutowireCapableBeanFactory autowireCapableBeanFactory;
// 该方法需要将实例化的任务对象手动的添加到springIOC容器中并且完成对象的注入
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
Object obj = super.createJobInstance(bundle);
// 将obj对象添加Spring IOC容器中,并完成注入
this.autowireCapableBeanFactory.autowireBean(obj);
return obj;
}
}
新发现
spring有一个SpringBeanJobFactory直接继承了AdaptableJobFactory ,在配置文件中配置好就可以用,效果和上面自己创建的一样。
@Service
public class QuartzService{
public void excuteJob() {
System.out.println("My!!!!!job正在执行"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()));
}
}
**优点:**因为继承了quartzjobbean,所以可以使用jobdatamap传参给job。
比如说不想写太多job类只想用一个job类实现所有的任务,那么可以通过传参的方式,把需要添加的任务名传进去,然后job里进行判断。
第二种方法是用MethodInvokingJobDetailFactoryBean配置
但是不可行(求指教)
个人分析:因为其中的jobdatamap不可序列化而报错
org.springframework.scheduling.quartz包下没有序列化的jobdetailfactorybean类。
添加任务代码如下
JobKey j1 = new JobKey("job3", "group");
JobDataMap map = new JobDataMap();//可以用来传参
//map.put("job", "job3");
JobDetail jobBuild = JobBuilder.newJob(MyJob.class).setJobData(map).withIdentity(j1).build();
TriggerKey tk1 = new TriggerKey("job3", "group");
CronTrigger c = TriggerBuilder.newTrigger().startAt(new Date()).withIdentity(tk1).withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();
scheduler.scheduleJob(jobBuild, c);//添加任务后自动执行。