本文介绍了在数据库中持久保存Quartz触发器的正确​​方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Quartz很新,现在我需要在Spring Web应用程序中安排一些工作。

I'm quite new to Quartz and now I need to schedule some jobs in Spring web application.

我知道Spring + Quartz集成(我正在使用Spring v 3.1.1)但我想知道这是否是正确的方法。

I know about Spring + Quartz integration (I'm using Spring v 3.1.1) but I'm wondering if this is the right way to follow.

特别是我需要坚持我的预定任务在数据库中,所以我可以在重新启动应用程序时重新初始化它们。

In particular I need to persist my scheduled tasks in a DB so I can re-initialize them when application is restarted.

Spring调度包装器是否提供了一些实用程序来执行此操作?
你能建议我采用一些众所周知的方法吗?

Are there some utilities provided by Spring scheduling wrapper to do this?Can you suggest me some "well known" approach to follow?

推荐答案

这是我处理这种情况的一种方法。

Here is one way I handle this scenario.

首先在我的Spring配置中指定一个 SchedulerFactoryBean 我可以从中注入调度程序到其他bean中。

First in my Spring Configuration I specify a SchedulerFactoryBean from which I can inject the Scheduler into other beans.

<bean name="SchedulerFactory"
    class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="applicationContextSchedulerContextKey">
        <value>applicationContext</value>
    </property>
</bean>

然后,当我在应用程序中创建作业时,我将作业的详细信息存储在数据库中。这个服务由我的一个控制器调用,它安排工作:

Then when I create a job in my application I store the details of the job in the database. This service is called by one of my controllers and it schedules the job:

@Component
public class FollowJobService {

    @Autowired
    private FollowJobRepository followJobRepository;

    @Autowired
    Scheduler scheduler;

    @Autowired
    ListableBeanFactory beanFactory;

    @Autowired
    JobSchedulerLocator locator;

    public FollowJob findByClient(Client client){
        return followJobRepository.findByClient(client);
    }

    public void saveAndSchedule(FollowJob job) {
        job.setJobType(JobType.FOLLOW_JOB);
        job.setCreatedDt(new Date());
        job.setIsEnabled(true);
        job.setIsCompleted(false);

        JobContext context = new JobContext(beanFactory, scheduler, locator, job);
        job.setQuartzGroup(context.getQuartzGroup());
        job.setQuartzName(context.getQuartzName());

        followJobRepository.save(job);

        JobSchedulerUtil.schedule(new JobContext(beanFactory, scheduler, locator, job));
    }
}

JobContext 我构建包含有关作业的详细信息,并最终传递给用于调度作业的实用程序。以下是实际调度作业的实用程序方法的代码。请注意,在我的服务中,我自动装载 JobScheduler 并将其传递给 JobContext 。另请注意,我使用我的存储库将作业存储在数据库中。

The JobContext I build contains detail about the job and is eventually passed to a utility for scheduling jobs. Here is that code for the utility method that actually schedules the job. Notice that in my service I autowire the JobScheduler and pass it to the JobContext. Also notice that I store the job in the database using my repository.

/**
 * Schedules a DATA_MINING_JOB for the client. The job will attempt to enter
 * followers of the target into the database.
 */
@Override
public void schedule(JobContext context) {
    Client client = context.getNetworkSociallyJob().getClient();
    this.logScheduleAttempt(context, client);

    JobDetail jobDetails = JobBuilder.newJob(this.getJobClass()).withIdentity(context.getQuartzName(), context.getQuartzGroup()).build();
    jobDetails.getJobDataMap().put("job", context.getNetworkSociallyJob());
    jobDetails.getJobDataMap().put("repositories", context.getRepositories());

    Trigger trigger = TriggerBuilder.newTrigger().withIdentity(context.getQuartzName() + "-trigger", context.getQuartzGroup())
            .withSchedule(cronSchedule(this.getSchedule())).build();

    try {
        context.getScheduler().scheduleJob(jobDetails, trigger);
        this.logSuccess(context, client);

    } catch (SchedulerException e) {
        this.logFailure(context, client);
        e.printStackTrace();
    }
}

所有这些代码执行后我有两件事情发生了,我的工作是存储在数据库中,并使用quartz调度程序进行了调度。现在,如果应用程序重新启动,我想使用调度程序重新安排我的作业。为此,我注册了一个实现 ApplicationListener< ContextRefreshedEvent> 的bean,每次容器重启或启动时都会被Spring调用。

So after all of this code executes I two things have happened, my job is store in the database and its been scheduled using the quartz scheduler. Now if the application restarts I want to reschedule my jobs with the scheduler. To do this I register a bean that implements ApplicationListener<ContextRefreshedEvent> which is called by Spring each time the container restarts or is started.

<bean id="jobInitializer" class="com.network.socially.web.jobs.JobInitializer"/>

JobInitializer.class

public class JobInitializer implements ApplicationListener<ContextRefreshedEvent> {

    Logger logger = LoggerFactory.getLogger(JobInitializer.class);

    @Autowired
    DataMiningJobRepository repository;

    @Autowired
    ApplicationJobRepository jobRepository;

    @Autowired
    Scheduler scheduler;

    @Autowired
    JobSchedulerLocator locator;

    @Autowired
    ListableBeanFactory beanFactory;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        logger.info("Job Initilizer started.");

        //TODO: Modify this call to only pull completed & enabled jobs
        for (ApplicationJob applicationJob : jobRepository.findAll()) {
            if (applicationJob.getIsEnabled() && (applicationJob.getIsCompleted() == null || !applicationJob.getIsCompleted())) {
                JobSchedulerUtil.schedule(new JobContext(beanFactory, scheduler, locator, applicationJob));
            }
        }
    }

}

此类自动装配调度程序和存储库,该存储库用于获取实现 ApplicationJob 接口的每个作业的实例。使用这些数据库记录中的信息,我可以使用我的调度程序实用程序重建我的作业。

This class autowires the scheduler and a repository that grabs instances of each of my jobs that implement the ApplicationJob interface. Using the information from these database records I can use my scheduler utility to reconstruct my jobs.

所以基本上我手动将作业存储在我的数据库中并通过注入一个来手动调度它们适当bean中的 Scheduler 的实例。要重新安排它们,我查询我的数据库,然后使用 ApplicationListener 安排它们来计算容器的重启和启动。

So basically I manually store the jobs in my database and manually schedule them by injecting a instance of the Scheduler in appropriate beans. To rescheduled them, I query my database and then schedule them using the ApplicationListener to account for restarts and starts of the container.

这篇关于在数据库中持久保存Quartz触发器的正确​​方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 01:08