在项目应用中往往会用到任务定时器的功能,比如某某时间,或者多少多少秒然后执行某个骚操作等。
spring 支持多种定时任务的实现,其中不乏自身提供的定时器。
接下来介绍一下使用 spring 的定时器和使用 quartz 定时器。
spring 自身提供了定时任务,为什么还要使用 quartz 呢?
使用 spring 自带的定时任务可以很简单很方便的完成一些简单的定时任务,没错,这里提到的是简单,因此我们想动态的执行我们的定时任务是非常困难的。然而使用 quartz 却可以很容易的管理我们的定时任务,很容易动态的操作定时任务。
spring 自带支持定时器的任务实现,其可通过简单配置来使用到简单的定时任务。
@Component
@Configurable
@EnableScheduling
public class ScheduledTasks{
/**
* 方式一
* 每6秒执行一次
**/
@Scheduled(fixedRate = 6000)
public void reportCurrentByCron(){
System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));
}
/**
* 方式二
* 每6秒执行一次
**/
@Scheduled(cron = "*/6 * * * * * ")
public void reportCurrentByCron(){
System.out.println ("Scheduling Tasks Examples By Cron: The time is now " + dateFormat ().format (new Date ()));
}
}
@Scheduled 参数可以接受两种定时的设置,一种是我们常用的 cron="/6 * * * ?",一种是 fixedRate = 6000,两种都可表示固定周期执行定时任务。
fixedRate说明
cron说明
cron 一定有七位数,最后一位是年,SpringBoot 定时方案只需要设置六位即可:
cron中,还有一些特殊的符号,含义如下:
举几个例子熟悉一下:
ok,spring的定时器就像如上这么简单,涉及到的几个注解:
@EnableScheduling:标注启动定时任务。
@Scheduled: 定义某个定时任务。
quartz 的设计者做了一个设计选择来从调度分离开作业。
quartz 中的触发器用来告诉调度程序作业什么时候触发,框架提供了一把触发器类型,但两个最常用的是 SimpleTrigger 和 CronTrigger。
SimpleTrigger 为需要简单打火调度而设计。典型地,如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。
另一方面,如果你有许多复杂的作业调度,那么或许需要CronTrigger。
什么是复杂调度?
当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。
开始之前需要了解的几个概念:
上边的四个概念,建议通读一遍,结合下方代码,思路更清晰。
SpringBoot2.x 之后,完成了对 Quartz 自动化配置集成,省去了很多繁琐的配置,下面进入正题吧。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
spring:
quartz:
# 任务信息存储至?MEMORY(内存方式:默认)、JDBC(数据库方式)
job-store-type: jdbc
properties:
org:
quartz:
jobStore:
misfireThreshold: 100
/**
* @author niceyoo
*/
@Slf4j
@RestController
@Api(description = "定时任务管理接口")
@RequestMapping("/tmax/quartzJob")
public class TmaxQuartzJobController {
/**
* 定时任务service
*/
@Autowired
private QuartzJobService quartzJobService;
/**
* 调度器
*/
@Autowired
private Scheduler scheduler;
@RequestMapping(value = "/add", method = RequestMethod.POST)
@ApiOperation(value = "添加定时任务")
public Result<Object> addJob(@ModelAttribute QuartzJob job){
add(job.getJobClassName(),job.getCronExpression(),job.getParameter());
quartzJobService.save(job);
return new ResultUtil<Object>().setSuccessMsg("创建定时任务成功");
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
@ApiOperation(value = "更新定时任务")
public Result<Object> editJob(@ModelAttribute QuartzJob job){
delete(job.getJobClassName());
add(job.getJobClassName(),job.getCronExpression(),job.getParameter());
job.setStatus(CommonConstant.STATUS_NORMAL);
quartzJobService.update(job);
return new ResultUtil<Object>().setSuccessMsg("更新定时任务成功");
}
@RequestMapping(value = "/pause", method = RequestMethod.POST)
@ApiOperation(value = "暂停定时任务")
public Result<Object> pauseJob(@ModelAttribute QuartzJob job){
try {
scheduler.pauseJob(JobKey.jobKey(job.getJobClassName()));
} catch (SchedulerException e) {
throw new TmaxException("暂停定时任务失败");
}
job.setStatus(CommonConstant.STATUS_DISABLE);
quartzJobService.update(job);
return new ResultUtil<Object>().setSuccessMsg("暂停定时任务成功");
}
@RequestMapping(value = "/resume", method = RequestMethod.POST)
@ApiOperation(value = "恢复定时任务")
public Result<Object> resumeJob(@ModelAttribute QuartzJob job){
try {
scheduler.resumeJob(JobKey.jobKey(job.getJobClassName()));
} catch (SchedulerException e) {
throw new TmaxException("恢复定时任务失败");
}
job.setStatus(CommonConstant.STATUS_NORMAL);
quartzJobService.update(job);
return new ResultUtil<Object>().setSuccessMsg("恢复定时任务成功");
}
@RequestMapping(value = "/delByIds/{ids}", method = RequestMethod.DELETE)
@ApiOperation(value = "删除定时任务")
public Result<Object> deleteJob(@PathVariable String[] ids){
for(String id:ids){
QuartzJob job = quartzJobService.get(id);
delete(job.getJobClassName());
quartzJobService.delete(job);
}
return new ResultUtil<Object>().setSuccessMsg("删除定时任务成功");
}
/**
* 添加定时任务
* @param jobClassName
* @param cronExpression
* @param parameter
*/
public void add(String jobClassName, String cronExpression, String parameter){
try {
##启动调度器
scheduler.start();
##构建job信息
JobDetail jobDetail = JobBuilder.newJob(getClass(jobClassName).getClass())
.withIdentity(jobClassName)
.usingJobData("parameter", parameter)
.build();
##表达式调度构建器(即任务执行的时间) 使用withMisfireHandlingInstructionDoNothing() 忽略掉调度暂停过程中没有执行的调度
CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression).withMisfireHandlingInstructionDoNothing();
##按新的cronExpression表达式构建一个新的trigger
CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName)
.withSchedule(scheduleBuilder).build();
scheduler.scheduleJob(jobDetail, trigger);
} catch (SchedulerException e) {
log.error(e.toString());
throw new TmaxException("创建定时任务失败");
} catch (Exception e){
throw new TmaxException("后台找不到该类名任务");
}
}
/**
* 删除定时任务
* @param jobClassName
*/
public void delete(String jobClassName){
try {
scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName));
scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName));
scheduler.deleteJob(JobKey.jobKey(jobClassName));
} catch (Exception e) {
throw new TmaxException("删除定时任务失败");
}
}
public static Job getClass(String classname) throws Exception {
Class<?> class1 = Class.forName(classname);
return (Job)class1.newInstance();
}
}
@Slf4j
public class SampleJob implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
log.info(String.format("打印时间:"+ DateUtil.now()));
}
}
4小步代码看完后,我们再来分析一波 quartz 的4个核心概念,先脑补一张图。
主要看 TmaxQuartzJobController 的 add() 方法
最后,调用 Controller 层的任务添加方法 /add 完成全部,效果如下:
2019-05-23 00:38:38.455 INFO 19856 --- [eduler_Worker-1] club.sscai.tmax.quartz.jobs.SampleJob : 打印时间:2019-05-24 09:38:38
2019-05-23 00:38:39.035 INFO 19856 --- [eduler_Worker-2] club.sscai.tmax.quartz.jobs.SampleJob : 打印时间:2019-05-24 09:38:39
2019-05-23 00:38:40.752 INFO 19856 --- [eduler_Worker-3] club.sscai.tmax.quartz.jobs.SampleJob : 打印时间:2019-05-24 09:38:40
2019-05-23 00:38:41.033 INFO 19856 --- [eduler_Worker-4] club.sscai.tmax.quartz.jobs.SampleJob : 打印时间:2019-05-24 09:38:41
2019-05-23 00:38:42.640 INFO 19856 --- [eduler_Worker-5] club.sscai.tmax.quartz.jobs.SampleJob : 打印时间:2019-05-24 09:38:42
2019-05-23 00:38:43.023 INFO 19856 --- [eduler_Worker-6] club.sscai.tmax.quartz.jobs.SampleJob : 打印时间:2019-05-24 09:38:43
习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:niceyoo
原文:https://www.cnblogs.com/niceyoo/p/10917461.html