| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.inspectiontask.service.impl; |
| | | |
| | | import com.ruoyi.inspectiontask.pojo.TimingTask; |
| | | import org.quartz.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.time.LocalTime; |
| | | import java.time.ZoneId; |
| | | import java.time.format.DateTimeParseException; |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @Service |
| | | public class TimingTaskScheduler { |
| | | |
| | | @Autowired |
| | | private Scheduler scheduler; |
| | | |
| | | /** |
| | | * æ·»å æ°ä»»å¡å°è°åº¦å¨ |
| | | */ |
| | | public void scheduleTimingTask(TimingTask task) throws SchedulerException { |
| | | JobDetail jobDetail = buildJobDetail(task); |
| | | Trigger trigger = buildJobTrigger(task, jobDetail); |
| | | scheduler.scheduleJob(jobDetail, trigger); |
| | | } |
| | | |
| | | /** |
| | | * æ´æ°å·²æä»»å¡ |
| | | */ |
| | | public void rescheduleTimingTask(TimingTask task) throws SchedulerException { |
| | | TriggerKey triggerKey = new TriggerKey("trigger_" + task.getId()); |
| | | |
| | | // è·åç°æè§¦åå¨å¹¶è½¬æ¢ä¸º CronTrigger |
| | | Trigger oldTrigger = scheduler.getTrigger(triggerKey); |
| | | if (!(oldTrigger instanceof CronTrigger)) { |
| | | throw new SchedulerException("Existing trigger is not a CronTrigger"); |
| | | } |
| | | |
| | | // æå»ºæ°è§¦åå¨ |
| | | Trigger newTrigger = TriggerBuilder.newTrigger() |
| | | .withIdentity(triggerKey) |
| | | .withDescription(task.getTaskName()) |
| | | .withSchedule(CronScheduleBuilder.cronSchedule(convertToCronExpression(task))) |
| | | .startAt(Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())) |
| | | .forJob(oldTrigger.getJobKey()) |
| | | .build(); |
| | | |
| | | scheduler.rescheduleJob(triggerKey, newTrigger); |
| | | } |
| | | |
| | | /** |
| | | * æåä»»å¡ |
| | | */ |
| | | public void pauseTimingTask(Long taskId) throws SchedulerException { |
| | | JobKey jobKey = new JobKey("timingTask_" + taskId); |
| | | scheduler.pauseJob(jobKey); |
| | | } |
| | | |
| | | /** |
| | | * æ¢å¤ä»»å¡ |
| | | */ |
| | | public void resumeTimingTask(Long taskId) throws SchedulerException { |
| | | JobKey jobKey = new JobKey("timingTask_" + taskId); |
| | | scheduler.resumeJob(jobKey); |
| | | } |
| | | |
| | | /** |
| | | * å é¤ä»»å¡ |
| | | */ |
| | | public void unscheduleTimingTask(Long taskId) throws SchedulerException { |
| | | JobKey jobKey = new JobKey("timingTask_" + taskId); |
| | | scheduler.deleteJob(jobKey); |
| | | } |
| | | |
| | | private JobDetail buildJobDetail(TimingTask task) { |
| | | JobDataMap jobDataMap = new JobDataMap(); |
| | | jobDataMap.put("taskId", task.getId()); |
| | | |
| | | return JobBuilder.newJob(TimingTaskJob.class) |
| | | .withIdentity("timingTask_" + task.getId()) |
| | | .withDescription(task.getTaskName()) |
| | | .usingJobData(jobDataMap) |
| | | .storeDurably() |
| | | .build(); |
| | | } |
| | | |
| | | private Trigger buildJobTrigger(TimingTask task, JobDetail jobDetail) { |
| | | String cronExpression = convertToCronExpression(task); |
| | | |
| | | TriggerBuilder<CronTrigger> triggerBuilder = TriggerBuilder.newTrigger() |
| | | .withIdentity("trigger_" + task.getId()) |
| | | .withDescription(task.getTaskName()) |
| | | .withSchedule(CronScheduleBuilder.cronSchedule(cronExpression)); |
| | | |
| | | if (jobDetail != null) { |
| | | triggerBuilder.forJob(jobDetail); |
| | | } |
| | | |
| | | if (task.getNextExecutionTime() != null) { |
| | | triggerBuilder.startAt(Date.from(task.getNextExecutionTime().atZone(ZoneId.systemDefault()).toInstant())); |
| | | } |
| | | |
| | | return triggerBuilder.build(); |
| | | } |
| | | private String convertToCronExpression(TimingTask task) { |
| | | // åæ°æ ¡éª |
| | | if (task == null || task.getFrequencyType() == null || task.getFrequencyDetail() == null) { |
| | | throw new IllegalArgumentException("ä»»å¡åæ°ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // 使ç¨switchç¡®ä¿æ¡ä»¶äºæ¥ |
| | | String frequencyType = task.getFrequencyType().toUpperCase(); // ç»ä¸è½¬ä¸ºå¤§åæ¯è¾ |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | return convertDailyToCron(task.getFrequencyDetail()); |
| | | case "WEEKLY": |
| | | return convertWeeklyToCron(task.getFrequencyDetail()); |
| | | case "MONTHLY": |
| | | return convertMonthlyToCron(task.getFrequencyDetail()); |
| | | case "QUARTERLY": |
| | | return convertQuarterlyToCron(task.getFrequencyDetail()); |
| | | default: |
| | | throw new IllegalArgumentException("䏿¯æçé¢çç±»å: " + task.getFrequencyType()); |
| | | } |
| | | } |
| | | |
| | | // æ¯æ¥ä»»å¡è½¬æ¢ |
| | | private String convertDailyToCron(String frequencyDetail) { |
| | | LocalTime time = parseTime(frequencyDetail); |
| | | return String.format("0 %d %d * * ?", time.getMinute(), time.getHour()); |
| | | } |
| | | |
| | | // æ¯å¨ä»»å¡è½¬æ¢ |
| | | private String convertWeeklyToCron(String frequencyDetail) { |
| | | String[] parts = validateAndSplit(frequencyDetail, ",", 2); |
| | | String daysOfWeek = convertDayNamesToCron(parts[0]); |
| | | LocalTime time = parseTime(parts[1]); |
| | | return String.format("0 %d %d ? * %s", time.getMinute(), time.getHour(), daysOfWeek); |
| | | } |
| | | |
| | | // æ¯æä»»å¡è½¬æ¢ |
| | | private String convertMonthlyToCron(String frequencyDetail) { |
| | | String[] parts = validateAndSplit(frequencyDetail, ",", 2); |
| | | int day = validateDayOfMonth(parts[0]); |
| | | LocalTime time = parseTime(parts[1]); |
| | | return String.format("0 %d %d %d * ?", time.getMinute(), time.getHour(), day); |
| | | } |
| | | |
| | | // æ¯å£åº¦ä»»å¡è½¬æ¢ |
| | | private String convertQuarterlyToCron(String frequencyDetail) { |
| | | String[] parts = validateAndSplit(frequencyDetail, ",", 3); |
| | | int month = validateMonth(parts[0]); // éªè¯æä»½(1-12) |
| | | int day = validateDayOfMonth(parts[1]); // éªè¯æ¥æ |
| | | LocalTime time = parseTime(parts[2]); // è§£ææ¶é´ |
| | | |
| | | // 计ç®å£åº¦èµ·å§æä»½(1æ=1, 4æ=4, 7æ=7, 10æ=10) |
| | | int quarterStartMonth = ((month - 1) / 3) * 3 + 1; |
| | | |
| | | return String.format("0 %d %d %d %d/3 ?", |
| | | time.getMinute(), |
| | | time.getHour(), |
| | | day, |
| | | quarterStartMonth); |
| | | } |
| | | |
| | | // æ°å¢éªè¯æä»½çæ¹æ³(1-12) |
| | | private int validateMonth(String monthStr) { |
| | | try { |
| | | int month = Integer.parseInt(monthStr); |
| | | if (month < 1 || month > 12) { |
| | | throw new IllegalArgumentException("æä»½å¿
é¡»å¨1-12ä¹é´"); |
| | | } |
| | | return month; |
| | | } catch (NumberFormatException e) { |
| | | throw new IllegalArgumentException("æ æçæä»½æ ¼å¼"); |
| | | } |
| | | } |
| | | |
| | | // è¾
婿¹æ³ï¼è§£ææ¶é´ |
| | | private LocalTime parseTime(String timeStr) { |
| | | try { |
| | | return LocalTime.parse(timeStr); |
| | | } catch (DateTimeParseException e) { |
| | | throw new IllegalArgumentException("æ¶é´æ ¼å¼å¿
须为HH:mm", e); |
| | | } |
| | | } |
| | | |
| | | // è¾
婿¹æ³ï¼éªè¯å¹¶åå²å符串 |
| | | private String[] validateAndSplit(String input, String delimiter, int expectedParts) { |
| | | String[] parts = input.split(delimiter); |
| | | if (parts.length != expectedParts) { |
| | | throw new IllegalArgumentException( |
| | | String.format("æ ¼å¼é误ï¼åºä¸º%dé¨åç¨'%s'åé", expectedParts, delimiter)); |
| | | } |
| | | return parts; |
| | | } |
| | | |
| | | // è¾
婿¹æ³ï¼éªè¯æä»½ä¸çæ¥ |
| | | private int validateDayOfMonth(String dayStr) { |
| | | int day = Integer.parseInt(dayStr); |
| | | if (day < 1 || day > 31) { |
| | | throw new IllegalArgumentException("æ¥æå¿
é¡»å¨1-31ä¹é´"); |
| | | } |
| | | return day; |
| | | } |
| | | |
| | | // è¾
婿¹æ³ï¼éªè¯å£åº¦ä¸çæ |
| | | private int validateMonthInQuarter(String monthStr) { |
| | | int month = Integer.parseInt(monthStr); |
| | | if (month < 1 || month > 3) { |
| | | throw new IllegalArgumentException("å£åº¦æä»½å¿
é¡»æ¯1ã2æ3"); |
| | | } |
| | | return month; |
| | | } |
| | | |
| | | // è½¬æ¢ææå åç§° |
| | | private String convertDayNamesToCron(String dayNames) { |
| | | return Arrays.stream(dayNames.split("\\|")) |
| | | .map(this::convertSingleDayName) |
| | | .collect(Collectors.joining(",")); |
| | | } |
| | | |
| | | // 转æ¢å个ææå åç§° |
| | | private String convertSingleDayName(String dayName) { |
| | | switch (dayName.toUpperCase()) { |
| | | case "MON": return "MON"; |
| | | case "TUE": return "TUE"; |
| | | case "WED": return "WED"; |
| | | case "THU": return "THU"; |
| | | case "FRI": return "FRI"; |
| | | case "SAT": return "SAT"; |
| | | case "SUN": return "SUN"; |
| | | default: throw new IllegalArgumentException("æ æçææå : " + dayName); |
| | | } |
| | | } |
| | | } |