Spring-Task定時任務, (springboot項目, 動態設置時間) -- Demo


SpringBoot + SpringTask + SpringDataJPA

業務:

用戶選擇 自動關閉 后, 可以選擇一個時間(格式為yyyy-MM-dd hh:mm),時間到后觸發定時任務,關閉或開啟系統(修改狀態)
精確到秒倒計時會出錯(未知), 所以就規定用戶不能選秒, 業務邏輯也是可以的(不太好).

核心代碼:


DynamicTaskController :


/**
 * 定時任務接口
 *
 * @author wqkeep
 * @date 2020/6/10 14:51
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/XXXXXX/task")
public class DynamicTaskController extends BaseController {

      //BaseController 主要用於調用JSONResponse ,給JSONResponse 中的參數賦值,this.success(Object data)就是這樣
      //JSONResponse 封裝好的返回結果,有 是否成功success,數據data,消息提示msg,狀態碼status

    private final TaskServiceImpl taskServiceImpl;

    /**
     * 開啟報名通道定時任務
     *
     * @param id 系統id
     * @param sysStatus 系統狀態
     * @param countDownTime 倒計時時間
     * @return JSONResponse 封裝好的返回結果,有 是否成功success,數據data,消息提示msg,狀態碼status
     * @throws OperationException 封裝好的自定義異常信息
     */
    @PostMapping("/XXXXXX/startCron")
    public JSONResponse startCron(Long id, Integer sysStatus, @RequestParam("date") String countDownTime) throws OperationException {
        taskServiceImpl.startCron(id, sysStatus,countDownTime);
        return this.success(SysConst.SUCCESS);
    }

    /**
     * 關閉當前線程定時任務
     *
     * @return JSONResponse
     */
    @PostMapping("/XXXXXX/stopCron")
    public JSONResponse stopCron() {
        taskServiceImpl.stopCron();
        return this.success(SysConst.SUCCESS);
    }

    /**
     * TODO 定時任務存在問題
     *
     * 目前可以實現倒計時的功能, 但系統如果要集群就會存在問題(關閉不了當前線程, 用戶可能會修改多個不同線程的定時任務).
     *
     */

}

TaskServiceImpl:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;

/**
 * 定時任務
 *
 * @author wqkeep
 * @date 2020/6/10 17:31
 */
@Slf4j
@Service
@Transactional(rollbackOn = RuntimeException.class)
public class TaskServiceImpl implements TaskService {

    @Autowired
    private TaskRepository taskRepository; //(PO)實體類Task 對應的Repository

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    private ScheduledFuture<?> future;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        return new ThreadPoolTaskScheduler();
    }

    /**
     * 開啟報名通道定時任務
     *
     * @param id 系統id
     * @param sysStatus 系統狀態
     * @param countDownTime 倒計時時間
     * @throws OperationException 自定義異常信息
     */
    public void startCron(Long id, Integer sysStatus, String countDownTime) throws OperationException {
        String currentThread = Thread.currentThread().getName();
        log.info("DynamicTask 報名通道定時任務開啟: 當前線程 " + currentThread);
        String strDateFormat = "yyyy-MM-dd HH:mm";
        SimpleDateFormat sd = new SimpleDateFormat(strDateFormat);
        Date countDownDate = null;
        try {
            countDownDate = sd.parse(countDownTime);
        } catch (Exception e) {
            throw new OperationException("字符串轉換日期失敗");
        }
        String cron = CronDateUtils.getCron(countDownDate);
      //task為自定義的定時任務實體類 我這里主要存儲cron表達式和定時任務具體時間,需要定時任務的系統名字,只有一個定時任務需求,所以寫死了(不好)
        Task task = new Task();
        task.setId(1L);
        task.setCron(cron);
        task.setName("XXXXX系統");
        task.setRemark("自動開啟關閉");
        task.setCountDownTime(countDownDate);
        //保存 自定義的定時任務實體類task
        taskRepository.save(task);
        if (future != null) {
            future.cancel(true);
        }
        future = threadPoolTaskScheduler.schedule(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                
                //業務代碼, 我這里是修改系統狀態為關閉或開啟

                stopCron();
                log.info("DynamicTask 報名通道定時任務停止: 當前線程 " + currentThread);
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                return new CronTrigger(cron).nextExecutionTime(triggerContext);
            }
        });
    }

    /**
     * 關閉當前線程定時任務
     */
    public void stopCron() {
        if (future != null) {
            future.cancel(true);
        }
    }

}


cron表達式和日期轉換工具類CronDateUtils :

import com.zjxf.config.exception.custom.OperationException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 定時任務cron表達式與Date之間的轉換
 *
 * @author wqkeep
 * @date 2020/6/10 14:51
 */
public class CronDateUtils {

     //自定義cron表達式格式 可以修改
    private static final String CRON_DATE_FORMAT = "0/1 mm HH dd MM ?";
 
    /***
     * Date轉換為cron表達式
     *
     * @param date 時間
     * @return cron類型的日期
     */
    public static String getCron(final Date date){
        SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
        String formatTimeStr = "";
        if (date != null) {
            formatTimeStr = sdf.format(date);
        }
        return formatTimeStr;
    }

    /**
     * cron表達式轉換為Date
     *
     * @param cron Quartz cron的類型的日期
     * @return Date日期
     * @throws OperationException 自定義異常信息
     */
    public static Date getDate(final String cron) throws OperationException {
        if(cron == null) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(CRON_DATE_FORMAT);
        Date date = null;
        try {
            date = sdf.parse(cron);
        } catch (Exception e) {
            throw new OperationException("轉換失敗");
        }
        return date;
    }
}


參考博客:

https://blog.csdn.net/weixin_37591536/article/details/82150933


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM