1、定时任务的两种实现方式
- 使用 Spring自带的定时任务处理器 @Scheduled 注解
- 另一种就是使用第三方框架 Quartz
2、使用@Scheduled
- 配置springboot
// 添加 @EnableScheduling 注解,开启定时任务
@SpringBootApplication
@EnableScheduling
public class ScheduledApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduledApplication.class, args);
}
}
- 配置定时任务
@Scheduled
注解开启一个定时任务;
fixedRate
表示任务执行之间的时间间隔,指两次任务的开始时间间隔;
fixedDelay
表示任务执行之间的时间间隔,指本次任务结束到下次任务开始之间的时间间隔;
//initialDelay 表示首次任务启动的延迟时间
@Scheduled(initialDelay = 2000,fixedDelay = 2000)
public void initialDelay() {
System.out.println("initialDelay>>>"+new Date());
}
3、使用Quartz
1.1 配置springboot
@SpringBootApplication
@EnableScheduling
public class QuartzApplication {
public static void main(String[] args) {
SpringApplication.run(QuartzApplication.class, args);
}
}
1、 定义job
一个是JobDetail(要做的事情)
一个是触发器(什么时候做)
public class MyJob2 extends QuartzJobBean {
HelloService helloService;
public HelloService getHelloService() {
return helloService;
}
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
helloService.sayHello();
}
}
public class HelloService {
public void sayHello() {
System.out.println("hello service >>>"+new Date());
}
}
2、 配置 JobDetail 和 Trigger 触发器
@Configuration
public class QuartzConfig {
//配置方式1
@Bean
MethodInvokingJobDetailFactoryBean methodInvokingJobDetailFactoryBean() {
MethodInvokingJobDetailFactoryBean bean = new MethodInvokingJobDetailFactoryBean();
bean.setTargetBeanName("myJob1");
bean.setTargetMethod("sayHello");
return bean;
}
//配置方式2
@Bean
JobDetailFactoryBean jobDetailFactoryBean() {
JobDetailFactoryBean bean = new JobDetailFactoryBean();
bean.setJobClass(MyJob2.class);
JobDataMap map = new JobDataMap();
map.put("helloService", helloService());
bean.setJobDataMap(map);
return bean;
}
//触发器SimpleTrigger用法
@Bean
SimpleTriggerFactoryBean simpleTriggerFactoryBean() {
SimpleTriggerFactoryBean bean = new SimpleTriggerFactoryBean();
bean.setStartTime(new Date());
bean.setRepeatCount(5);
bean.setJobDetail(methodInvokingJobDetailFactoryBean().getObject());
bean.setRepeatInterval(3000);
return bean;
}
//触发器CronTrigger用法
@Bean
CronTriggerFactoryBean cronTrigger() {
CronTriggerFactoryBean bean = new CronTriggerFactoryBean();
bean.setCronExpression("0/10 * * * * ?");
bean.setJobDetail(jobDetailFactoryBean().getObject());
return bean;
}
//类似于前面说的 @Scheduled 的基本用法
@Bean
SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean bean = new SchedulerFactoryBean();
bean.setTriggers(cronTrigger().getObject(), simpleTriggerFactoryBean().getObject());
return bean;
}
//类似于@Scheduled中cron表达式的用法
@Bean
HelloService helloService() {
return new HelloService();
}
}
1.2 quartz注入job问题解决
定时任务Job对象的实例化过程是在Quartz中进行的,而TaskCronJobService Bean是由Spring容器管理的,Quartz根本就察觉不到TaskCronJobService Bean的存在,故而无法将TaskCronJobService Bean装配到Job对象中。
1、配置Scheduler的工厂与调度器实例
@Configuration
public class QuartzConfig {
private JobFactory jobFactory;
public QuartzConfig(JobFactory jobFactory) {
this.jobFactory = jobFactory;
}
@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setJobFactory(jobFactory);
return factory;
}
@Bean(name = "scheduler")
public Scheduler scheduler() {
return schedulerFactoryBean().getScheduler();
}
}
2、将jobBean注入Spring容器
@Component
public class JobFactory extends AdaptableJobFactory {
// 需要使用这个BeanFactory对Qurartz创建好Job实例
// 进行后续处理,属于Spring的技术范畴.
private AutowireCapableBeanFactory beanFactory;
public JobFactory(AutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
// 调用父类的方法创建好Quartz所需的Job实例
Object job = super.createJobInstance(bundle);
// 使用BeanFactory为创建好的Job实例自动装配到Spring容器
beanFactory.autowireBean(job);
return job;
}
}
3、创建任务实例与定时类
@Component
public class QuartzManager {
private Scheduler scheduler;
public QuartzManager(Scheduler scheduler) {
this.scheduler = scheduler;
}
public void createJob(QuartzDTO quartzParams) {
// 格式化时间
String runTime = TimeFormatter.getCron(quartzParams.getTime());
// 1、创建JobDetail
JobDetail jobDetail = JobBuilder.newJob(quartzParams.getClazz())
.withIdentity(quartzParams.getJobName(), quartzParams.getJobGroupName()).build();
jobDetail.getJobDataMap().putAll(quartzParams.getParams());
// 2、创建Trigger
CronTrigger cronTrigger = TriggerBuilder.newTrigger()
// 根据作业名及作业组名生成触发器key
.withIdentity(quartzParams.getTriggerName(), quartzParams.getTriggerGroupName())
// 设置触发时间
.withSchedule(CronScheduleBuilder.cronSchedule(runTime))
.build();
try {
// 3、注册任务和定时器
scheduler.scheduleJob(jobDetail, cronTrigger);
// 4、调度器开启
if (!scheduler.isShutdown()) {
scheduler.start();
}
} catch (SchedulerException e) {
e.printStackTrace();
}
}
public void removeJob(QuartzDTO quartzParams) {
completeParams(quartzParams);
TriggerKey triggerKey =
TriggerKey.triggerKey(quartzParams.getTriggerName(), quartzParams.getTriggerGroupName());
JobKey jobKey = JobKey.jobKey(quartzParams.getJobName(), quartzParams.getJobGroupName());
try {
// 移除触发器
// 1. 停止
scheduler.pauseTrigger(triggerKey);
// 2. 移除
scheduler.unscheduleJob(triggerKey);
// 删除任务
scheduler.deleteJob(jobKey);
} catch (SchedulerException e) {
e.printStackTrace();
}
}
}
```java
public class QuartzDTO {
/**
* 作业名
*/
private String jobName;
/**
* 作业分组名
*/
private String jobGroupName;
/**
* 触发器名
*/
private String triggerName;
/**
* 触发器分组名
*/
private String triggerGroupName;
/**
* 作业类型
*/
private Class<? extends Job> clazz;
/**
* 执行时间
*/
private Timestamp time;
/**
* 参数
*/
private Map<String, Object> params;
}