Quartz

该扩展组件支持通过用户界面管理 Quartz 任务:

  • 使用已有的 org.quartz.Job 接口实现创建新的 Quartz 任务。

  • 暂停和继续执行任务。

  • 触发非活动任务的立即执行。

  • 编辑任务触发器和参数。

  • 删除任务。

安装

按照 扩展组件 章节的说明进行安装。

手动安装,需在 build.gradle 文件添加下列依赖:

implementation 'io.jmix.quartz:jmix-quartz-starter'
implementation 'io.jmix.quartz:jmix-quartz-flowui-starter'

使用

按照下列步骤创建并设定任务计划:

  1. 创建一个类,实现 org.quartz.Job 接口。调度器会执行其 execute() 方法。示例:

    package quartz.ex1.app;
    
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class SampleJob implements Job {
    
        private static final Logger log = LoggerFactory.getLogger(SampleJob.class);
    
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            log.info("Sample job is executed");
        }
    }

    在任务类中,可以用 @Autowired 注入 Spring bean。

  2. 启动应用程序,打开 Quartz → Quartz jobs(Quartz 任务) 界面,并点击 Create(新建)

    • Name(名称) 字段输入一个唯一的名称,并在 Class(类) 字段选择任务类。

      Group(分组) 字段是可选的,用于在 UI 中对任务进行分组。

    • Triggers(触发器) 标签页为任务创建至少一个触发器。可以选择 Cron expression(Cron 表达式)Simple(简易) 调度类型。前一种方式需要输入一个 Cron 表达式,例如,0/5 * * ? * * *(每一个第五秒)。后一种方式仅需输入任务执行的重复周期(单位为毫秒)。

    保存触发器和任务之后,会根据触发器的设置立即开始调度。

    如需修改任务设置,首先选中任务并点击 Pause(暂停)。保存修改后,可以点击 Resume(继续) 继续任务调度。

    也可以点击 Execute now(马上执行) 按钮开始执行任一注册的任务,即便任务此时还没有触发器。该功能方便测试。

任务中的认证

调度器执行的代码未经认证,即未与任何用户关联。

如需调用需要认证的操作,例如,通过 DataManager 处理数据,可以使用 SystemAuthenticator@Authenticated 注解:

public class SampleAuthenticatedJob implements Job {

    private static final Logger log = LoggerFactory.getLogger(SampleAuthenticatedJob.class);

    @Autowired
    private DataManager dataManager;

    @Authenticated
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        int usersCount = dataManager.load(User.class).all().list().size();
        log.info("There are {} registered users", usersCount);
    }
}
还可以使用 UnconstrainedDataManager 在未认证的上下文中处理数据。

任务参数

Job editor 视图的 Job data parameters(任务数据参数) 标签页可以为任务实例设置参数。可以像下面这样在任务类中使用参数:

public class SampleParameterizedJob implements Job {

    private static final Logger log = LoggerFactory.getLogger(SampleParameterizedJob.class);

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
        String paramStr = jobDataMap.entrySet().stream()
                .map(e -> e.getKey() + " : " + e.getValue())
                .collect(Collectors.joining(", ", "[", "]"));
        log.info("Sample job is executed with parameters: " + paramStr);
    }
}

跟踪任务执行

如需跟踪任务的执行,创建一个 bean,实现 JobListener 接口,或继承 JobListenerSupport

package quartz.ex1.app;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.listeners.JobListenerSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class JobExecutionListener extends JobListenerSupport {

    private static final Logger log = LoggerFactory.getLogger(JobExecutionListener.class);

    @Autowired
    private Scheduler scheduler;

    @Override
    public String getName() {
        return "SampleJobExecutionListener";
    }

    @PostConstruct
    private void registerListener() { (1)
        try {
            scheduler.getListenerManager().addJobListener(this);
        } catch (SchedulerException e) {
            log.error("Cannot register job listener", e);
        }
    }

    @Override
    public void jobWasExecuted(JobExecutionContext context,
                               JobExecutionException jobException) { (2)
        log.info("jobWasExecuted: name={}, context={}",
                context.getJobDetail().getKey().getName(), context);
    }
}
1 bean 初始化完成后由 Spring 调用。
2 任务执行完成后,由 Quartz 调度器调用。

jobWasExecuted() 方法内,可以将任务的执行结果保存至日志或者数据库。