Spring Boot 2はQuartJobを統合し、タイマーのリアルタイム管理機能を実現します。


一、QuartJob概要
1、一言で表す
QuartzはJavaによって完全に編纂されたオープンソース作業スケジュールの枠組みであり、形式が簡単で、機能が強い。
2、核心API
(1)、Scheduler
Quarzの独立した運転容器を表します。SchdulerはTriggerを特定のJobDetailに結び付けます。これによりTriggerがトリガされると、対応するJobがスケジュールされます。
(2)、トリガー
Jobが実行する時間トリガルールについて説明します。主にSimpleTriggerとCronTriggerの二つのサブクラスがあります。一つのTrigger Keyによって一意に表示されます。
(3)、Job
タスクを定義し、タスクは実行時の行為であると規定しています。JobExecution Contectはスケジューラのコンテキスト情報を提供し、JobのデータはJobDataMapから取得することができる。
(4)、JobDetail
QuartzはJobを実行するたびにJobのインスタンスを再作成するので、Jobのインスタンスを直接的に受け入れず、むしろJob実装クラスを受信する。Jobの実装クラスおよびその他の関連する静的情報、例えばJobの名前、記述などを説明する。
二、Spring Boot 2.0と整合する
1、プロジェクト構造

バージョンの説明
spring-boot:2.1.3.RELEASE
quart-job:2.3.0
2、タイマーの設定

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import javax.sql.DataSource;
import java.util.Properties;
@Configuration
public class ScheduleConfig {
 @Bean
 public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource) {
 // Quartz    
 Properties prop = new Properties();
 // Schedule        
 prop.put("org.quartz.scheduler.instanceName", "HuskyScheduler");
 //    AUTO   ,     org.quartz.scheduler.SimpleInstanceGenerator             。
 prop.put("org.quartz.scheduler.instanceId", "AUTO");
 //      
 prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
 prop.put("org.quartz.threadPool.threadCount", "20");
 prop.put("org.quartz.threadPool.threadPriority", "5");
 // JobStore  :Scheduler             
 // JDBCJobStore JobStoreTX           Schedule     。
 // JobStoreTX           commit  rollback     。
 prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
 //     :                  true
 prop.put("org.quartz.jobStore.isClustered", "true");
 //     :                  
 prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
 //       (  ),               
 prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
 //                  
 prop.put("org.quartz.jobStore.misfireThreshold", "12000");
 //       
 prop.put("org.quartz.jobStore.tablePrefix", "qrtz_");
 //   LOCKS                SQL   
 prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");

 //        
 SchedulerFactoryBean factory = new SchedulerFactoryBean();
 factory.setDataSource(dataSource);
 factory.setQuartzProperties(prop);
 factory.setSchedulerName("HuskyScheduler");
 factory.setStartupDelay(30);
 factory.setApplicationContextSchedulerContextKey("applicationContextKey");
 //   ,QuartzScheduler          Job
 factory.setOverwriteExistingJobs(true);
 //       ,   true
 factory.setAutoStartup(true);
 return factory;
 }
}
3、タイマー管理ツール

import com.quart.job.entity.ScheduleJobBean;
import org.quartz.*;
/**
 *       
 */
