In simple terms, SpringBoot integrates Quartz to implement scheduled tasks and Redis health detection (1)

Table of Contents

Preface

Environment configuration

Quartz

What is Quartz?

Application scenarios

core components

Job

JobDetail

Trigger

CronTrigger

SimpleTrigger

Scheduler

task storage

RAM

JDBC

Import dependencies

scheduled tasks

sales statistics

Redis detection

use

Precautions


Foreword

The Quartz framework was introduced in Yuexiang Campus 1.0 to implement the daily sales statistics function for merchants. The project has been upgraded to the SpringBoot version, so the corresponding code needs to be adjusted. In addition, consider how to ensure the normal startup of the project if Redis fails or when the project does not want to configure Redis? That is, when Redis fails, how to seamlessly switch to the database to query data instead of throwing an error message? Since the client that integrates Redis in the project is Lettuce, you can consider using scheduled tasks to monitor the Redis service so as to switch data query operations without any sense.

Environment Configuration

JDK 1.8

Spring Boot 2.7.12

lettuce 6.1.10 (included in Spring-Boot-Starter-Data-Redis)

Quartz 2.3.2

Quartz

What is Quartz?

According to the official documentation, Quartz is a feature-rich, open source job scheduling library that can be integrated into any Java application, ranging from independent applications to complex electronic applications. Business systems. Quartz can be used to create simple or complex schedules to execute dozens, hundreds, or even tens of thousands of jobs. Jobs are defined as standard Java components and can be executed programmatically.

Application Scenario

As mentioned at the beginning of the article, when we need to count the daily sales or weekly sales of a store, we can perform the corresponding operations through a scheduled task. And Redis may cause client problems when it is not used for a long time. In addition, Quartz can also be used for other operations such as sending message notifications regularly, such as getting daily weather and pushing emails to designated customers. These can all be achieved through Quartz. In addition, Quartz can also complete other complex tasks.

Core Component

Job

Used to store task logic that really needs to be executed regularly

JobDetail

Used to describe task information, such as task name, task grouping, etc. It should be noted that JobDetail contains a Key attribute, which will construct the Key from the incoming task name and group name. If the parameter is empty, it will construct it from the UUID to ensure that the Key is unique. Therefore, the same task name and group name will overwrite the previous task, which needs to be noted.

Using the design of JobDetail + Job can avoid access problems to the same instance in concurrent situations.

Data can be stored and passed to Job instances through JobDataMap.

Trigger

Trigger is a trigger, used to specify how scheduled tasks will be executed. Note that Trigger corresponds to JobDetail one-to-one, that is, a trigger can only be used for one defined task. Here are two commonly used triggers:

CronTrigger

The core is to use Cron expressions to construct tasks. The following is a Cron expression that represents the execution of tasks on the last day of each month:

# The last day of each month
    0 0 L * * *

    illustrate:
    Linux
    * * * * *
    - - - - -
    | | | | |
    | | | + ----- day of week (0 - 7) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
    | | | + ---------- month (1 - 12) OR jan,feb,mar,apr ...
    | | + --------------- day of month (1 - 31)
    | + -------------------- hour (0 - 23)
     + --------------------------- minute (0 - 59)

Since there are many articles about Cron expressions on the Internet, I won’t go into details here. Here are a few commonly used Cron expressions:

(1) 0/2 * * * * ? means executing the task every 2 seconds

(2) 0 0/2 * * * ? means executing the task every 2 minutes

(3) 0 0 2 1 * ? means adjusting the task at 2 am on the 1st of every month

(4) 0 15 10 ? * MON-FRI means the job is executed at 10:15 am every day from Monday to Friday

(5) 0 0 10,14,16 * * ? Every day 10 am, 2 pm, 4 pm

(5) 0 0/30 9-17 * * ? Every half hour during working hours from 9 to 5

Cron expressions can be verified through Crontab.guru – The cron schedule expression editor website.

SimpleTrigger

Compared with the Cron expression mentioned above, SimpleTrigger is easier to build some tasks to be executed at specified intervals. For example, to execute a task every 75 seconds, it is better to use SimpleTrigger.

Scheduler

Task scheduler, which can associate JobDetail with Trigger, and start task execution through the task scheduler. A task scheduler can contain multiple associated instances.

Task Storage

