SpringBoot e-commerce project mall (40K + STAR) address: github.com/macrozheng/…

Abstract

Before we talked about a distributed task scheduling framework, PowerJob, which can be used for task scheduling in a visual way. However, sometimes we just need a lightweight task scheduling function, and PowerJob requires a scheduling center. This is where SpringBoot’s Quartz framework comes in handy. This article mainly introduces the use of Quartz in SpringBoot, so that you have more choices in implementing task scheduling!

Introduction of Quartz

Quartz is a powerful open source task scheduling framework that can be integrated into almost any Java application, from small standalone to large distributed. Quartz can be used to create simple or complex task schedules to perform tens of thousands of tasks. Tasks are defined as standardized Java components, and any task written in Java can be executed.

The core concept

There are some core concepts in Quartz that are helpful to understand!

  • Scheduler: A task Scheduler in Quartz that can be used to schedule, pause, and delete tasks via Trigger and JobDetail.
  • Trigger: in Quartz, a CRON expression can be used to specify the time when a task will be executed. When the time is up, the task will be automatically triggered.
  • JobDetail: Details of tasks to be executed in Quartz, including the unique identifier of the task and the specific task to be executed. Data can be sent to the task through JobDataMap.
  • Job: The specific task in Quartz, which contains the specific method of performing the task.

CRON expression

A Cron expression is a string containing 6 to 7 time elements that can be used in Quartz to specify the execution time of a task.

CRON syntax format

Seconds Minutes Hours DayofMonth Month DayofWeek
Copy the code

Description of each time element in the CRON format

The time element The character that can appear Effective value range
Seconds , – * / 0-59
Minutes , – * / 0-59
Hours , – * / 0-23
DayofMonth , – * /? L W 0-31
Month , – * / 1-12
DayofWeek , – * /? L # 1-7 – SAT or SUN

Special characters in CRON format

character role For example,
. Listing enumerated values Use 5,10 in the Minutes field to fire at 5 and 10 Minutes each
Indicates trigger range Use 5-10 in the Minutes field to trigger every minute from 5 to 10 Minutes
* Match any value Using * in the Minutes field means that it fires every minute
/ Start time Triggers at fixed intervals Use 5/10 in the Minutes field to fire once every 5 Minutes and again every 10 Minutes
? In DayofMonth and DayofWeek, used to match any value Used in the DayofMonth domain? Is triggered every day
# In DayofMonth, determine the day of the week 1#3 is the third Sunday
L Said the last Use 5L in DayofWeek to trigger on the last Thursday
W Represents valid working days (Monday to Friday) Use 5W in DayofMonth, and if the 5th falls on a Saturday, it will be triggered once on the 4th of the nearest weekday

Online CRON expression generator

CRON expressions don’t need to be memorized. use the online generator (cron.qqe2.com/) when needed

Integrate SpringBoot use

Next, we will talk about how to use Quartz in SpringBoot to implement task scheduling. In e-commerce systems, there will often be the need to regularly send emails or in-site letters, so we take this as a scenario to implement!

  • There are two ways for Quartz to store task information: memory or database. Here we use database storage. First of all, we need to create Quartz related tables and build table scripts in the projectresourcesIn the directory, the name istables_mysql.sql, there are 11 more tables in the database after the successful creation.

  • The next inpom.xmlAdd Quartz dependency, SpringBoot official has provided us with a good Starter;
<! - SpringBoot integration QuartZ - >
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Copy the code
  • inapplication.ymlAdd Quartz related configuration, configuration instructions directly read the note is good, mainly for thescheduler,jobStoreandthreadPoolTo configure;
spring:
  quartz:
    job-store-type: jdbc # Quartz Task storage type: JDBC or Memory
    wait-for-jobs-to-complete-on-shutdown: true Wait for the task to complete while closing
    overwrite-existing-jobs: true You can override existing tasks
    properties: # Quartz native configuration
      org:
        quartz:
          scheduler:
            instanceName: scheduler The scheduler instance name
            instanceId: AUTO The scheduler instance ID is automatically generated
          jobStore:
            class: org.quartz.impl.jdbcjobstore.JobStoreTX Scheduling information storage processing class
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # Use a fully JDBC-compliant driver
            tablePrefix: QRTZ_ # Quartz table prefix
            useProperties: false # whether to convert JobDataMap attributes to string stores
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool Specifies a thread pool implementation class that provides a fixed size thread pool for the scheduler
            threadCount: 10 Set the number of concurrent threads
            threadPriority: 5 # set thread priority
