The use of Quartz (to solve the problem that the job of quartz cannot be injected into the spring object)

1. Description:

Versions below spring3.1 must use quartz1.x series, and versions above 3.1 support quartz 2.x, otherwise an error will occur. As for the reason, spring's support for quartz implements org.springframework.scheduling.quartz.CronTriggerBean, which inherits org.quartz.CronTrigger. In the quartz1.x series, org.quartz.CronTrigger is a class, and in the quartz2.x series org .quartz.CronTrigger has become an interface, which makes it impossible to configure quartz triggers in spring.

The quartz version I am using is 2.2.1.

Problem:
The original job was automatically scanned by Spring, and the properties could be injected automatically. Now, instead of using a separate Quartz, the properties cannot be injected.

2. Customize a class:

Under normal circumstances, the object injected by the autowired annotation in the quartz job is empty. At this time, we need to use the AdaptableJobFactory class provided by spring-quartz.

package com.yj.quartzjob;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.scheduling.quartz.AdaptableJobFactory;

public class JobFactory extends AdaptableJobFactory {
    @Autowired 
    private AutowireCapableBeanFactory capableBeanFactory;  

    @Override 
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {  
        //调用父类的方法  
        Object jobInstance = super.createJobInstance(bundle);  
        //进行注入  
        capableBeanFactory.autowireBean(jobInstance);  
        return jobInstance;  
    }
}

3. Configuration of Spring.XML:

 <!-- quartz的定时任务的factorybean,配置其他config -->   
    <bean id="jobFactory" class="com.yj.quartzjob.JobFactory"></bean>  
    <bean id="schedulerFactoryBean" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
        <property name="jobFactory" ref="jobFactory"></property>  
    </bean>  

4. Simple task management class:

