Spring Boot 入门 - 进阶篇(3)- 定时任务(@Scheduled)

主要用于定时发送邮件、夜间自动维护等。

[b](1)开启定时任务功能[/b]
@Configuration
@EnableScheduling
public class SpringTaskScheduleConfig {
@Bean
public TaskScheduler poolScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize(10);
return scheduler;
}
}

*** Spring4只允许定义一个TaskScheduler。

[b](2)定义定时任务[/b]

[b]1)@Scheduled注解[/b]
@Scheduled(cron="*/5 * * * * MON-FRI")
public void doSomeTask(){
}

@Scheduled(fixedDelay = 2000)
public void fixedDelayJob() {
}

@Scheduled(fixedRate = 2000)
public void fixedRateJob() {
}

[list][*]Cron – 自由指定时间
[*]FixedRate – 开始后计时
[*]FixedDelay – 完成后计时[/list]

[b]2)实现SchedulingConfigurer[/b]
@Configuration
public class MySchedulingConfigurer implements SchedulingConfigurer {

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(poolScheduler());
// add job
taskRegistrar.addFixedRateTask(new IntervalTask(
new Runnable() {
@Override
public void run() {
System.out.println("Job @ fixed rate " + new Date() + ", Thread name is " + Thread.currentThread().getName());
}
},
1000, 0));
}

@Bean
public TaskScheduler poolScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize(10);
return scheduler;
}

}


[b]3)动态定义[/b]
TaskScheduler(ThreadPoolTaskScheduler)、Trigger(CronTrigger、PeriodicTrigger)。
ThreadPoolTaskScheduler scheduler = (ThreadPoolTaskScheduler) appContext.getBean("scheduler");
CronTrigger trigger = new CronTrigger("0 0/5 * * * ?"); // Every 5 minutes
ScheduledFuture<Object> scedulefuture = scheduler.schedule(taskObject, trigger);


[b](3)规则定义到配置文件[/b]

application.properties
[quote]cron.expression=0 0 0/1 * * ?
task.exec.time.delayed=5000[/quote]
@Scheduled(cron = "${cron.expression}")
public void demoServiceMethod() {
}

@Scheduled(fixedDelayString = "${task.exec.time.delayed}")
public void autoProcess() {
}


[b](4)集群下的定时任务[/b]

[b]1)通过AOP拦截限定定时任务的启动[/b]
多服务器的时候,不能所有服务器都同时执行定时任务,最简单的方法是只让特殊的服务才执行执行定时任务。

application.properties
[quote]batch.exec.host=192.168.1.100[/quote]
@Aspect
@Component
public class TaskInterceptor {
@Value(“${batch.exec.host}”) String batchExecHost;

@Around("execution(* com.rensanning.task..*.*(..)) && @annotation(org.springframework.scheduling.annotation.Scheduled)")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
String currentThread = Thread.currentThread().getName();
if (!allowedBatchExec()) {
log.info("Skip batch ({}): {}", currentThread, methodName);
return null;
}
log.info("Begin batch ({}): {}", currentThread, methodName);
Stopwatch stopWatch = Stopwatch.createStarted();
try {
return pjp.proceed();
} catch (Exception e) {
log.error("batch error: {}", methodName, e);
return null;
} finally {
log.info("End batch ({}): {}, elapsed = {} (ms)", currentThread, methodName,
stopWatch.elapsed(TimeUnit.MILLISECONDS));
}
}

private boolean allowedBatchExec() {
if (getHostName().equals(batchExecHost)) {
return true;
}
return false;
}
}


[b]2)集成Quartz Scheduler[/b]
Quartz的集群方案是基于数据库的,与Spring无缝对接。

[b]a)导入jar[/b]
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.2.3</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>2.2.3</version>
</dependency>


[b]b)将Quartz所需的表Schema导入数据库[/b]
从 http://www.quartz-scheduler.org/downloads/ 下载quartz-2.2.3-distribution.tar.gz后,quartz-2.2.3-distribution.tar.gz\quartz-2.2.3\docs\dbTables\ 里边有表结构定义DDL,大概11个表。

