Quartz的使用(解决quartz的job无法注入spring对象)

1、说明:

spring3.1以下的版本必须使用quartz1.x系列,3.1以上的版本才支持quartz 2.x,不然会出错。至于原因,则是spring对于quartz的支持实现org.springframework.scheduling.quartz.CronTriggerBean继承了org.quartz.CronTrigger,在quartz1.x系列中org.quartz.CronTrigger是个类,而在quartz2.x系列中org.quartz.CronTrigger变成了接口,从而造成无法用spring的方式配置quartz的触发器(trigger)。

我使用的quartz版本是2.2.1 。

问题:
原来的Job是Spring自动扫描的,属性可以自动注入,现在换成使用单独的Quartz,属性不能注入了。

2、自定义一个类:

一般情况下,quartz的job中使用autowired注解注入的对象为空,这时候我们就要使用spring-quartz提供的AdaptableJobFactory类。

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、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、简单的任务管理类:

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类:

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、测试类:

@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引入:

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

8、监听器:

自定义一个监听类:

貌似Quartz的job在项目重启时,job都失效了,我是把每次启动的job都存放在数据库,然后项目启动时监听器读取数据库的job,然后添加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) {
    }

}

web.xml的配置:

ps:自定义的监听类要在SpringMVC框架的监听器之后。

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

猜你喜欢

转载自blog.csdn.net/jingyang07/article/details/74983099