FrameTimerUtil.java 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. package cn.hmsoft.frame.timer;
  2. import java.time.LocalDateTime;
  3. import java.util.LinkedHashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.Properties;
  7. import org.quartz.CronExpression;
  8. import org.quartz.CronScheduleBuilder;
  9. import org.quartz.CronTrigger;
  10. import org.quartz.Job;
  11. import org.quartz.JobBuilder;
  12. import org.quartz.JobDetail;
  13. import org.quartz.JobKey;
  14. import org.quartz.SchedulerFactory;
  15. import org.quartz.TriggerBuilder;
  16. import org.quartz.impl.StdSchedulerFactory;
  17. import cn.hmsoft.frame.constants.FrameParamConstants;
  18. import cn.hmsoft.frame.constants.FrameStatus;
  19. import cn.hmsoft.frame.data.dao.FrameTimerDao;
  20. import cn.hmsoft.frame.data.model.FrameTimer;
  21. import cn.hmsoft.helper.DateHelper;
  22. import cn.hmsoft.helper.LogHelper;
  23. import cn.hmsoft.helper.StringHelper;
  24. import cn.hmsoft.web.config.SpringConfig;
  25. /*************************
  26. * 系统定时器辅助类
  27. *
  28. * @author zxq
  29. * @create 2018-05-10 15:31:38
  30. * @version 5.0.0
  31. * @email: revisit@126.com
  32. * @Company: www.hmsoft.cn
  33. */
  34. public final class FrameTimerUtil {
  35. private final static String JobGroupName = "HmSoftJobGroup";
  36. private final static String JobNameStartWith = "HmSoftJobName";
  37. public final static String TimerJobParamName = "TimerJobParamName";
  38. private static SchedulerFactory JobSchedulerFactory = null;
  39. private static Map<Integer, FrameTimer> TimerMap = null;
  40. /*********************
  41. * 系统定时器模块是否正常启用
  42. */
  43. private static boolean FrameTimerStatus = false;
  44. /***************************
  45. * 数据库是否可用
  46. */
  47. private static boolean TimerDatabaseFlag = false;
  48. /*************************************************
  49. * 设置基本参数
  50. */
  51. static {
  52. synchronized (FrameTimerUtil.class) {
  53. if (JobSchedulerFactory == null) {
  54. Properties p = new Properties();
  55. // 表明scheduler的主线程是否为守护线程
  56. p.setProperty("org.quartz.scheduler.makeSchedulerThreadDaemon",
  57. TimerModuleConfig.FrameTimerThreadDaemon);
  58. // 使用ThreadPool的实现的名字。Quartz自带的线程池是“org.quartz.simpl.SimpleThreadPool”,几乎满足所有用户的需求。它的行为很简单,测试的也很好。它提供了固定大小的线程池,生命周期与Scheduler相同。
  59. p.setProperty("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
  60. // 可以是任意的正整数。实际上只有1到100会用到。这是并行执行job可用的线程数。如果只有几个job,一天也只有几次触发,那么一个线程就足够了!如果有成百上千的job,且每一个每一分钟都会触发。那么可能想要让线程的数量达到50或者100了。
  61. p.setProperty("org.quartz.threadPool.threadCount", "" + TimerModuleConfig.FrameTimerThreadCount);
  62. // 可以设为true,那么线程池中创建的线程都是守护线程。默认为false
  63. p.setProperty("org.quartz.threadPool.makeThreadsDaemons", TimerModuleConfig.FrameTimerThreadDaemon);
  64. TimerMap = new LinkedHashMap<Integer, FrameTimer>();
  65. try {
  66. // 启动任务池
  67. JobSchedulerFactory = new StdSchedulerFactory(p);
  68. JobSchedulerFactory.getScheduler().start();
  69. FrameTimerStatus = true;
  70. } catch (Exception e) {
  71. LogHelper.error("frame timer module load error , please check quartz's file");
  72. }
  73. }
  74. }
  75. }
  76. private static FrameTimerUtil util = null;
  77. private FrameTimerUtil() {
  78. TimerMap = new LinkedHashMap<Integer, FrameTimer>();
  79. }
  80. public static FrameTimerUtil getInstance() {
  81. if (util == null) {
  82. synchronized (FrameTimerUtil.class) {
  83. if (util == null)
  84. util = new FrameTimerUtil();
  85. // 只有正常初始quartz之后,以下操作才有意义
  86. if (FrameTimerStatus == true) {
  87. List<FrameTimer> timerArray = SpringConfig.getBean(FrameTimerDao.class)
  88. .listTimer(FrameParamConstants.AppName);
  89. for (FrameTimer timer : timerArray) {
  90. util.initTimer(timer);
  91. }
  92. }
  93. }
  94. }
  95. return util;
  96. }
  97. /************************
  98. * 启动一个定时器
  99. */
  100. public boolean initTimer(FrameTimer timer) {
  101. if (!timer.getTimer_status().equals(FrameStatus.Active.toString())
  102. || (timer.getTimer_end_time() != null && timer.getTimer_end_time().isBefore(LocalDateTime.now())))
  103. return false;
  104. String timer_cron = timer.getTimer_cron();
  105. if (StringHelper.isEmpty(timer_cron)) {
  106. // 一次性任务,直接运行
  107. FrameTimerConfig config = null;
  108. try {
  109. config = (FrameTimerConfig) Class.forName(timer.getTimer_class()).newInstance();
  110. } catch (Exception e) {
  111. // 不是FrameTimerConfig子类,无法正常初始化
  112. LogHelper.error(
  113. "frame timer [" + timer.getTimer_name() + "] timer_class instanct fail,please check code !");
  114. return false;
  115. }
  116. timer.prepareParamMap();
  117. // 直接执行..
  118. try {
  119. config.execute(timer);
  120. return true;
  121. } catch (Exception e) {
  122. LogHelper.log(e);
  123. return false;
  124. }
  125. } else {
  126. // 定时任务
  127. // 判断表达式是否正确
  128. if (!CronExpression.isValidExpression(timer_cron)) {
  129. LogHelper.error("frame timer [" + timer.getTimer_name() + "],cron expression [" + timer.getTimer_cron()
  130. + "] is error !");
  131. return false;
  132. }
  133. // 初始化JOB
  134. try {
  135. JobKey key = new JobKey(JobNameStartWith + timer.getTimer_id(), JobGroupName);
  136. @SuppressWarnings("unchecked")
  137. JobDetail jobDetail = JobBuilder.newJob((Class<Job>) Class.forName(timer.getTimer_class()))
  138. .withIdentity(key).build();
  139. jobDetail.getJobDataMap().put(TimerJobParamName, timer);
  140. LocalDateTime start_time = timer.getTimer_start_time(), end_time = timer.getTimer_end_time();
  141. // 没有配置结束时间,加30年
  142. if (end_time == null)
  143. end_time = LocalDateTime.now().plusYears(30);
  144. // 如果没有开始时间,10秒后开始
  145. if (start_time == null)
  146. start_time = LocalDateTime.now().plusSeconds(10);
  147. CronTrigger trigger = TriggerBuilder.newTrigger()
  148. .withIdentity(JobNameStartWith + timer.getTimer_id(), JobGroupName)
  149. .withSchedule(CronScheduleBuilder.cronSchedule(timer_cron))
  150. .startAt(DateHelper.toDate(start_time)).endAt(DateHelper.toDate(end_time)).build();
  151. JobSchedulerFactory.getScheduler().scheduleJob(jobDetail, trigger);
  152. if (trigger.getNextFireTime() != null)
  153. timer.setTimer_next_time(DateHelper.toLocalDateTime(trigger.getNextFireTime()));
  154. // 如果数据库可用,更新数据库
  155. if (TimerDatabaseFlag)
  156. SpringConfig.GobalDao.update(timer);
  157. LogHelper.info("frame timer [" + timer.getTimer_name() + "] init:" + timer.getTimer_class());
  158. TimerMap.put(timer.getTimer_id(), timer);
  159. // 如果是自动启动,马上进行调度
  160. if (timer.getAuto_run_flag().equals(FrameStatus.Active.toString()))
  161. JobSchedulerFactory.getScheduler().triggerJob(key);
  162. } catch (Exception e) {
  163. LogHelper.error(e);
  164. return false;
  165. }
  166. }
  167. return true;
  168. }
  169. public boolean shutdown() {
  170. try {
  171. JobSchedulerFactory.getScheduler().shutdown();
  172. return true;
  173. } catch (Exception e) {
  174. LogHelper.error(e);
  175. return false;
  176. }
  177. }
  178. }