Quartz provides two scheduled task storage functions, one is RAM and the other is JDBC.

RAM

By default, Quartz will store task data in memory. The advantage is that task reading is fast and easy to use. But the disadvantage is that tasks will be lost as the service restarts. (This article adopts this method)

JDBC

Quartz provides the function of persisting scheduled tasks. You can persist scheduled tasks into the database by creating corresponding data tables. This ensures that tasks will not be lost due to service restarts and allows for better management of tasks. . The disadvantage is that additional database table creation is required. This article uses the default RAM storage method, which can be selected based on specific demand scenarios.

Import dependencies

Since the project of this article uses SpringBoot, you can import the following dependencies

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-quartz</artifactId>
        </dependency>

Scheduled tasks

Task creation can be accomplished by inheriting the QuartzJobBean class and rewriting its excuteInternal method, or by implementing the excute method of the Job interface. From the source code of QuartzJobBean, we know that it implements the Job interface, so you can choose any of the above creation methods.

Sales Statistics

Sales statistics task class, only log printing is used here, the specific business logic can be written by yourself

@Slf4j
public class SellDailyJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("This is a daily sales statistics scheduled task...");
    }
}

Execution rule configuration class

@Configuration
public class SellDailyConfig{

    @Bean("sellDailyJob")
    public JobDetail jobDetail(){
        // Specify the class for task execution
        return JobBuilder.newJob(SellDailyJob.class)
                 //Task name and group name, cannot be repeated
                .withIdentity("sellDailyJob", "group")
                .withDescription("Task description: Run in memory mode")
                .storeDurably()
                .build();
    }

    @Bean("sellDailyTrigger")
    public Trigger trigger() {
        return TriggerBuilder.newTrigger()
                // Trigger name and group name, cannot be repeated
                .withIdentity("trigger", "group")
                .forJob(jobDetail())
                .startNow()
                //Use Cron expression to build execution event and execute it every 5s
                .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?"))
                .build();
    }

}

Redis detection

Redis health detection scheduled task class, the construction method is the same as above

@Slf4j
public class RedisCheckJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("This is a Redis scheduled heartbeat task");
    }
}

Execution rule configuration class

@Configuration
@Slf4j
public class RedisCheckConfig {
    //Specify the name of the generated Bean instance object
    @Bean("redisCheck")
    public JobDetail jobDetail() {
        return JobBuilder.newJob(RedisCheckJob.class)
                //Task name and task grouping
                .withIdentity("RedisCheckJob", "group")
                .withDescription("Task description: Run in memory mode")
                .storeDurably()
                .build();
    }

    @Bean("redisTrigger")
    public Trigger trigger() {
        return TriggerBuilder.newTrigger()
                // Trigger name and group
                .withIdentity("redisCheck", "group")
                .forJob(jobDetail())
                .startNow()
                // Use SimpleSchedule to build scheduled tasks
                .withSchedule(
                        SimpleScheduleBuilder
                                .simpleSchedule()
                                 //Execute tasks every 10 seconds
                                .withIntervalInSeconds(10)
                                // Never expires
                                .repeatForever())
                .build();
    }
}

use

In the previous section, two scheduled tasks were built using CronTrigger and SimpleTrigger respectively. According to the official SpringBoot documentation, when Quartz is available, the SchedulerFactoryBean will automatically assemble the Scheduler into the container, so @Configuration is used in SpringBoot. + After constructing scheduled tasks with @Bean annotation, there is no need to explicitly create a Scheduler. SpringBoot will automatically load these scheduled tasks and hand them over to the Scheduler for scheduling.

So after the configuration is completed, you only need to start the application, and the execution results are as follows.

Notes

1. When building a scheduled task above, you need to create a task class and write custom business methods in it. And write the corresponding task class in the configuration class newJob. When the jobDetail and Trigger methods are built using @Bean annotations, they need to specify names and do not repeat them. Otherwise, other configuration classes cannot build Bean instances normally.

2. The withIdentity in the jobDetail method and the trigger method should specify different task names and task groups respectively. It is necessary to ensure that at least one of the above two attributes in other configuration classes is different, otherwise the scheduled task will not be executed normally. (eg: The task name in the configuration class A is work, and the group name is group. If the configuration in B is the same, service A will not run normally)

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. Java Skill TreeHomepageOverview 135481 people are learning the system