SpringTask实现定时任务

Spring task的三种典型的应用模式可以集成在传统springMVC项目,也可以在SpringBoot项目中,优点比较轻量,不需要添加过多依赖,缺点分布式支持不友好

不累赘叙述task的引用了,常用模式有:

1. 静态定时

直接使用@Scheduled注释,缺点cron表达的信息固定不可变

2. 修改定时器

import java.util.Date;

import org.apache.log4j.Logger;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
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 org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@EnableScheduling
@RequestMapping("/task")
public class TaskController implements SchedulingConfigurer {

    private Logger logger = Logger.getLogger(TaskController.class);

    /**
     * 定时任务的定时器表达式: 秒 分 时 日期 月 星期
     * 注意:有的地方说定时正则表达式可以有year,即7个元素,但是,在spring-boot里面,只能是6个元素,没有年。
     */
    private String cronExpression = "1/5 * * * * *";

    /**
     * 通过REST API请求对参数进行修改,定时规则进行调整
     * @param exp
     * @return
     */
    @RequestMapping("/change")
    public String change(@RequestParam("exp") String exp) {
        cronExpression = exp;
        logger.info("new cron expression: " + exp);
        return cronExpression;
    }

    /**
     * 定时任务要执行的方法
     * @return
     */
    private Runnable getTask() {
        Runnable task = new Runnable() {
            @Override
            public void run() {
            	logger.info("==定时任务==开始: " + new Date());
            	
            	//业务处理,忽视所有异常
                try {
                	//do something
                	
				} catch (Exception e) {
					e.printStackTrace();
				}
                
                logger.info("==定时任务==结束: " + new Date());
            }
        };
        return task;
    }

    /**
     * 调度实现的时间控制
     * @param scheduledTaskRegistrar
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        Trigger trigger=new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                CronTrigger cronTrigger=new CronTrigger(cronExpression);
                return cronTrigger.nextExecutionTime(triggerContext);
            }
        };
        scheduledTaskRegistrar.addTriggerTask(getTask(), trigger);
    }
}

缺点:控制不强,没有持久化,不随时启动停止

3. 动态启动和停止以及修改定时规则

/**
 * 定时任务核心类
 * @ClassName: TimmerComponent
 */
@Component
public class TimmerComponent {

    // 保存任务
    private Map<String, ScheduledFuture<?>> futuresMap = new ConcurrentHashMap<String, ScheduledFuture<?>>();
    
    private Logger logger = Logger.getLogger(TimmerComponent.class);

	//持久化任务
    //@Autowired
    //private ITaskJobDao taskJobDao;
    
    // 创建ThreadPoolTaskScheduler线程池
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;
    
    @Bean
    public ThreadPoolTaskScheduler getThreadPoolTaskScheduler(){
    	threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    	threadPoolTaskScheduler.setPoolSize(20);
    	threadPoolTaskScheduler.setThreadNamePrefix("task-");
    	threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
    	threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
    	threadPoolTaskScheduler.initialize();
        return threadPoolTaskScheduler;
    }

    // 初始化任务
    @Bean
    public Map<String, ScheduledFuture<?>> initTimmer(){
		//启动时获取持久化任务,可以避免服务重启任务丢失,如不需要可以注释
        // List<WelcomTaskJob> list = welcomTaskJobDao.getList4Enable();
        // for (WelcomTaskJob s : list){
            // ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getRunnable(s), getTrigger(s));
            // futuresMap.put(s.getTaskJobCode(), future);
        // }
        return futuresMap;
    }
    

    /**
     * 添加任务
     * @param s
     */
    public void addTask(WelcomTaskJob s){
    	logger.info("定时任务#====>添加: " + new Date());
        ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getRunnable(s), getTrigger(s));
        futuresMap.put(s.getTaskJobCode(), future);
    }

    /**
     * 暂停任务
     * @param key
     * @return
     */
    public boolean cancelTask(String key) {
    	logger.info("定时任务#====>取消: " + new Date());
        ScheduledFuture<?> toBeRemovedFuture = futuresMap.remove(key);
        if (toBeRemovedFuture != null) {
            toBeRemovedFuture.cancel(true);
            return true;
        } else {
            return false;
        }
    }

    /**
     * 更新任务
     * @param s
     */
    public void updateTask(WelcomTaskJob s) {
    	logger.info("定时任务#====>更新: " + new Date());
        ScheduledFuture<?> toBeRemovedFuture = futuresMap.remove(s.getTaskJobCode());
        if (toBeRemovedFuture != null) {
            toBeRemovedFuture.cancel(true);
        }
        ScheduledFuture<?> future = threadPoolTaskScheduler.schedule(getRunnable(s), getTrigger(s));
        futuresMap.put(s.getTaskJobCode(), future);
    }


    /**
     * 转换首字母小写
     *
     * @param str
     * @return
     */
    public static String lowerFirstCapse(String str) {
        char[] chars = str.toCharArray();
        chars[0] += 32;
        return String.valueOf(chars);
    }

    /**
     * runnable
     * @param taskJob
     * @return
     */
    private Runnable getRunnable(WelcomTaskJob taskJob){
        return new Runnable() {
            @Override
            public void run() {
                Class<?> clazz;
                try {
                	logger.info("定时任务#====>启动: " + new Date());
					//使用反射原理来获取执行操作类及方法,注意可能无法获取登录用户信息,业务操作中请勿绑定
                    clazz = Class.forName(taskJob.getClassName());
                    String className = lowerFirstCapse(clazz.getSimpleName());
                    Object bean = (Object) ApplicationContextHelper.getBean(className);
                    Method method = ReflectionUtils.findMethod(bean.getClass(), taskJob.getMethodName());
                    ReflectionUtils.invokeMethod(method, bean);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        };
    }

    /**
     * Trigger
     * @param taskJob
     * @return
     */
    private Trigger getTrigger(WelcomTaskJob taskJob){
        return new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                CronTrigger trigger = new CronTrigger(taskJob.getCron());
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        };

    }
}
/**
 * 获取bean
 * @ClassName: ApplicationContextHelper
 */
@Component
public class ApplicationContextHelper implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public ApplicationContextHelper() {
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ApplicationContextHelper.applicationContext = applicationContext;
    }

    public static Object getBean(String beanName) {
        return applicationContext != null?applicationContext.getBean(beanName):null;
    }
}

 

 

参考 : https://www.cnblogs.com/shihuc/p/9275780.html

            https://blog.csdn.net/xcc_2269861428/article/details/100023788

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值