Spring 和 Quartz 与 Java Config 的集成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31764078/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 19:05:19  来源:igfitidea点击:

Spring and Quartz integration with Java Config

javaquartz-schedulerspring-annotations

提问by hadi

I searched a lot, but i couldn't fine any post or comment or any complete code on integrating spring and quartz and store the quartz config in database with java config (XML-LESS) could anyone help me and show me some code or reference ? thanks a lot

我搜索了很多,但我无法找到任何关于集成 spring 和石英的帖子或评论或任何完整的代码,并将石英配置存储在带有 java 配置(XML-LESS)的数据库中,任何人都可以帮助我并向我展示一些代码或参考? 多谢

回答by Sushil

We can implement it like this -
1) Annotations

我们可以像这样实现它 -
1) 注释

Class level Annotation :
Only this class will be scan for quartz support-

班级注释:
只有这个班级会扫描石英支持-

package com.example.config;  

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface QuartzJob{


}


Method Level Annotation : Annotation holds property of quartz configuration


方法级注释:注释持有石英配置的属性

package com.example.config;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Cron {

    String name();

    String group() default "DEFAULT_GROUP";

    String cronExp();

    String timeZone() default "Europe/London";
}

2) create Beans holding methods to run as cron job

2) 创建 Beans 持有方法作为 cron 作业运行

package com.example.job;
public class AnotherBean  {
public void print(){
    System.out.println("I am printing in another bean");
}
}
package com.example.job;

import org.springframework.beans.factory.annotation.Autowired;

import com.example.config.Cron;
import com.example.config.QuartzJob;


@QuartzJob
public class MyJobOne {

    @Autowired
    private AnotherBean anotherBean;
    protected void myTask() {
        System.out.println("This is my task");
    }

    protected void myTask1() {
        System.out.println("This is love task");
    }


    @Cron(name="abc", cronExp="* * * * * ? *", timeZone="Asia/Kolkata")
    protected void scheduleMyJob() {
        System.out.println("This is lovely task");
        anotherBean.print();
    }

    @Cron(name="xyz", cronExp="0 35 9 ? * MON-FRI", timeZone="Asia/Kolkata")
    protected void scheduleMyJob1() {
        System.out.println("This is hate task");
    }
}

3) Listener to look into bean and initiate Job

3)监听bean并启动Job

package com.example.config;


import java.lang.reflect.Method;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.ReflectionUtils.MethodCallback;

public class QuartJobSchedulingListener implements ApplicationListener<ContextRefreshedEvent>
{ 


