Job任务

Quartz中,Job组件包含我们具体需要执行的业务代码。Quartz还具有Job的串行控制、维护状态参数等功能,下面我们详细介绍。

创建Job组件

package com.gacfox.demoquartz;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DemoJob implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        Date date = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("任务执行 " + sdf.format(date));
    }
}
// 创建任务实例
JobDetail jobDetail = JobBuilder
        .newJob(DemoJob.class)
        .withIdentity("jobDetail", "demoGroup")
        .build();

Quartz中的Job组件需要实现Job接口,具体使用时,需要对其创建JobDetail实例,然后载入调度器。

串行Job

默认情况下,Job会并发执行,也就是说之前的Job代码还没执行完,再次触发还会在新的线程中执行。有时我们需要控制Job串行执行,这可以用@DisallowConcurrentExecution注解实现。

@DisallowConcurrentExecution
public class DemoJob implements Job {
    // ...
}

设置JobDataMap参数

Quartz中Job运行时可以维护一些参数,存在于一个JobDataMap对象中。例子如下:

package com.gacfox.demoquartz;

import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class DemoJob implements Job {

    private String key;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        System.out.println("Job参数:key [" + key + "]");
    }

    public void setKey(String key) {
        this.key = key;
    }
}
// 创建任务实例
JobDetail jobDetail = JobBuilder
        .newJob(DemoJob.class)
        .withIdentity("jobDetail", "demoGroup")
        .usingJobData("key", "gacfox")
        .build();

上面代码中,我们设置了一个字符串参数,键为key,值为gacfox。Job中,我们编写了一个set方法,用于接收该参数,每次Job执行时将其打印出来。参数实际上以键值对形式存储在JobDataMap对象中,我们可以通过jobExecutionContext.getJobDetail().getJobDataMap()获取。

如上配置我们会发现,Job中只能读取参数,而主动设置这些参数是无效的,如果希望Job能够修改并持久化参数,这实际上是试图创建有状态Job,当然Quartz也支持有状态Job。

有状态Job

之前我们为Job设置了参数,但实际上这些参数每次都会被重新设置,因此上面的配置中Job每次执行时没有状态这个概念。然而如果Job中读取之前修改的参数值、并再次修改这些参数后存储,那么其实这就是一个有状态的Job。

下面是一个有状态Job例子,我们为Job设置了一个变量count,在Job每次执行时都对其加1,并输出当前是第几次执行:

package com.gacfox.demoquartz;

import org.quartz.*;

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
public class DemoJob implements Job {

    private Integer count;

    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        count++;
        jobExecutionContext.getJobDetail().getJobDataMap().put("count", count);
        System.out.println("Job参数:已执行次数 count [" + count + "]");
    }

    public void setCount(Integer count) {
        this.count = count;
    }
}

注意这里我们为Job设置了@PersistJobDataAfterExecution注解,该注解标明此Job中的参数会被持久化,否则执行时参数会被默认覆盖为JobDataMap的初始值。此外有状态Job一般都是串行执行的,因此我们还指定了@DisallowConcurrentExecution注解,并发执行可能造成状态数据混乱。

有状态Job的配置例子如下。

// 创建任务实例
JobDetail jobDetail = JobBuilder
        .newJob(DemoJob.class)
        // 这里设置任务名和任务组名,用于和触发器关联
        .withIdentity("jobDetail", "demoGroup")
        .storeDurably(true)
        .usingJobData("count", 0)
        .build();

代码中,我们除了设置JobDataMap,还设置了storeDurably(true),表示持久化状态数据。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap