【问题标题】:how to configure spring job dynamically using quartz scheduler如何使用石英调度程序动态配置弹簧作业
【发布时间】:2016-07-15 07:11:45
【问题描述】:

我是 Spring Batch 框架和石英调度程序的新手。我的任务是使用石英调度程序动态调度一个新的 Spring Batch 作业。所有新的春季批处理作业的条目都在我的数据库中,带有触发器表达式。问题是,对于来自数据库的每个新的 spring 批处理作业,我们需要将其包装在quartz 的调度程序作业中。所以意味着有尽可能多的春季批处理作业,应该有许多批处理作业类来包装它们并由石英调度程序运行。

quartz 将所有作业和触发器条目存储到它自己的数据库表中。我在配置文件中配置。这项工作将永远是石英的工作,而不是春季批处理工作。 这是我的主要方法,这里我将编写我的数据库连接代码以找出新的springbatch作业名称和触发器表达式并将它们与石英调度绑定

 public static void main(String[] args) {
      try {

        ApplicationContext context = new ClassPathXmlApplicationContext("quartz-context.xml");              
        JobLauncher launcher=(JobLauncher) context.getBean("jobLauncher");
        JobLocator locator= (JobLocator) context.getBean("jobRegistry");
        Scheduler schedulerFactoryBean=(Scheduler) context.getBean("quartzSchedulerFactoryBean");

        JobDetail job = newJob(SpringBatchJob.class).withIdentity("myJob001", "group1").build();

        Trigger trigger1 =newTrigger().withIdentity("myTrigger001", "group1").startNow().withSchedule(simpleSchedule().withIntervalInSeconds(10).repeatForever()).build();

          schedulerFactoryBean.scheduleJob(job, trigger1);

           schedulerFactoryBean.start();              

      } catch (SchedulerException e) {
           e.printStackTrace();
      }
 }

在这里我们可以看到我们有jobDetail,它是quartz job,它的execute方法用于运行spring batch job。

springBatchjob.java

public class SpringBatchJob implements Job {

private String jobName;
private String batchJob;

private JobLocator jobLocator;

private JobLauncher jobLauncher;

private File contentDirectory;

private String directoryPath = "inputFiles";

public void init(){
    contentDirectory = new File(directoryPath);
}

boolean fileFound = false;


public void performJob(String str) {}


public String getJobName() {
    return jobName;
}

public void setBatchJob(String batchJob) {
    this.batchJob = batchJob;
}

public void setJobName(String jobName) {
    this.jobName = jobName;
}

public void setJobLocator(JobLocator jobLocator) {
    this.jobLocator = jobLocator;
}

public void setJobLauncher(JobLauncher jobLauncher) {
    this.jobLauncher = jobLauncher;
}

@Override
public void execute(JobExecutionContext arg0) throws org.quartz.JobExecutionException {
    JobParameter jb= new JobParameter(5L);
    Map<String, JobParameter> map= new HashMap<>();
    map.put(jobName,jb);
     ApplicationContext context = new ClassPathXmlApplicationContext("quartz-context.xml");             
     JobLauncher launcher=(JobLauncher) context.getBean("jobLauncher");
        JobLocator locator= (JobLocator) context.getBean("jobRegistry");
        setJobLauncher(launcher);
        setJobLocator(locator);
        setJobName("helloWorldJob");
    // TODO Auto-generated method stub
    JobExecution result = null;
    try {
        result = jobLauncher.run(jobLocator.getJob(jobName), new JobParameters(map));
    } catch (JobExecutionAlreadyRunningException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JobRestartException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JobInstanceAlreadyCompleteException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JobParametersInvalidException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchJobException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } 
    System.out.println("ExamResult Job completetion details : "+result.toString());

}

setJobName 方法中,我正在对我的春季批处理作业名称进行硬编码, 但是在我的项目中,我们有近 800 个工作,因此根据方法,我们需要制作 800 个包装类。

请帮助我,如何通过制作泛型类来解决此解决方案。

【问题讨论】:

    标签: java spring spring-mvc spring-batch quartz-scheduler


    【解决方案1】:

    我真诚地希望您并没有真正使用该类,它最终会在您一遍又一遍地重新创建应用程序时吃掉您的所有内存。

    Spring 已经支持石英,尤其是以SpringBeanJobFactory 的形式构建作业,您可以利用它来发挥自己的优势,特别是如果您使用一些自动布线功能对其进行扩展。

    public class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
    
        private ApplicationContext context;
    
        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
    
            Object object = super.createJobInstance(bundle);
            context.getAutowireCapableBeanFactory().autowireBean(object);
            return object;
        } 
    
        public void setApplicationContext(ApplicationContext applicationContext) {
            this.context=applicationContext;
        }
    }
    

    然后将你的工作类改写成这样

    public class SpringBatchJob implements Job {
    
        private final Logger logger = LoggerFactory.getLogger(SpringBatchJob.class);
    
        private String jobName;
    
        @Autowired
        private JobLocator jobLocator;
    
        @Autowired
        private JobLauncher jobLauncher;
    
        @Override
        public void execute(JobExecutionContext context) throws org.quartz.JobExecutionException {
    
            JobDataMap JobDataMap = context.getMergedJobDataMap();
            JobParametersBuilder builder = new JobParametersBuilder();
            for (Map.Entry<String, Object) param : jobDataMap.entrySet()) {
                String key = param.getKey();
                Object val = param.getValue();
                builder.addString(key, String.valueOf(val)); // Or make it smarter by doing type detection.
            }
    
            Job jobToLaunch = jobLocator.getJob(jobName);
            JobExecution result;
            try {
                result = jobLauncher.run(jobToLaunch, builder.to);
            } catch (JobExecutionException e) {
                throw new org.quartz.JobExecutionException("Exception execution job '"+this.jobName+"'", e);
            } finally {
                logger.info("{}  Job completetion details ", this.jobName, result);
            }
        }
    }
    

    现在您需要通过设置jobFactory 属性来配置SchedulerFactoryBean 以使用AutowiringSpringBeanJobFactory。完成后,您只需要适当地配置石英作业。

    对于您发布的示例,以下将在触发启动时启动helloWorldJob

    public static void main(String[] args) {
          try {
    
            ApplicationContext context = new ClassPathXmlApplicationContext("quartz-context.xml");              
            JobLauncher launcher=(JobLauncher) context.getBean("jobLauncher");
            JobLocator locator= (JobLocator) context.getBean("jobRegistry");
            Scheduler schedulerFactoryBean=(Scheduler) context.getBean("quartzSchedulerFactoryBean");
    
            JobDetail job = newJob(SpringBatchJob.class)
                              .withIdentity("myJob001", "group1")
                              .usingJobData("jobName", "helloWorldJob")
                              .build();
    
            Trigger trigger1 =newTrigger().withIdentity("myTrigger001", "group1")
                              .startNow()
                              .withSchedule(simpleSchedule().withIntervalInSeconds(10).repeatForever())
                              .build();
    
              schedulerFactoryBean.scheduleJob(job, trigger1);
              schedulerFactoryBean.start();              
    
          } catch (SchedulerException e) {
               e.printStackTrace();
          }
     }
    

    注意.usingJobData("jobName", "helloWorldJob")SpringBeanJobFactory 将尝试满足SpringBatchJob 类上的所有设置方法。这有一个setJobName,它会在启动时注入helloWorldJob。该功能由AutowiringSpringBeanJobFactory 扩展,还可以从 Spring Batch 自动连接所需的基础设施 bean。

    如果您需要将其他属性传递给 Spring Batch 作业(例如要使用的键或其他信息,只需添加另一个 usingJobData("your-property", your-value)。修改后的 SpringBatchJob 将在启动作业之前将所有 quarts 作业参数映射到 Spring Batch 参数.

    注意:这是从我的脑海中输入的,我还没有实际测试过,但它至少应该让你知道如何做到这一点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多