 @Override
 public void onApplicationEvent(ContextRefreshedEvent event)
 {
  try 
  {
    ApplicationContext applicationContext = event.getApplicationContext();
    List<CronTrigger> cronTriggerBeans = this.loadCronTriggerBeans(applicationContext);
    if(cronTriggerBeans.size() > 0){
        SchedulerFactoryBean schedulerFactoryBean =  applicationContext.getBean(SchedulerFactoryBean.class, cronTriggerBeans);
        schedulerFactoryBean.start();
    }

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

 private List<CronTrigger> loadCronTriggerBeans(ApplicationContext applicationContext)
 {
   Map<String, Object> quartzJobBeans = applicationContext.getBeansWithAnnotation(QuartzJob.class);

   Set<String> beanNames = quartzJobBeans.keySet();

   List<CronTrigger> cronTriggerBeans = new ArrayList<CronTrigger>();

   for (String beanName : beanNames) 
   {
     Object bean = quartzJobBeans.get(beanName);

     ReflectionUtils.doWithMethods(bean.getClass(), new MethodCallback(){

        @Override
        public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
            if(method.isAnnotationPresent(Cron.class)){
                Cron cron = method.getAnnotation(Cron.class);
                System.out.println("Scheduling a job for "+ bean.getClass()+ " and method "+method.getName());
                MethodInvokingJobDetailFactoryBean jobDetailFactoryBean = new MethodInvokingJobDetailFactoryBean();
                jobDetailFactoryBean.setName(beanName+"."+cron.name()+"."+method.getName());
                jobDetailFactoryBean.setTargetMethod(method.getName());
                jobDetailFactoryBean.setTargetObject(bean);

                try {
                    jobDetailFactoryBean.afterPropertiesSet();
                } catch (ClassNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                CronTriggerFactoryBean triggerFactoryBean = new CronTriggerFactoryBean();

                triggerFactoryBean.setJobDetail(jobDetailFactoryBean.getObject());
                triggerFactoryBean.setName(beanName+"_trigger_"+method.getName());
                triggerFactoryBean.setCronExpression(cron.cronExp()); 
                GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone(cron.timeZone()));
                System.out.println(calendar.getTime());
                triggerFactoryBean.setStartTime(calendar.getTime());
                triggerFactoryBean.setTimeZone(TimeZone.getTimeZone(cron.timeZone()));

                try {
                    triggerFactoryBean.afterPropertiesSet();
                    System.out.println(triggerFactoryBean.getObject().getFinalFireTime());
                    System.out.println(triggerFactoryBean.getObject().getCronExpression());
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                cronTriggerBeans.add(triggerFactoryBean.getObject());
            }
        }

     });

   }

   return cronTriggerBeans;
 }


 public Trigger getCronTrigger(String cronExpression){
      CronScheduleBuilder cronScheduleBuilder=null;
      Trigger cronTrigger=null;
      cronScheduleBuilder=CronScheduleBuilder.cronSchedule(cronExpression);
    cronScheduleBuilder.withMisfireHandlingInstructionFireAndProceed();
    TriggerBuilder<Trigger> cronTtriggerBuilder=TriggerBuilder.newTrigger();
    cronTtriggerBuilder.withSchedule(cronScheduleBuilder);
    cronTrigger=cronTtriggerBuilder.build();

      return cronTrigger;
    }

}

4) Creating JavaConfig class-

4) 创建 JavaConfig 类-

package com.example.config;

import java.util.List;

import org.quartz.CronTrigger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import com.example.job.AnotherBean;
import com.example.job.MyJobOne;

@Configuration 
public class QuartzConfiguration {

    @Bean
    public QuartJobSchedulingListener quartJobSchedulingListener(){
        return new QuartJobSchedulingListener();
    }

    @Bean
    public MyJobOne myJobOne(){
        return new MyJobOne(); 
    }

    @Bean(name="scheduler")
    @Scope(value="prototype")
    public SchedulerFactoryBean schedulerFactoryBean(List<CronTrigger> triggerFactoryBeans) {
        SchedulerFactoryBean scheduler = new SchedulerFactoryBean();
        CronTrigger[] cronTriggers = new CronTrigger[triggerFactoryBeans.size()];
        cronTriggers = triggerFactoryBeans.toArray(cronTriggers);
        scheduler.setTriggers(cronTriggers);
        System.out.println(cronTriggers[0].getCronExpression());
        System.out.println(cronTriggers[0].getCalendarName());
        System.out.println(cronTriggers[0].getTimeZone());
        System.out.println(cronTriggers[0].getEndTime());
        return scheduler;
    }

    @Bean
    public AnotherBean anotherBean(){
        return new AnotherBean();
    }
}  

5) Creating main class to test it

5)创建主类进行测试

package com.example;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

import com.example.config.QuartzConfiguration;
@ComponentScan
@EnableAutoConfiguration
public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(QuartzConfiguration.class);
        context.refresh();
    }
}

回答by Andrew Liu

This is a good example on integrating spring with quartz with spring annotation config (XML-LESS). You can ignore the AutowiringSpringBeanJobFactory and use the standard spring job factory if you don't need inject bean into your job class. Just have a look at this QuartzConfig class.

这是将 spring 与石英与 spring 注释配置 (XML-LESS) 集成的一个很好的例子。如果不需要将 bean 注入作业类,则可以忽略 AutowiringSpringBeanJobFactory 并使用标准的 spring 作业工厂。看看这个 QuartzConfig 类。

https://gist.github.com/jelies/5085593

https://gist.github.com/jelies/5085593