Earlier we talked about a distributed task scheduling framework PowerJob, which can perform task scheduling in a visual way. But sometimes we just need a lightweight task scheduling function, and it is a bit heavy for PowerJob to build a scheduling center. At this time, Quartz, the task scheduling framework officially supported by SpringBoot, comes in handy! This article mainly introduces the use of Quartz in SpringBoot, giving you more choices in implementing task scheduling!
SpringBoot actual e-commerce project mall (40k+star) address: https://github.com/macrozheng/mall
About Quartz
Quartz is a powerful open source task scheduling framework that can be integrated into almost any Java application (from a small stand-alone application to a large distributed application). Quartz can be used to create simple or complex task schedules to execute tens of thousands of tasks. Tasks are defined as standardized Java components, and tasks written in Java can be executed.
core concept
There are some core concepts in Quartz, and understanding them is very helpful for using Quartz!
- Scheduler: The task scheduler in Quartz, which can be used to schedule, suspend and delete tasks through Trigger and JobDetail.
- Trigger: Trigger in Quartz, you can specify the time of task execution through CRON expression, and the task execution will be automatically triggered when the time is up.
- JobDetail (task details): The details of the tasks to be executed in Quartz, including the unique identifier of the task and the specific task to be executed. Data can be passed to the task through JobDataMap.
- Job (task): A specific task in Quartz, including the specific method of executing the task.
CRON expression
Cron expression is a string, including 6~7 time elements, which can be used to specify the execution time of the task in Quartz.
Syntax of CRON
Seconds Minutes Hours DayofMonth Month DayofWeek
Description of each time element in CRON format
time element | characters that can appear | valid value range |
---|---|---|
Seconds | , - * / | 0-59 |
Minutes | , - * / | 0-59 |
Hours | , - * / | 0-23 |
DayofMonth | , - * / ? L W | 0-31 |
Month | , - * / | 1-12 |
DayofWeek | , - * / ? L # | 1-7 or SUN-SAT |
Description of special characters in CRON format
character | effect | Example |
---|---|---|
, | List enumeration values | Use 5, 10 in the Minutes field, which means that it is triggered once at 5 minutes and 10 minutes each |
\- | Indicates the trigger range | Use 5-10 in the Minutes field to trigger every minute from 5 to 10 minutes |
\* | matches any value | Use * in the Minutes field to indicate that it will be triggered every minute |
/ | The start time starts to trigger, and it is triggered every fixed time | Use 5/10 in the Minutes field, which means that it is triggered once every 5 minutes and every 10 minutes. |
? | In DayofMonth and DayofWeek, for matching arbitrary values | Use ? in the DayofMonth field to indicate that it is triggered once a day |
\# | In DayofMonth, determine the day of the week | 1#3 means the third Sunday |
L | means last | Use 5L in DayofWeek for triggering on the last Thursday |
W | Indicates valid working days (Monday to Friday) | Use 5W on DayofMonth, if the 5th is a Saturday, it will trigger once on the 4th of the nearest weekday |
Online CRON Expression Generator
In fact, there is no need to memorize the CRON expression. When you need to use it, you can directly use the online generator. The address: https://cron.qqe2.com/
Integrate SpringBoot usage
Next, let's talk about how to use Quartz in SpringBoot to achieve task scheduling. In the e-commerce system, there is often a need to send emails or in-site messages regularly. Let's take this as a scenario to realize it!
- There are two ways to store task information in Quartz, using memory or using database to store, here we use the database storage method, first of all, we need to create a new Quartz related table, the table creation script is in the resources directory of the project, named tables_mysql.sql, create After success, there are 11 more tables in the database;
- Next, add the relevant dependencies of Quartz in pom.xml, and SpringBoot officially has provided us with the relevant Starter;
<!--SpringBoot integrated QuartZ--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
- Add Quartz related configuration in application.yml, just look at the comments for configuration instructions, mainly to configure scheduler, jobStore and threadPool;
spring: quartz: job-store-type: jdbc # quartz task storage type: jdbc or memory wait-for-jobs-to-complete-on-shutdown: true # Wait for task to complete on shutdown overwrite-existing-jobs: true # Can overwrite existing tasks properties: # quartz native configuration org: quartz: scheduler: instanceName: scheduler # Scheduler instance name instanceId: AUTO # Scheduler instance ID is automatically generated jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX # Schedule information storage processing class driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # Use a fully JDBC-compliant driver tablePrefix: QRTZ_ # quartz related table prefix useProperties: false # Whether to convert attributes in JobDataMap to string storage threadPool: class: org.quartz.simpl.SimpleThreadPool # Specify the thread pool implementation class to provide a fixed size thread pool to the scheduler threadCount: 10 # Set the number of concurrent threads threadPriority: 5 # Specify thread priority
- Create a task scheduling business interface, and define three methods, namely scheduling tasks through CRON expressions, scheduling tasks at specified time, and canceling timed tasks;
/** * Quartz Scheduled task operation class * Created by macro on 2020/9/27. */ public interface ScheduleService { /** * Scheduling tasks via CRON expressions */ String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data); /** * Schedule a task at a specified time */ String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data); /** * Cancel a scheduled task */ Boolean cancelScheduleJob(String jobName); }
- Create task scheduling business implementation classes, and implement related methods through Scheduler, CronTrigger, and JobDetail API s;
/** * Quartz Scheduled task operation implementation class * Created by macro on 2020/9/27. */ @Slf4j @Service public class ScheduleServiceImpl implements ScheduleService { @Autowired private Scheduler scheduler; private String defaultGroup = "default_group"; @Override public String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data) { // Create tasks that need to be performed String jobName = UUID.fastUUID().toString(); JobDetail jobDetail = JobBuilder.newJob(jobBeanClass) .withIdentity(jobName, defaultGroup) .usingJobData("data", data) .build(); //Create a trigger to specify the task execution time CronTrigger cronTrigger = TriggerBuilder.newTrigger() .withIdentity(jobName, defaultGroup) .withSchedule(CronScheduleBuilder.cronSchedule(cron)) .build(); //Task scheduling using the scheduler try { scheduler.scheduleJob(jobDetail, cronTrigger); } catch (SchedulerException e) { e.printStackTrace(); log.info("Failed to create scheduled task!"); } return jobName; } @Override public String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data) { //Date to CRON Expression String startCron = String.format("%d %d %d %d %d ? %d", DateUtil.second(startTime), DateUtil.minute(startTime), DateUtil.hour(startTime, true), DateUtil.dayOfMonth(startTime), DateUtil.month(startTime) + 1, DateUtil.year(startTime)); return scheduleJob(jobBeanClass, startCron, data); } @Override public Boolean cancelScheduleJob(String jobName) { boolean success = false; try { // Pause trigger scheduler.pauseTrigger(new TriggerKey(jobName, defaultGroup)); // Remove tasks from triggers scheduler.unscheduleJob(new TriggerKey(jobName, defaultGroup)); // delete task scheduler.deleteJob(new JobKey(jobName, defaultGroup)); success = true; } catch (SchedulerException e) { e.printStackTrace(); } return success; } }
- Define the tasks that need to be executed, inherit the QuartzJobBean class, and implement the executeInternal method. Three tasks are defined here, sending emails regularly, sending internal messages regularly, and executing CRON expression tasks;
/** * Send Email Scheduled Task Executor * Created by macro on 2020/9/27. */ @Slf4j @Component public class SendEmailJob extends QuartzJobBean { @Autowired private ScheduleService scheduleService; @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { Trigger trigger = jobExecutionContext.getTrigger(); JobDetail jobDetail = jobExecutionContext.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); String data = jobDataMap.getString("data"); log.info("Scheduled sending email operations:{}",data); //Delete triggers and tasks when done scheduleService.cancelScheduleJob(trigger.getKey().getName()); } }
/** * Timed task executor for sending intra-station messages * Created by macro on 2020/9/27. */ @Slf4j @Component public class SendMessageJob extends QuartzJobBean { @Autowired private ScheduleService scheduleService; @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { Trigger trigger = jobExecutionContext.getTrigger(); JobDetail jobDetail = jobExecutionContext.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); String data = jobDataMap.getString("data"); log.info("The operation of sending intra-station messages regularly:{}",data); //Delete triggers and tasks when done scheduleService.cancelScheduleJob(trigger.getKey().getName()); } }
/** * Task executor using CRON expressions * Created by macro on 2020/9/29. */ @Slf4j @Component public class CronProcessJob extends QuartzJobBean { @Override protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException { JobDetail jobDetail = jobExecutionContext.getJobDetail(); JobDataMap jobDataMap = jobDetail.getJobDataMap(); String data = jobDataMap.getString("data"); log.info("CRON Expression task execution:{}",data); } }
- Finally, create a task scheduling related interface and call the task scheduling business class.
/** * Scheduled Task Scheduling Related Interfaces * Created by macro on 2020/9/29. */ @Api(tags = "ScheduleController", description = "Scheduled Task Scheduling Related Interfaces") @RestController @RequestMapping("/schedule") public class ScheduleController { @Autowired private ScheduleService scheduleService; @ApiOperation("Send emails regularly") @PostMapping("/sendEmail") public CommonResult sendEmail(@RequestParam String startTime,@RequestParam String data) { Date date = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_FORMAT); String jobName = scheduleService.scheduleFixTimeJob(SendEmailJob.class, date, data); return CommonResult.success(jobName); } @ApiOperation("Send intra-station messages regularly") @PostMapping("/sendMessage") public CommonResult sendMessage(@RequestParam String startTime,@RequestParam String data) { Date date = DateUtil.parse(startTime, DatePattern.NORM_DATETIME_FORMAT); String jobName = scheduleService.scheduleFixTimeJob(SendMessageJob.class, date, data); return CommonResult.success(jobName); } @ApiOperation("pass CRON Expression scheduling tasks") @PostMapping("/scheduleJob") public CommonResult scheduleJob(@RequestParam String cron, @RequestParam String data) { String jobName = scheduleService.scheduleJob(CronProcessJob.class, cron, data); return CommonResult.success(jobName); } @ApiOperation("Cancel a scheduled task") @PostMapping("/cancelScheduleJob") public CommonResult cancelScheduleJob(@RequestParam String jobName) { Boolean success = scheduleService.cancelScheduleJob(jobName); return CommonResult.success(success); } }
run the test
- Call the interface test to send email regularly;
- After reaching the point, it is found that the console has printed the task execution information;
2020-09-30 11:23:00.035 INFO 10160 --- [eduler_Worker-1] com.macro.mall.tiny.job.SendEmailJob : Timing send email operation: send email content
- Use the CRON expression to start a scheduled task, starting from 0s and executing it every 10s;
- The console prints task execution information every 10s;
2020-09-30 11:26:30.024 INFO 10160 --- [eduler_Worker-2] com.macro.mall.tiny.job.CronProcessJob : CRON Expression task execution: CRON Message content 2020-09-30 11:26:40.025 INFO 10160 --- [eduler_Worker-3] com.macro.mall.tiny.job.CronProcessJob : CRON Expression task execution: CRON Message content 2020-09-30 11:26:50.017 INFO 10160 --- [eduler_Worker-4] com.macro.mall.tiny.job.CronProcessJob : CRON Expression task execution: CRON Message content 2020-09-30 11:27:00.023 INFO 10160 --- [eduler_Worker-5] com.macro.mall.tiny.job.CronProcessJob : CRON Expression task execution: CRON Message content 2020-09-30 11:27:10.019 INFO 10160 --- [eduler_Worker-6] com.macro.mall.tiny.job.CronProcessJob : CRON Expression task execution: CRON Message content
- We can cancel the task by calling the jobName returned by the start task and calling the interface for canceling the scheduled task. After the call is successful, the scheduled task will not be executed.
References
Official documentation: http://www.quartz-scheduler.o...
Project source code address
https://github.com/macrozheng...
This article GitHub https://github.com/macrozheng/mall-learning It has been recorded, welcome everyone to Star!