Springboot integrates quarzt to realize dynamic timing task

Time:2019-12-30

Several ways to implement timed tasks:

1. Using crontab of Linux

Advantage:
    1. It is easy to use, as long as it is written in crontab
    2. It can be modified at any time without restarting the server
Disadvantages:
    1. The distributed system is not easy to use and can only be modified by one machine
    2. Minute is the minimum time unit, and second level cannot be used

2. Use the scheduledexecutor that comes with spring

Advantage:
    Cronexpression is more powerful than crontab. It supports seconds and has better performance
Disadvantages:
    The server restart of cronexpression has been modified, otherwise it will not take effect

3. Use timer provided by JDK

Advantage: 
    Lightweight, fast execution
Disadvantages:
    The distributed system is not easy to use and cannot be executed at a specified time, but only at a certain frequency

4. Use quartz

Advantage:
    1. It can be applied to distributed system and quartz can support cluster mode
    2. It is not necessary to restart the server after modifying the timing task (this is just some advantages and disadvantages that I think of personally, netizens can leave a message with other opinions)

Integration steps:

Now that we know that quartz is so excellent, how can we integrate it into the project? Next, the author will implement a small function to trigger dynamic timing task through HTTP interface call
Environment used by the author:

jdk:1.8.0_162;
springboot:1.5.10.RELEASE

1. Introduce the required jar package, add the jar package of quartz and spring jar supporting quartz in POM file

         <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

2. Configure the bean of the scheduler. Here, spring implements three factory classes: schedulerfactorybean, crontriggerbean, and jobdetailbean. These three classes are handed over to spring management by annotation. Generally, the online materials are all these three classes, which are handed over to spring management. You can refer to this article.
In my case, the timing task is triggered through the interface, so only the scheduler that implements the schedulerfactorybean below can be used. If you don’t understand what these classes are for, you can read the articles used by quartz.
Let me just say:
Scheduler: task scheduler, job: specific task class, trigger: trigger, which determines when the task is executed. That is to say, what the time person does, the scheduler is the subject person, the trigger is the time, and the job is to do.

@Configuration
public class SchedulerConfig {

    /**
     * attention:
     *Details: define the quartz scheduling factory
     */
    @Bean(name = "scheduler")
    public SchedulerFactoryBean schedulerFactory() {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        //For quartz cluster, update existing jobs when quartzscheduler starts
        bean.setOverwriteExistingJobs(true);
        //Delay start, 1 second after application start
        bean.setStartupDelay(1);
        return bean;
    }
}

3. For the specific task class job, you must implement the job class of quartz. This can also implement the spring’s quartjobbean (the spring’s implementation of the job class). Or there is another way to do this: methodinvokingjobdetailfactorybean. In this class, you can set what kind of method to perform this task, which will be more flexible:

@Slf4j
public class ScheduleTaskJob implements Job {

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Log.info ("task executed...");
    }
}

4. HTTP interface to trigger the scheduler:

@Slf4j
@RestController
public class Controller {

    @Resource(name = "scheduler")
    private Scheduler scheduler;

    @PostMapping(value = "/api/executeTask")
    public String executeTask(TaskVO taskVO) {
        // job class
        JobDetail jobDetail = JobBuilder.newJob(ScheduleTaskJob.class)
               .withIdentity(taskVO.getJobName(), taskVO.getJobGroupName())
                .build();
        //Trigger class
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity(taskVO.getTriggerName(), taskVO.getTriggerGroupName())
                .startNow()
                .withSchedule(cronSchedule(taskVO.getCronExpression()))
                .build();
        try {
            //Perform task
            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            Log.error ("task execution exception", e);
        }
        return "success";
    }
}

5. The value object passed in by HTTP interface is actually used to specify the name and groupname of job and Trier. If the name is the same, it will fail. It must be unique,
6. Execute the program to see the effect:
Parameters I passed in:
jobName:job1
jobGroupName:jobGroup1
triggerName:trigger1
triggerGroupName:triggerGroup1
cronExpression:0/1 ?

jobName:job2
jobGroupName:jobGroup1
triggerName:trigger2
triggerGroupName:triggerGroup1
cronExpression:0/1 ?
Springboot integrates quarzt to realize dynamic timing task
In the red box, there is only one scheduled task at the top, which is executed every second. In the lower part, because a new task is added, the answer leads to the execution results of two tasks.

Pit encountered:

1.java.lang.NoSuchMethodError: org.springframework.boot.SpringApplication.run(Ljava/lang/Object;[Ljava/lang/String;)Lorg/springframework/context/ConfigurableApplicationContext;
Solution: This is due to the incompatibility of springboot2, so using springboot1.5 will not cause this error.

2.Caused by: java.lang.ClassNotFoundException: org.springframework.transaction.PlatformTransactionManager

at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_162]
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_162]
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) ~[na:1.8.0_162]
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_162]
39 common frames omitted
If this error is reported during startup, a package of spring TX things should be introduced
 <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
 </dependency>

Source address: the source address of GitHub. My friends think it’s OK to write it. Star, follower, 23333. Thank you~

reference material:

[1]https://blog.csdn.net/liuchua…
[2]https://www.w3cschool.cn/quar…
[3]https://www.ibm.com/developer…
[4]http://www.quartz-scheduler.org/

Recommended Today

PHP realizes UnionPay business H5 payment

UnionPay business H5 payment interface document: document address 1: H5 payment interface address: 1: Alipay payment Test address: http://58.247.0.18:29015/v1/netpay/trade/h5-pay Official address: https://api-mop.chinaums.com/ 2: UnionPay payment Test address: http://58.247.0.18:29015/v1/netpay/uac/order Official address: https://api-mop.chinaums.com/ 2: Basic parameters required by the interface The interface uses get parameters. After the interface parameters are directly put into the interface address, the […]