package com.yj.until;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.DateBuilder;
import org.quartz.DateBuilder.IntervalUnit;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class QuartzManager {

    @Autowired
    private Scheduler sched;

    /**
     * 增加一个job
     * @param jobClass 任务实现类
     * @param jobName 任务名称
     *  @param jobGroupName 任务组名
     * @param jobTime 时间表达式 (如:0/5 * * * * ? )
     */
    public  void addJob(Class<? extends Job> jobClass, String jobName,String jobGroupName,String jobTime) {
        try {
            //创建jobDetail实例,绑定Job实现类  
            //指明job的名称,所在组的名称,以及绑定job类
            JobDetail jobDetail = JobBuilder.newJob(jobClass)
                            .withIdentity(jobName, jobGroupName)//任务名称和组构成任务key
                            .build();
            //定义调度触发规则  
            //使用cornTrigger规则 
            Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(jobName, jobGroupName)//触发器key
                        .startAt(DateBuilder.futureDate(1, IntervalUnit.SECOND))
                        .withSchedule(CronScheduleBuilder.cronSchedule(jobTime))
                        .startNow().build();
            //把作业和触发器注册到任务调度中
            sched.scheduleJob(jobDetail, trigger);
            // 启动
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 增加一个job
     * @param jobClass  任务实现类
     * @param jobName  任务名称
     * @param jobGroupName 任务组名
     * @param jobTime  时间表达式 (这是每隔多少秒为一次任务)
     */
    public void addJob(Class<? extends Job> jobClass, String jobName,String jobGroupName,int jobTime){
        addJob(jobClass,jobName,jobGroupName,jobTime,-1);
    }

    /**
     * 增加一个job
     * @param jobClass 任务实现类
     * @param jobName  任务名称
     * @param jobGroupName 任务组名
     * @param jobTime  时间表达式 (这是每隔多少秒为一次任务)
     * @param jobTimes  运行的次数 (<0:表示不限次数)
     */
    public void addJob(Class<? extends Job> jobClass, String jobName,String jobGroupName,int jobTime,int jobTimes){
         try {
             JobDetail jobDetail = JobBuilder.newJob(jobClass)
                             .withIdentity(jobName, jobGroupName)//任务名称和组构成任务key
                             .build();
           //使用simpleTrigger规则
             Trigger trigger=null;
             if(jobTimes<0){
                 trigger=TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)  
                        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime))  
                        .startNow().build();
             }else{
                 trigger=TriggerBuilder.newTrigger().withIdentity(jobName, jobGroupName)  
                        .withSchedule(SimpleScheduleBuilder.repeatSecondlyForever(1).withIntervalInSeconds(jobTime).withRepeatCount(jobTimes))  
                        .startNow().build();
             }
            sched.scheduleJob(jobDetail, trigger);
            if (!sched.isShutdown()) {
                sched.start();
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 修改 一个job的 时间表达式
     * @param jobName
     * @param jobGroupName
     * @param jobTime
     */
    public void updateJob(String jobName,String jobGroupName,String jobTime){
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroupName);  
            CronTrigger trigger = (CronTrigger) sched.getTrigger(triggerKey);  
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
                    .withSchedule(CronScheduleBuilder.cronSchedule(jobTime))
                    .build();
            //重启触发器
            sched.rescheduleJob(triggerKey, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }  
    }

    /**
     * 删除任务一个job
     * @param jobName 任务名称
     * @param jobGroupName 任务组名
     */
    public  void deleteJob(String jobName,String jobGroupName) {
        try {
            sched.deleteJob(new JobKey(jobName, jobGroupName));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 暂停一个job
     * @param jobName
     * @param jobGroupName
     */
    public void pauseJob(String jobName,String jobGroupName){
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);  
            sched.pauseJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        } 
    }

    /**
     * 恢复一个job
     * @param jobName
     * @param jobGroupName
     */
    public void resumeJob(String jobName,String jobGroupName){
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.resumeJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 立即执行一个job
     * @param jobName
     * @param jobGroupName
     */
    public void runAJobNow(String jobName,String jobGroupName){
        try {
            JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
            sched.triggerJob(jobKey);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有计划中的任务列表
     * @return
     */
    public List<Map<String,Object>> queryAllJob(){
        List<Map<String,Object>> jobList=null;
        try {
             GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();  
             Set<JobKey> jobKeys = sched.getJobKeys(matcher);
             jobList = new ArrayList<Map<String,Object>>();  
             for (JobKey jobKey : jobKeys) {  
                  List<? extends Trigger> triggers = sched.getTriggersOfJob(jobKey);  
                  for (Trigger trigger : triggers) {  
                      Map<String,Object> map=new HashMap<>();
                      map.put("jobName",jobKey.getName());
                      map.put("jobGroupName",jobKey.getGroup());
                      map.put("description","触发器:" + trigger.getKey());
                      Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());  
                      map.put("jobStatus",triggerState.name());
                      if (trigger instanceof CronTrigger) {  
                          CronTrigger cronTrigger = (CronTrigger) trigger;  
                          String cronExpression = cronTrigger.getCronExpression();  
                          map.put("jobTime",cronExpression);
                      }  
                      jobList.add(map);  
                  }  
              }  
        } catch (SchedulerException e) {
            e.printStackTrace();
        }  
        return jobList;  
    }

    /**
     * 获取所有正在运行的job
     * @return
     */
    public List<Map<String,Object>> queryRunJon(){
        List<Map<String,Object>> jobList=null;
        try {
            List<JobExecutionContext> executingJobs = sched.getCurrentlyExecutingJobs();
            jobList = new ArrayList<Map<String,Object>>(executingJobs.size());  
            for (JobExecutionContext executingJob : executingJobs) {  
                Map<String,Object> map=new HashMap<String, Object>();  
                JobDetail jobDetail = executingJob.getJobDetail();  
                JobKey jobKey = jobDetail.getKey();  
                Trigger trigger = executingJob.getTrigger(); 
                map.put("jobName",jobKey.getName());
                map.put("jobGroupName",jobKey.getGroup());
                map.put("description","触发器:" + trigger.getKey());
                Trigger.TriggerState triggerState = sched.getTriggerState(trigger.getKey());  
                map.put("jobStatus",triggerState.name());
                if (trigger instanceof CronTrigger) {  
                    CronTrigger cronTrigger = (CronTrigger) trigger;  
                    String cronExpression = cronTrigger.getCronExpression();  
                    map.put("jobTime",cronExpression);
                }  
                jobList.add(map);  
            }  
        } catch (SchedulerException e) {
            e.printStackTrace();
        }  
        return jobList;  
    }
}

5. Job class:

package com.yj.quartzjob;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.yj.service.WeiXinService;
/**
 * quart test
 * @author jing
 *
 */
@Component
public class QuartzJob implements Job{
    @Autowired
    public WeiXinService service;

    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
        System.out.println("TestQuartJob 的运行 :"+dateFormat.format(new Date()));
        service.getAccessToken();
    }

}

6. Test class:

@RequestMapping("add")
    public void text(){

        try {
            String jobName="job1";
            String jobGroupName="job1";
            String jobTime="0/5 * * * * ? ";
            SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
            System.out.println("TestQuartJob 开始启动:"+dateFormat.format(new Date()));
            quartzManager.addJob(QuartzJob.class,jobName,jobGroupName,jobTime);
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

7. maven introduces:

            <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.1</version>
            </dependency>

8. Listener:

Customize a listener class:

It seems that Quartz's job fails when the project is restarted. I store the job every time it starts in the database, and then when the project starts, the listener reads the job in the database, and then adds the job.

package com.yj.quartzjob;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.quartz.Job;
import org.springframework.web.context.support.WebApplicationContextUtils;
import com.yj.until.QuartzManager;

/**
 * 容器监听器
 * @author jing
 */
public class QuartzJobListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent arg0) {
        /***处理获取数据库的job表,然后遍历循环每个加到job中 ***/
        QuartzManager quartzManager = WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext()).getBean(QuartzManager.class);

        //此处就不写获取数据库了,模拟一个集合遍历的数据  
        List<Map<String,Object>> listMap=new ArrayList<>();
        Map<String, Object> map1=new HashMap<String, Object>();
        map1.put("jobClass","com.yj.quartzjob.QuartzJob");
        map1.put("jobName","job1");
        map1.put("jobGroupName","job1");
        map1.put("jobTime","0/5 * * * * ? ");
        listMap.add(map1);

        for (Map<String, Object> map : listMap) {
            try {
                quartzManager.addJob((Class<? extends Job>)(Class.forName((String)map1.get("jobClass")).newInstance().getClass()),(String)map.get("jobName"), (String)map.get("jobGroupName"),(String)map.get("jobTime"));
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
        System.out.println("QuartzJobListener 启动了");
    }
    public void contextDestroyed(ServletContextEvent arg0) {
    }

}

Configuration of web.xml:

ps: The custom listener class should be after the listener of the SpringMVC framework.

<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
 <listener>
   <listener-class>com.yj.quartzjob.QuartzJobListener</listener-class>
</listener>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325835802&siteId=291194637