SpringTask介绍与实践

一、三种定时任务的实现方法

  • Java自带的Api java.util.Timer类和java.util.TimerTask类
  • Quartz开源框架,功能强大,使用起来稍显复杂
  • Spring 3.0以后自带了task 调度工具,比Quartz更加的简单方便,除Spring相关的包外不需要额外的包,而且支持注解和配置文件两种形式

二、SpringTask实践

本篇文章不会介绍基于SpringTask的定时任务基本使用,主要会详细介绍动态更改cron表达式的实现方法。因为我在实际开发过程中需要通过平台能够动态修改cron表达式,并且还要满足更新后的cron表达式实时生效,如果按以往的使用方式,将cron表达式定义成一个常量的话,是无法满足当前的功能需求的

2.1 新cron表达式只能在项目启动时进行更新

这种方式其实也是不能满足我们的要求的,但是可以在一定程度上实现cron表达式动态更新生效的目标

package com.test.testmanagement.config;

import com.test.testmanagement.controller.casemanagementcontroller.InterfaceCaseTestSuiteController;
import com.test.testmanagement.model.interfaceBean.InterfaceCaseTestSuite;
import com.test.testmanagement.service.InterfaceCaseTestSuiteService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @description:
 * @author: XXX
 * @time: 2021-02-09 15:42
 */
@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {
    
    

    @Autowired
    private TaskScheduler threadPoolTaskScheduler;

    @Autowired
    private InterfaceCaseTestSuiteService interfaceCaseTestSuiteService;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
    
    
        taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);

        try{
    
    
            //获取所有的设置定时任务的测试集
            List<InterfaceCaseTestSuite> interfaceCaseTestSuiteList = interfaceCaseTestSuiteService.findAllInterfaceCaseTestSuiteWithCrontab();
            System.out.println("需要执行定时任务的测试集个数为:" + interfaceCaseTestSuiteList.size());
            InterfaceCaseTestSuiteController interfaceCaseTestSuiteController = new InterfaceCaseTestSuiteController();
            for(InterfaceCaseTestSuite testSuite : interfaceCaseTestSuiteList){
    
    
                System.out.println(testSuite.getTestSuiteName() + "     tab: " + testSuite.getTestSuiteCrontab());
                //可以实现动态调整定时任务的执行频率
                taskRegistrar.addTriggerTask(
                        // 1、添加任务内容(Runnable)
//                        () -> System.out.println("cccccccccccccccc--->" + Thread.currentThread().getId()),
                        new Runnable() {
    
    
                            @Override
                            public void run() {
    
    
                                try{
    
    
//                                    interfaceCaseTestSuiteController.debugInterfaceCaseTestSuite(testSuite.getId(), testSuite.getTestSuiteName());
                                }catch (Exception e){
    
    
                                    e.printStackTrace();
                                }
                            }
                        },
                        // 2、设置执行周期(Trigger)
                        triggerContext -> {
    
    
                            SimpleDateFormat sdf = new SimpleDateFormat();// 格式化时间
                            sdf.applyPattern("yyyy-MM-dd HH:mm:ss");// a为am/pm的标记
                            Date date = new Date();// 获取当前时间
                            System.out.println("现在时间:" + sdf.format(date)); // 输出已经格式化的现在时间(24小时制)

                            //2.1 从数据库动态获取执行周期
                            String cron = testSuite.getTestSuiteCronExpression();
                            System.out.println("cron表达式的值:" + cron);
                            //2.2 合法性校验.
                            if (StringUtils.isEmpty(cron)) {
    
    
                                // Omitted Code ..
                                System.out.println("计划任务为空");
                            }
                            //2.3 返回执行周期(Date)
                            return new CronTrigger(cron).nextExecutionTime(triggerContext);
                        }
                );
            }
        }catch (Exception e){
    
    
            System.out.println("动态定时任务出现异常!!");
            e.printStackTrace();
        }
    }
}

2.2 新cron表达式实时生效且无需重启工程

下面将要介绍的实现方式,能够保证在不重启工程的情况下实现cron表达式随时更新随时生效

package com.test.testmanagement.controller.casemanagementcontroller;

import com.test.testmanagement.model.interfaceBean.InterfaceCaseTestSuite;
import com.test.testmanagement.service.InterfaceCaseTestSuiteService;
import com.umetrip.qa.model.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

/**
 * @description:
 * @author: XXX
 * @time: 2021-07-27 09:40
 */
@RestController
@RequestMapping(value = "/api/testsuite/schedule")
public class TestSuiteScheduleDynamicTask {
    
    

    @Autowired
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    private Map<Integer, ScheduledFuture<?>> testSuiteMap = new HashMap<>();

    @Autowired
    private InterfaceCaseTestSuiteService interfaceCaseTestSuiteService;