Copy the code
  • Create a task scheduling service interface and define three methods, namely, scheduling a task through CRON expression, scheduling a task at a specified time and canceling a scheduled task.
/** * Created by macro on 2020/9/27. */
public interface ScheduleService {
    /** * Schedule tasks */ using CRON expressions
    String scheduleJob(Class<? extends Job> jobBeanClass, String cron, String data);

    /** * Schedules tasks at specified time */
    String scheduleFixTimeJob(Class<? extends Job> jobBeanClass, Date startTime, String data);

    /** * Cancel the scheduled task */
    Boolean cancelScheduleJob(String jobName);
}
Copy the code
  • Create a task scheduling business implementation class, throughScheduler,CronTrigger,JobDetailAPI implementation related methods;
/** * 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 a task to execute
        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();
        // Use the scheduler to schedule tasks
        try {
            scheduler.scheduleJob(jobDetail, cronTrigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
            log.info("Failed to create a 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 the trigger
            scheduler.pauseTrigger(new TriggerKey(jobName, defaultGroup));
            // Remove the task from the trigger
            scheduler.unscheduleJob(new TriggerKey(jobName, defaultGroup));
            // Delete the task
            scheduler.deleteJob(new JobKey(jobName, defaultGroup));
            success = true;
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        returnsuccess; }}Copy the code
  • Define the tasks that need to be performed and inheritQuartzJobBeanClasses that implementexecuteInternalThree tasks are defined here, namely, regularly sending mail, regularly sending intra-station messages and executing CRON expression tasks;
/** * 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("Timed mail operation: {}",data);
        // Delete triggers and tasks after completionscheduleService.cancelScheduleJob(trigger.getKey().getName()); }}Copy the code
/** * 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("Timed message operation in station: {}",data);
        // Delete triggers and tasks after completionscheduleService.cancelScheduleJob(trigger.getKey().getName()); }}Copy the code
/** * 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); }}Copy the code
  • Finally, create the task scheduling related interface and call the task scheduling business class.
/** * Created by macro on 2020/9/29. */
@API (tags = "ScheduleController", description = "Interface for scheduling tasks ")
@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 (" Timed send station message ")
    @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 (" Scheduling tasks via CRON expressions ")
    @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 scheduled task ")
    @PostMapping("/cancelScheduleJob")
    public CommonResult cancelScheduleJob(@RequestParam String jobName) {
        Boolean success = scheduleService.cancelScheduleJob(jobName);
        returnCommonResult.success(success); }}Copy the code

Run the test

  • Call timed mail interface test;

  • Task execution information is printed on the console after the task arrives.
11:23:00 2020-09-30. 10160-035 the INFO [] eduler_Worker - 1 com. Macro. Mall. Tiny. Job. SendEmailJob: operation: timing to send mail to send emailCopy the code
  • The CRON expression is used to start a scheduled task, starting from 0s and executing it every 10s.

  • The console prints the task execution information every 10 seconds.
The 2020-09-30 11:26:30. 10160-024 the INFO [eduler_Worker - 2] com. Macro. Mall. Tiny. Job. CronProcessJob: CRON expressions perform tasks: CRON news contents 11:26:40 2020-09-30. 10160-025 the INFO/eduler_Worker - 3 com. Macro. Mall. Tiny. Job. CronProcessJob: CRON expressions perform tasks: CRON news contents 11:26:50 2020-09-30. 10160-017 the INFO [eduler_Worker - 4] com. Macro. Mall. Tiny. Job. CronProcessJob: CRON expressions perform tasks: CRON news contents 11:27:00 2020-09-30. 10160-023 the INFO [eduler_Worker - 5] com. Macro. Mall. Tiny. Job. CronProcessJob: CRON expressions perform tasks: CRON news contents 11:27:10 2020-09-30. 10160-019 the INFO [eduler_Worker - 6] com. Macro. Mall. Tiny. Job. CronProcessJob: CRON expression task execution: CRON message contentCopy the code
  • We can return it by starting the taskjobNameTo cancel the scheduled task, the scheduled task will not be executed after the call is successful.

The resources

The official document: www.quartz-scheduler.org/documentati…

Project source code address

Github.com/macrozheng/…

In this paper, making github.com/macrozheng/… Already included, welcome everyone Star!