public class ScheduleUtil {
 private ScheduleUtil (){}
 private static final String SCHEDULE_NAME = "HUSKY_" ;
 /**
 *     KEY
 */
 public static TriggerKey getTriggerKey(Long jobId){
 return TriggerKey.triggerKey(SCHEDULE_NAME+jobId) ;
 }
 /**
 *     Key
 */
 public static JobKey getJobKey (Long jobId){
 return JobKey.jobKey(SCHEDULE_NAME+jobId) ;
 }
 /**
 *       
 */
 public static CronTrigger getCronTrigger (Scheduler scheduler,Long jobId){
 try {
  return (CronTrigger)scheduler.getTrigger(getTriggerKey(jobId)) ;
 } catch (SchedulerException e){
  throw new RuntimeException("getCronTrigger Fail",e) ;
 }
 }
 /**
 *      
 */
 public static void createJob (Scheduler scheduler, ScheduleJobBean scheduleJob){
 try {
  //      
  JobDetail jobDetail = JobBuilder.newJob(TaskJobLog.class).withIdentity(getJobKey(scheduleJob.getJobId())).build() ;
  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder
   .cronSchedule(scheduleJob.getCronExpression())
   .withMisfireHandlingInstructionDoNothing() ;
  CronTrigger trigger = TriggerBuilder.newTrigger()
   .withIdentity(getTriggerKey(scheduleJob.getJobId()))
   .withSchedule(scheduleBuilder).build() ;
  jobDetail.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob);
  scheduler.scheduleJob(jobDetail,trigger) ;
  //             
  if (scheduleJob.getStatus() == 1){
  pauseJob(scheduler,scheduleJob.getJobId()) ;
  }
 } catch (SchedulerException e){
  throw new RuntimeException("createJob Fail",e) ;
 }
 }
 /**
 *       
 */
 public static void updateJob(Scheduler scheduler, ScheduleJobBean scheduleJob) {
 try {
  //      
  TriggerKey triggerKey = getTriggerKey(scheduleJob.getJobId());
  CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression())
   .withMisfireHandlingInstructionDoNothing();
  CronTrigger trigger = getCronTrigger(scheduler, scheduleJob.getJobId());
  trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
  trigger.getJobDataMap().put(ScheduleJobBean.JOB_PARAM_KEY, scheduleJob);
  scheduler.rescheduleJob(triggerKey, trigger);
  //             
  if(scheduleJob.getStatus() == 1){
  pauseJob(scheduler, scheduleJob.getJobId());
  }
 } catch (SchedulerException e) {
  throw new RuntimeException("updateJob Fail",e) ;
 }
 }
 /**
 *      
 */
 public static void pauseJob (Scheduler scheduler,Long jobId){
 try {
  scheduler.pauseJob(getJobKey(jobId));
 } catch (SchedulerException e){
  throw new RuntimeException("pauseJob Fail",e) ;
 }
 }
 /**
 *      
 */
 public static void resumeJob (Scheduler scheduler,Long jobId){
 try {
  scheduler.resumeJob(getJobKey(jobId));
 } catch (SchedulerException e){
  throw new RuntimeException("resumeJob Fail",e) ;
 }
 }
 /**
 *      
 */
 public static void deleteJob (Scheduler scheduler,Long jobId){
 try {
  scheduler.deleteJob(getJobKey(jobId));
 } catch (SchedulerException e){
  throw new RuntimeException("deleteJob Fail",e) ;
 }
 }
 /**
 *      
 */
 public static void run (Scheduler scheduler, ScheduleJobBean scheduleJob){
 try {
  JobDataMap dataMap = new JobDataMap() ;
  dataMap.put(ScheduleJobBean.JOB_PARAM_KEY,scheduleJob);
  scheduler.triggerJob(getJobKey(scheduleJob.getJobId()),dataMap);
 } catch (SchedulerException e){
  throw new RuntimeException("run Fail",e) ;
 }
 }
}
4、タイマーの実行とログ

import com.quart.job.entity.ScheduleJobBean;
import com.quart.job.entity.ScheduleJobLogBean;
import com.quart.job.service.ScheduleJobLogService;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.quartz.QuartzJobBean;
import java.lang.reflect.Method;
import java.util.Date;
/**
 *          
 */
public class TaskJobLog extends QuartzJobBean {
 private static final Logger LOG = LoggerFactory.getLogger(TaskJobLog.class) ;
 @Override
 protected void executeInternal(JobExecutionContext context) {
 ScheduleJobBean jobBean = (ScheduleJobBean)context.getMergedJobDataMap().get(ScheduleJobBean.JOB_PARAM_KEY) ;
 ScheduleJobLogService scheduleJobLogService = (ScheduleJobLogService)SpringContextUtil.getBean("scheduleJobLogService") ;
 //        
 ScheduleJobLogBean logBean = new ScheduleJobLogBean () ;
 logBean.setJobId(jobBean.getJobId());
 logBean.setBeanName(jobBean.getBeanName());
 logBean.setParams(jobBean.getParams());
 logBean.setCreateTime(new Date());
 long beginTime = System.currentTimeMillis() ;
 try {
  //           run   
  Object target = SpringContextUtil.getBean(jobBean.getBeanName());
  Method method = target.getClass().getDeclaredMethod("run", String.class);
  method.invoke(target, jobBean.getParams());
  long executeTime = System.currentTimeMillis() - beginTime;
  logBean.setTimes((int)executeTime);
  logBean.setStatus(0);
  LOG.info("    === >> "+jobBean.getJobId()+"    ,   === >> " + executeTime);
 } catch (Exception e){
  //     
  long executeTime = System.currentTimeMillis() - beginTime;
  logBean.setTimes((int)executeTime);
  logBean.setStatus(1);
  logBean.setError(e.getMessage());
 } finally {
  scheduleJobLogService.insert(logBean) ;
 }
 }
}
三、タイマーサービスパッケージ
1、タイマー初期化

