Suppose we have a data synchronization requirement that requires a data synchronization every five seconds. So how do we implement this data synchronization task?
Hello, everyone, I’m Xiao Feng.
Implement Scheduled tasks using @Scheduled in a Spring Boot project.
Quick start
Based on the above requirements, we set up a simple data synchronization scheduling task based on Spring Boot framework.
The Demo is as follows.
Create a project
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
Copy the code
Since we are developing based on Spring Boot, no other dependencies are required.
package com.fengwenyi.demospringbootscheduled;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/ * * *@author <a href="https://www.fengwenyi.com">Erwin Feng</a>
* @sinceThe 2021-09-29 * /
@SpringBootApplication
public class DemoSpringBootScheduledApplication {
public static void main(String[] args) { SpringApplication.run(DemoSpringBootScheduledApplication.class, args); }}Copy the code
Enable scheduling annotations
package com.fengwenyi.demospringbootscheduled.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
/ * * *@author <a href="https://www.fengwenyi.com">Erwin Feng</a>
* @sinceThe 2021-09-29 * /
@Configuration
@EnableScheduling
public class ScheduledConfiguration {}Copy the code
Data Synchronization Task
package com.fengwenyi.demospringbootscheduled.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/ * * *@author <a href="https://www.fengwenyi.com">Erwin Feng</a>
* @sinceThe 2021-10-21 * /
@Component
@Slf4j
public class DemoTask {
@Scheduled(initialDelay = 5, fixedRate = 5, timeUnit = TimeUnit.SECONDS)
public void dataSynchronizationTask(a) {
log.info("Start data synchronization task"); }}Copy the code
perform
Through the meaning of the steps, our demo is set up, run, the console print log as follows:
2021-10-21 21:44:55.711 INFO 10320 -- [scheduling-1] C.F.D.task.demotask: 2021-10-21 21:45:00.705 INFO 10320 -- [scheduling-1] C.F.D.task. DemoTask: 2021-10-21 21:45:05.715 INFO 10320 -- [scheduling-1] C.F.D.task. DemoTask: 2021-10-21 21:45:10.710 INFO 10320 -- [scheduling-1] C.F.D.task. DemoTask: Starts the data synchronization taskCopy the code
By printing logs, we specify that “data synchronization task” will be automatically executed every 5 seconds, which makes task scheduling easy.
@scheduled parameter details
The following is an explanation of how the @Scheduled annotation provides configuration.
cron
Let’s start with an example: Perform a task every 5 seconds.
@Scheduled(cron = "0/5 * * * * ? ")
public void testCron01(a) {
log.info("test cron 01 exec");
}
Copy the code
Perform:
2021-10-23 02:31:50.030 INFO 18872 -- [scheduling-1] C.F.D.task.scheduledTask: Test cron 1 exec 2021-10-23 02:31:55.009 INFO 18872 -- [scheduling-1] C.F.D.task.scheduledTask: Test cron 1 exec 2021-10-23 02:32:00.005 INFO 18872 -- [scheduling-1] C.F.D.task. ScheduledTask: Test cron 1 exec 2021-10-23 02:32:00.005 INFO 18872 -- [scheduling-1] C.F.D.task. ScheduledTask: Test cron 1 execCopy the code
There are a few things to note about cron expressions:
1, structure,
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ the second (0-59) │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ minute (0-59) │ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ the adrenaline-charged (0-23) │ │ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ day Of the month (1-31) │ │ │ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ the month (1-12) (or JAN - DEC) │ │ │ │ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ day of the week (0 7) │ │ │ │ │ │ (0 or 7 is Sunday, or MON - SUN) │ │ │ │ │ │ * * * * * *Copy the code
The spring-supported CRon expression consists of six bits representing:
- seconds
- minutes
- hours
- Day (month)
- month
- Day (week)
2. Cron expression example
To get a better understanding of what cron expressions mean, let’s use the examples in spring’s official documentation.
IO /spring-fram…
Asterisks (*) and question marks (?) Both represent wildcards, where,? Can be used for days (month) and days (week), i.e. fourth and sixth place.
L is for the end, like the last Sunday in January.
W indicates working days (Monday to Friday).
# indicates the day of the month. 5#2: indicates the second Friday of each month. MON#1:1st Monday of each month.
3, Macros,
Spring provides several special CRon expressions (year, month, week, day or night, hour) that we can use directly.
@Scheduled(cron = "@hourly")
public void testCron02(a) {
log.info("test cron 02 exec");
}
Copy the code
zone
The time zone
fixedDelay
Fixed interval, parameter type long.
fixedDelayString
Fixed interval, parameter type String, same as fixedDelay.
fixedRate
Fixed rate, parameter type long.
fixedRateString
FixedRate, argument type long, same as fixedRate.
timeUnit
Time unit, starting from 5.3.10
Spring Boot 2.5.5 starts
initialDelay
First delay time. The parameter type is long.
initialDelayString
First delay time. The parameter type is String.
FixedDelay and fixedRate
The difference between
A fixedDelay is the interval from the end of the task.
FixedRate, interval time, counting from the start time of the task.
The interval is longer than the task execution time
For example, for a task, the interval is 5 seconds and the task execution time is 2 seconds.
Assuming the first fixedDelay executes at 5 seconds, the second one executes at 12 seconds.
While fixedRate executes the first time at 5 seconds, the second time executes at 10 seconds.
The interval is shorter than the task execution time
For example, for a task, the interval is 2 seconds and the task execution time is 5 seconds.
Assuming the fixedDelay executes the first time at second, the second time executes at ninth.
FixedRate executes the first time at second, and the second time at seven seconds.
The configuration file
In real projects, the execution time is usually written in the configuration file so that it can be easily changed; otherwise, the code needs to be changed.
You’ve probably encountered this problem with how to write in configuration files.
In this section we solve such a problem and summarize.
cron
@Scheduled(cron = "${erwin.cron:0/2 * * * * ? } ")
public void cronTaskYmlDemo(a) {
log.info("cron yml demo");
}
Copy the code
Configuration:
erwin:
cron: 0/ 10 * * * * ?
Copy the code
If the configuration file is not configured, the default value is used.
Note that a null value does not equate to no match.
fixedDelay
In the argument explanation above, we specify that this accepts an integer and how to solve the problem.
I believe smart you, must also guess.
Yes, that’s it.
@Scheduled(initialDelay = 5, fixedDelayString = "${erwin.fixed-delay:2}", timeUnit = TimeUnit.SECONDS)
public void fixedDelayTaskYmlDemo(a) {
log.info("fixedDelay yml demo");
}
Copy the code
Configuration:
erwin:
fixed-delay: 5
Copy the code
For a quick explanation, if it is not configured in the configuration file, it is executed every 2 seconds, and if it is configured, it is executed every 5 seconds. InitialDelay says that the first task will start in 5 seconds after the project starts.
${erwin.fixed-delay:2};
fixedRate
With the above experience, I believe you will learn. Let’s look at an example.
@Scheduled(initialDelay = 5, fixedRateString = "${erwin.fixed-rate:2}", timeUnit = TimeUnit.SECONDS)
public void fixedRateTaskYmlDemo(a) {
log.info("fixedRate yml demo");
}
Copy the code
Configuration:
erwin:
fixed-rate: 5
Copy the code
Example:
2021-10-25 20:41:57.394 INFO 19368 -- [scheduling-1] C.F.D.task.demotask: FixedRate YML Demo 2021-10-25 20:41:59.394 INFO 19368 -- [scheduling-1] C.F.D.task.demotask: FixedRate YML Demo 2021-10-25 20:42:01.394 INFO 19368 -- [scheduling-1] C.F.D.ask.DemoTask: fixedRate YML DemoCopy the code
And finally, one last question, let’s look at the picture.
See the problem?
When we write the configuration, there is no prompt, and it doesn’t look very friendly.
So what’s the solution?
First introduce dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
Copy the code
Let’s write a property configuration class.
@Getter
@Setter
@Configuration
@ConfigurationProperties("erwin")
public class ErwinProperties {
private String cron;
private Long fixedDelay;
private Long fixedRate;
}
Copy the code
Did you notice Erwin?
When you first started writing the example, did you wonder why you had this prefix
Ha ha, in fact, we have already buried the foreshadowing.
Finally, take a look.
Also, at this point, when you write the match again, there will be a hint.
That’s it for today. See you next time!