侧边栏壁纸
  • 累计撰写 25 篇文章
  • 累计创建 27 个标签
  • 累计收到 43 条评论

目 录CONTENT

文章目录

Quartz Job和JobDetail详解

junior
2022-06-22 / 0 评论 / 2 点赞 / 729 阅读 / 3,363 字

Job接口包含什么

Job接口非常容易实现,它只有一个execute方法。从上篇文章可以了解到这个方法中有一个JobExecutionContext参数,它保存着当前Job的所有信息。

JobDetail用来干什么

当你实现Job接口类,Quartz需要你提供job实例的各种参数,Job接口实现类中的代码才知道如何去完成指定类型Job的实际工作。这个过程是通过JobDetail类来完成的。(以下代码可以在后续Springboot2.0整合Quartz中找到)

//创建一个新的job任务
    @GetMapping("/add/{jobName}")
    public void addJob(@PathVariable(value = "jobName") String jobName) {
        String groupName = "group_one"; //定义job所在组名称
        String cronExpression = "0 * * * * ? *";//执行时间表达式
        try {

            //构建一个新的任务规范,执行特定任务,任务执行的时间
            JJobDetail jobDetail = JobBuilder.newJob(SampleJob.class).withIdentity(jobName, groupName)
                    .usingJobData("jobSays", "Hello World!")
                    .build();
            //执行的任务中传入参数
            jobDetail.getJobDataMap().put("jobname", jobName);
            //创建corn表达式,创建执行任务的时间规范
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            //创建一个触发器,加入上面创建的时间规范
            CronTrigger trigger =
                            TriggerBuilder.newTrigger().withIdentity(jobName, groupName).withSchedule(scheduleBuilder)
                                            .build();

            //把执行的job任务和创建时间trigger绑定一起
            scheduler.scheduleJob(jobDetail, trigger);

            //启动任务调度器,准备添加任务相关信息操作
            scheduler.start();
        } catch (SchedulerException e) {
            LOGGER.info("scheduler start or shutdown error ...");
        }
    }

下面是任务SampleJob.class

public class SampleJob implements Job {

    @Autowired
    @Qualifier(value = "Scheduler")
    private Scheduler scheduler;

    public SampleJob() {
    }

    @Override
    public void execute(JobExecutionContext context) {
        String id = context.getJobDetail().getJobDataMap().get("jobname").toString();
        id = id + ">";
        System.out.println("执行方法。。。。。" + id);
        context.getJobDetail().getJobDataMap().put("jobname", id);
        try {
            scheduler.addJob(context.getJobDetail(), true, true);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }
}

从上面代码可以注意到我们给scheduler提供了一个JobDetail实例,我们构建JobDetail对象时不仅提供了job的class对象,还定义了JobKey,并且通过JobDataMap为Job传递参数。调度器就知道它要执行的job类型。每次调度器执行job时,它在调用excecute方法前会创建一个新的job实例,同时将传递的参数作为实例参数,以便于我们后续跟踪状态。

JobDataMap的作用

JobDataMap是JobDetail的一部分

  1. 为Job传入参数
    JobDataMap可以用来持有任何可序列化的数据对象,当job实例对象被执行时这些参数对象会传递给它。JobDataMap实现Map接口,并且添加了一些非常方便的方法用来存取基本数据类型。
    下面的代码片断演示了在定义/构建JobDetail对象时,job对象添加到调度器之前,如何将数据存放至JobDataMap中:
//构建一个新的任务规范,执行特定任务,任务执行的时间
JobDetail jobDetail = JobBuilder.newJob(SampleJob.class).withIdentity(jobName, groupName)
                    .usingJobData("jobSays", "Hello World!")   		//  1.使用usingJobData直接赋值
                    .build();
            //执行的任务中传入参数
jobDetail.getJobDataMap().put("jobname", jobName);  	// 2.先获取JobDataMap,然后再填入参数
  1. 在Job中获取传递的参数
    我们可以从Job的JobExecutionContext中获取JobDetail,然后获取JobDataMap,最后从JobDataMap中按键取出参数内容。
@Override
public void execute(JobExecutionContext context) {
        String id = context.getJobDetail().getJobDataMap().get("jobname").toString();
        id = id + ">";
        System.out.println("执行方法。。。。。" + id);
}

Job实例

你可以创建一个单独的Job实现类,创建多个不同的JobDetail实例,将不同Job实例定义存储在调度器中,每个JobDetail实例都有各自的参数和JobDataMap,并且把这些JobDetail添加到调度器中。

例如:你创建一个Job接口的实现类,类名为“SalesReportJob”,Job类可以预先传入一些假想的参数(通过JobDataMap)来指定销售报表中业务员的名字。接下来创建多个Job的定义(即JobDetail),如“SalesReportForJoe”和 “SalesReportForMike”通过“Joe”和“Mike”指定到相应的JobDataMap中作为参数输入到各自的Job对象中。

当trigger被触发时,相关的JobDetail实例会被加载,通过在调度器中配置的JobFactory会将关联的Job类实例化。默认的JobFactory只是简单的调用Job类的newInstance方法,然后尝试调用匹配JobDataMap键值的setter方法。你可以开创建自己的JobFactory实现类,以完成一些诸如通过应用IOC或DI机制完成Job实例的创建和初始化的事情。

用Quartz框架的话来说,我们将每个存储的JobDetail称为Job定义或JobDetail实例,将每个执行的作业任务(Job)称为Job实例或Job定义实例。通常我们只用“job”单词来对应命名的Job定义或是JobDetail。当我们指Job接口的实现类时,一般使用“job class”术语。

上一篇:Quartz简单使用以及常用API解释
下一篇:Quartz Trigger详解

2

评论区