Spring Quartz 任務靜態配置和動態添加

Quartz任務能夠靜態配置到配置文件中,也能夠動態添加.java

1.Quartz任務 靜態配置

其中 <property name="concurrent" value="false"/>,是設置job不能併發執行。spring

<!-- 刪除舊數據定時任務 -->
    <!-- 刪除新聞數據job -->
    <bean id="delOldNewsJobDetail"
          class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="deleteOldNewsJob"/>
        <property name="targetMethod" value="doJob"/>
        <property name="concurrent" value="false"/>   <!--防止job併發執行-->
    </bean> 
    <!-- tigger -->
    <bean id="deleteOldNewsJobTrigger"
          class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<!-- org.springframework.scheduling.quartz.CronTriggerBean -->
        <property name="jobDetail">
            <ref bean="delOldNewsJobDetail"/>
        </property>
        <property name="cronExpression">
            <!-- cron表達式  -->
            <value>${delete.old.news.cron}</value> 
        </property>
    </bean>

 

定時任務執行類併發

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


@Component
public class DeleteOldNewsJob {
  
  private Logger logger = LoggerFactory.getLogger(DeleteOldNewsJob.class);
  
  @Value("${delete.old.news.job.enable}")
  private boolean enabled;
  
  @Autowired
  private NewsFeedMapper newsFeedMapper;

  public void doJob() {
    if (!enabled) {
      logger.info("delete old news job enabled = false");
      return;
    }
    logger.info("----------------delete old news begins------------------");
    newsFeedMapper.deleteOldNews();
    logger.info("----------------delete old news end---------------------");
  }
}

 

2.Quartz任務 動態添加

 定時器動態添加任務類app

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.stereotype.Service;

/**
 * Quartz定時任務調度器管理類
 *
 */
@Component
public class QuartzManager{
  /**
   * 任務組名
   */
  private static final String JOB_GROUP_NAME = "PUSH_MESSAGE_JOB_GROUP";
  /**
   * 觸發器組名
   */
  private static final String TRIGGER_GROUP_NAME = "PUSH_MESSAGE_TRIGGER_GROUP";
  /**
   * Quartz調度器
   */
  private Scheduler scheduler;

  /**
   * 初始化調度器
   *
   * @throws SchedulerException
   */
  @PostConstruct
  public void init() throws SchedulerException {
    SchedulerFactory schedulerFactory = new StdSchedulerFactory();
    scheduler = schedulerFactory.getScheduler();
  }

  /**
   * 添加一個定時任務,使用默認的任務組名、觸發器組名,觸發器的名稱跟任務的同樣
   *
   * @param jobName 任務名稱
   * @param cls 任務
   * @param time 任務執行的時間,Cron表達式
   */
  @SuppressWarnings("rawtypes")
  @Override
  public void addJob(String jobName, Class cls, String time) {
    try {
      JobDetail jobDetail = new JobDetail(jobName, JOB_GROUP_NAME, cls);
      CronTrigger trigger = new CronTrigger(jobName, TRIGGER_GROUP_NAME);
      trigger.setCronExpression(time);
      scheduler.scheduleJob(jobDetail, trigger);
      if (!scheduler.isShutdown()) {
        scheduler.start();
      }
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 移除一個定時任務 使用默認的任務組名、觸發器組名,觸發器名跟任務名一致
   *
   * @param jobName 任務名稱
   */
  @Override
  public void removeJob(String jobName) {
    try {
      scheduler.pauseTrigger(jobName, TRIGGER_GROUP_NAME);// 暫停觸發器
      scheduler.unscheduleJob(jobName, TRIGGER_GROUP_NAME);// 移除觸發器
      scheduler.deleteJob(jobName, JOB_GROUP_NAME);// 刪除任務
    } catch (SchedulerException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 啓動全部定時任務
   */
  @Override
  public void startJobs() {
    try {
      scheduler.start();
    } catch (SchedulerException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 關閉全部定時任務
   */
  @Override
  public void shutdownJobs() {
    try {
      if (!scheduler.isShutdown()) {
        scheduler.shutdown();
      }
    } catch (SchedulerException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * 當關閉應用時,中止全部調度任務,並關掉調度器
   */
  @PreDestroy
  public void stopQuartz() {
    try {
      if (!scheduler.isShutdown()) {
        scheduler.shutdown();
      }
    } catch (SchedulerException e) {
      throw new RuntimeException(e);
    }
  }
}

 

測試動態定時任務添加框架

任務類less

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TestJob implements Job {
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        System.out.println("time out!!!");
    }
}

 

測試類,須要使用ide

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class QuartzTest {
    @Resource
    private QuartzManager manager;
    @Test
    public void test(){
        manager.startJobs();
        manager.addJob("test", TestJob.class,"*/5 * * * * ?");
        while (true);
    }
}

 

Quartz防止job併發執行測試

Quartz框架中防止任務並行能夠有兩種方案:spa

一、若是是經過MethodInvokingJobDetailFactoryBean在運行中動態生成的Job,配置的xml文件有個concurrent屬性,這個屬性的功能是配置此job是否能夠並行運行,若是爲false則表示不能夠並行運行,不然能夠並行。若是一個job的業務處理髮費的時間超過了job的啓動的間隔時間(repeatInterval),這個屬性很是有用。若是爲false,那麼,在這種狀況下,當前job還在運行,那麼下一個job只能延時運行。若是爲true,那麼job就會並行運行。code

二、若是是經過自定義要執行的任務的類的名稱實現job的話,則有另外一種方式:

默認的任務的類實現org.quartz.Job接口,此時任務是stateless(無狀態的),即會出現並行的狀況,那麼如何避免這種狀況發生呢?

解決方案:使QuartzJobBean類實現org.quartz.StatefulJob接口便可(StatefulJob接口僅僅是擴展了 Job 接口,未加入新的方法,能夠不需實現Job接口了),那麼此時任務就會變成stateful(有狀態的),此時的任務也就會串行執行了。

相關文章
相關標籤/搜索