[b]c)配置Quartz[/b]
@Configuration
public class ConfigureQuartz {

@Bean
public SpringBeanJobFactory jobFactory(ApplicationContext applicationContext) {
AutoWiringSpringBeanJobFactory jobFactory = new AutoWiringSpringBeanJobFactory();
jobFactory.setApplicationContext(applicationContext);
return jobFactory;
}

@Bean
public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory,
@Qualifier("sampleJob1Trigger") Trigger trigger1,
@Qualifier("sampleJob2Trigger") Trigger trigger2) throws IOException {
SchedulerFactoryBean factory = new SchedulerFactoryBean();
factory.setOverwriteExistingJobs(true);
factory.setAutoStartup(true);
factory.setStartupDelay(20);
factory.setJobFactory(jobFactory);
factory.setQuartzProperties(quartzProperties());
factory.setTriggers(trigger1, trigger2);
return factory;
}

@Bean(name = "sampleJob1Detail")
public JobDetailFactoryBean sampleJob1Detail() {
return createJobDetail(SampleJob1.class);
}

@Bean(name = "sampleJob2Detail")
public JobDetailFactoryBean sampleJob2Detail() {
return createJobDetail(SampleJob2.class);
}

@Bean(name = "sampleJob1Trigger")
public CronTriggerFactoryBean sampleJob1Trigger(@Qualifier("sampleJob1Detail") JobDetail jobDetail,
@Value("${cron.job1.expression}") String job1CronExp) {
return createCronTrigger(jobDetail, job1CronExp);
}

@Bean(name = "sampleJob2Trigger")
public CronTriggerFactoryBean sampleJob2Trigger(@Qualifier("sampleJob2Detail") JobDetail jobDetail,
@Value("${cron.job2.expression}") String job2CronExp) {
return createCronTrigger(jobDetail, job2CronExp);
}

@Bean
public Properties quartzProperties() throws IOException {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("quartz.properties"));
propertiesFactoryBean.afterPropertiesSet();
return propertiesFactoryBean.getObject();
}

private JobDetailFactoryBean createJobDetail(Class<?> jobClass) {
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
factoryBean.setJobClass(jobClass);
factoryBean.setDurability(true);
return factoryBean;
}

private CronTriggerFactoryBean createCronTrigger(JobDetail jobDetail, String cronExpression) {
CronTriggerFactoryBean factoryBean = new CronTriggerFactoryBean();
factoryBean.setJobDetail(jobDetail);
factoryBean.setCronExpression(cronExpression);
factoryBean.setMisfireInstruction(SimpleTrigger.MISFIRE_INSTRUCTION_FIRE_NOW);
return factoryBean;
}

}

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;
}
}

quartz properties
[quote]org.quartz.scheduler.instanceName=ClusteredScheduler
org.quartz.scheduler.instanceId=AUTO
org.quartz.scheduler.makeSchedulerThreadDaemon=true
org.quartz.scheduler.skipUpdateCheck=true

org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.makeThreadsDaemons=true
org.quartz.threadPool.threadCount=20
org.quartz.threadPool.threadPriority=5

org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.tablePrefix=QRTZ_
org.quartz.jobStore.dataSource=myDS
org.quartz.jobStore.misfireThreshold=25000

org.quartz.jobStore.isClustered=true
org.quartz.jobStore.clusterCheckinInterval=20000

org.quartz.dataSource.myDS.driver=org.postgresql.Driver
org.quartz.dataSource.myDS.URL=jdbc:postgresql://localhost:5432/test
org.quartz.dataSource.myDS.user=postgres
org.quartz.dataSource.myDS.password=postgres
org.quartz.dataSource.myDS.maxConnections=5
org.quartz.dataSource.myDS.validationQuery=select 1
[/quote]
application.properties
[quote]cron.job1.expression=0 0/3 * * * ?
cron.job2.expression=0 0/5 * * * ?[/quote]

[b]c)定义Job[/b]

基于org.quartz.Job
@Component
@DisallowConcurrentExecution
public class SampleJob1 implements Job {

@Autowired
private SampleJobService jobService;

public void execute(JobExecutionContext context) throws JobExecutionException {
jobService.executeSampleJob1();
}
}


基于org.springframework.scheduling.quartz.QuartzJobBean
@Component
@DisallowConcurrentExecution
public class SampleJob2 extends QuartzJobBean {

@Autowired
private SampleJobService jobService;

@Override
protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
jobService.executeSampleJob2();
}

}


@Service
public class SampleJobService {

public void executeSampleJob1() {
System.out.println(" hello job 1. ");
}

public void executeSampleJob2() {
System.out.println(" hello job 2. ");
}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值