@Service
public class ScheduleJobServiceImpl implements ScheduleJobService {

 @Resource
 private Scheduler scheduler ;
 @Resource
 private ScheduleJobMapper scheduleJobMapper ;

 /**
 *       
 */
 @PostConstruct
 public void init (){
 ScheduleJobExample example = new ScheduleJobExample() ;
 List<ScheduleJobBean> scheduleJobBeanList = scheduleJobMapper.selectByExample(example) ;
 for (ScheduleJobBean scheduleJobBean : scheduleJobBeanList) {
  CronTrigger cronTrigger = ScheduleUtil.getCronTrigger(scheduler,scheduleJobBean.getJobId()) ;
  if (cronTrigger == null){
  ScheduleUtil.createJob(scheduler,scheduleJobBean);
  } else {
  ScheduleUtil.updateJob(scheduler,scheduleJobBean);
  }
 }
 }
}

2、タイマーを追加する

@Override
@Transactional(rollbackFor = Exception.class)
public int insert(ScheduleJobBean record) {
 ScheduleUtil.createJob(scheduler,record);
 return scheduleJobMapper.insert(record);
}

3、直ちに一回のタイマーを実行します。

@Override
@Transactional(rollbackFor = Exception.class)
public void run(Long jobId) {
 ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;
 ScheduleUtil.run(scheduler,scheduleJobBean);
}

4、タイマーを更新する

@Override
@Transactional(rollbackFor = Exception.class)
public int updateByPrimaryKeySelective(ScheduleJobBean record) {
 ScheduleUtil.updateJob(scheduler,record);
 return scheduleJobMapper.updateByPrimaryKeySelective(record);
}

5、停止タイマー

@Override
@Transactional(rollbackFor = Exception.class)
public void pauseJob(Long jobId) {
 ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;
 ScheduleUtil.pauseJob(scheduler,jobId);
 scheduleJobBean.setStatus(1);
 scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean) ;
}

6、回復タイマ

@Override
@Transactional(rollbackFor = Exception.class)
public void resumeJob(Long jobId) {
 ScheduleJobBean scheduleJobBean = scheduleJobMapper.selectByPrimaryKey(jobId) ;
 ScheduleUtil.resumeJob(scheduler,jobId);
 scheduleJobBean.setStatus(0);
 scheduleJobMapper.updateByPrimaryKeySelective(scheduleJobBean) ;
}
7、タイマーを削除する

@Override
@Transactional(rollbackFor = Exception.class)
public void delete(Long jobId) {
 ScheduleUtil.deleteJob(scheduler, jobId);
 scheduleJobMapper.deleteByPrimaryKey(jobId) ;
}

四、テストのタイマーを配置する
1、タイミングインターフェースパッケージ

public interface TaskService {
 void run(String params);
}
2、テストタイマ

@Component("getTimeTask")
public class GetTimeTask implements TaskService {
 private static final Logger LOG = LoggerFactory.getLogger(GetTimeTask.class.getName()) ;
 private static final SimpleDateFormat format =
  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
 @Override
 public void run(String params) {
 LOG.info("Params === >> " + params);
 LOG.info("    ::::"+format.format(new Date()));
 }
}

五、ソースコード
GitHub:セミが笑う
https://github.com/cicadasmile/middle-ware-parent

締め括りをつける
以上は小编でご绍介したSpring Boot 2整合QuartJobでタイマーのリアルタイム管理机能を実现しました。皆様のご协力をお愿いします。ここでも私たちのサイトを応援してくれてありがとうございます。
本文があなたのためになると思ったら、転載を歓迎します。出所を明記してください。ありがとうございます。