    private InterfaceCaseTestSuiteController interfaceCaseTestSuiteController = new InterfaceCaseTestSuiteController();

    //实例化一个线程池任务调度类,可以使用自定义的ThreadPoolTaskScheduler
    @Bean
    @Qualifier("threadPoolTaskScheduler")
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
    
    
        return new ThreadPoolTaskScheduler();
    }

    @RequestMapping(value = "/startCron", method = RequestMethod.GET)
    public ApiResult startCron(@RequestParam(value = "id") Integer id) {
    
    
        ApiResult apiResult = new ApiResult();
        InterfaceCaseTestSuite testSuite = interfaceCaseTestSuiteService.findByPrimaryKey(id);
        String cron = testSuite.getTestSuiteCronExpression();
        //接受任务的返回结果
        ScheduledFuture future = threadPoolTaskScheduler.schedule(new MyRunnable(testSuite), new CronTrigger(cron));
        System.out.println("future: " + future);
        System.out.println("DynamicTask.startCron()");
        testSuiteMap.put(id, future);
        return apiResult;
    }

    @RequestMapping(value = "/stopCron", method = RequestMethod.GET)
    public ApiResult stopCron(@RequestParam(value = "id") Integer id) {
    
    
        ApiResult apiResult = new ApiResult();
        ScheduledFuture futureTemp = testSuiteMap.get(id);
        if (futureTemp != null) {
    
    
            boolean res = futureTemp.cancel(true);
            if (res){
    
    
                apiResult.setCode(200);
                apiResult.setResult("定时任务停止成功");
            }else {
    
    
                apiResult.setCode(400);
                apiResult.setResult("定时任务停止失败");
            }
        }else {
    
    
            apiResult.setCode(200);
            apiResult.setResult("定时任务已经停止");
        }
        System.out.println("DynamicTask.stopCron()");
        return apiResult;
    }

//    @RequestMapping(value = "/changeCron10", method = RequestMethod.GET)
//    public String startCron10(@RequestParam(value = "id") Integer id) {
    
    
//        stopCron(id);// 先停止,在开启.
//        ScheduledFuture future = threadPoolTaskScheduler.schedule(new MyRunnable(), new CronTrigger("*/10 * * * * *"));
//        System.out.println("DynamicTask.startCron10()");
//        return "changeCron10";
//    }

    @RequestMapping(value = "/changeCron", method = RequestMethod.GET)
    public ApiResult changeCron(@RequestParam(value = "id") Integer id) {
    
    
        ApiResult apiResult = new ApiResult();

        try{
    
    
            InterfaceCaseTestSuite testSuite = interfaceCaseTestSuiteService.findByPrimaryKey(id);
            System.out.println("testSuite name: " + testSuite.getTestSuiteName());
            stopCron(testSuite.getId());// 先停止,在开启.
            String cron = testSuite.getTestSuiteCronExpression();
            ScheduledFuture future = threadPoolTaskScheduler.schedule(new MyRunnable(testSuite), new CronTrigger(cron));
            //更新或新增数据到map中
            testSuiteMap.put(testSuite.getId(), future);
            apiResult.setCode(200);
            apiResult.setResult("定时任务表达式更新成功并执行");
            System.out.println("DynamicTask.changeCron()");
        }catch (Exception e){
    
    
            apiResult.setCode(400);
            apiResult.setResult("定时任务表达式更新失败");
        }
        return apiResult;
    }

    @RequestMapping(value = "/initTestSuiteScheduledTasks", method = RequestMethod.GET)
    public void initTestSuiteScheduledTasks(){
    
    
        ApiResult apiResult = new ApiResult();
        //获取所有的设置定时任务的测试集
        List<InterfaceCaseTestSuite> interfaceCaseTestSuiteList = interfaceCaseTestSuiteService.findAllInterfaceCaseTestSuiteWithCrontab();
        System.out.println("需要执行定时任务的测试集个数为:" + interfaceCaseTestSuiteList.size());
        for(InterfaceCaseTestSuite testSuite : interfaceCaseTestSuiteList) {
    
    
            System.out.println(testSuite.getTestSuiteName() + "     tab: " + testSuite.getTestSuiteCrontab());
            changeCron(testSuite.getId());
        }
        return;
    }


    private class MyRunnable implements Runnable {
    
    
        private InterfaceCaseTestSuite testSuite;

        public MyRunnable(InterfaceCaseTestSuite testSuite){
    
    
            this.testSuite = testSuite;
        }

        @Override
        public void run() {
    
    
            System.out.println("DynamicTask.MyRunnable.run()," + new Date());
            try{
    
    
                interfaceCaseTestSuiteController.debugInterfaceCaseTestSuite(testSuite.getId(), testSuite.getTestSuiteName());
            }catch (Exception e){
    
    
                e.printStackTrace();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/sinat_34241861/article/details/119250605