当前位置: 首页 > 面试题库 >

在数据库中持久保存Quartz触发器的正确​​方法

令狐宜民
2023-03-14
问题内容

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

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

特别是, 我需要将计划的任务保存 在数据库中,以便在重新启动应用程序时可以将其重新初始化。

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


问题答案:

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

首先,在我的Spring配置中,指定一个SchedulerFactoryBean可以将注入Scheduler其他bean的。

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

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

@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。还要注意,我使用存储库将作业存储在数据库中。

/**
 * 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();
    }
}

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

<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接口的每个作业的实例。使用这些数据库记录中的信息,我可以使用调度程序实用程序来重建作业。

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



 类似资料:
  • 我想写一个脚本,它将2 GB的数据从硬盘加载到内存中,然后当其他程序请求时,它必须得到一个输入,并根据输入对这个数据进行一些计算。对我来说,重要的是将这2 GB的数据持久地保存在内存中,以加快计算速度,更重要的是避免巨大的I/O负载。 我应该如何将数据永远保存在内存中?或者更一般地说,我应该如何在Python中解决这样的问题?

  • 当我尝试将Point datatype持久化到postgres DB时,它失败了,错误org.postgresql.util.PSQLE:错误: ERROR:列“Point Col就列”是点类型,但表达式是几何类型 这是我的波乔快照 这是我的驱动程序和方言属性 驱动程序org.postgresql. dialect = org . hibernate . spatial . dialect . p

  • 问题内容: 让我解释一下:我并不是在问将特定日期时间的时区存储在数据库中的正确方法。我说的是时区本身。例如: 我有一个名为“用户”的MySQL表。现在,在此表上,我希望有一列包含用户居住地的时区(由用户提供,将从列表中选择)。我正在使用PHP,其中包含类似以下时区字符串的列表: 美国时区列表 现在,显而易见的解决方案(至少对我而言)是在“用户”表中创建VARCHAR列,然后将PHP使用的时区字符串

  • 目的 配置 NFS 共享为 OpenShift 节点提供存储,并且配置 OpenShift 持久卷以绑定至数据库 Pod。 环境 openshift v3.11.16/kubernetes v1.11.0 步骤 配置 NFS 共享持久卷1. 登录到 NFS 服务器 # ssh nfs.example.com2. 创建 config-nfs.sh 脚本,内容如下 #!/usr/bin/sh exp

  • 问题内容: 我是Java和Android开发的新手,我想问一下将数据存储到持久性存储的可用方法是什么?例如,我想在数据库或文件中存储字符串的集合。 请指教。谢谢。 问题答案: 正如您在问题本身中所说的那样,您可以使用文件或数据库。如果有更多数据,则可以使用文件和数据库(SQLITE);如果数据量较小,则也可以使用SharedPreferences。以下是其中所有链接的一个链接关于Android中的

  • 我在研究内存数据库的概念。有关这方面的文章说, 内存数据库系统是一种将数据完全存储在主存中的数据库管理系统。 他们讨论了这个概念的优点和缺点。 我的问题是如果这些数据库管理系统将数据完全存储在主存储器中, 停电后所有数据都消失了吗??? 还是有办法保护数据???