任务调度系统

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/g893465244/article/details/79065766


有时,我们需要程序进行不同的调度进行执行,比如每天早晨10点执行、每隔10分钟执行一次、今晚20:00执行等。

所以,此处通过开源的作业调度框架Quart快速完成任务调度的工作.

基本原理:
   1、创建调度工厂();    //工厂模式
   2、根据工厂取得调度器实例();  //工厂模式
   3、Builder模式构建子组件<Job,Trigger>  // builder模式, 如JobBuilder、TriggerBuilder、DateBuilder
   4、通过调度器组装子组件   调度器.组装<子组件1,子组件2...>  //工厂模式

   5、调度器.start(); //工厂模式

核心算法:

QuartzJobBean.java

public class QuartzJobBean implements StatefulJob {
    
    private Log log = LogFactory.getLog(QuartzJobBean.class);
    
    public static final String TARGET_CLASS = "class";
    public static final String TARGET_METHOD = "method";
    public static final String TARGET_ARGUMENTS = "arguments";
    
    private static ApplicationContext ac;

    public static void setAc(ApplicationContext ac) {
        QuartzJobBean.ac = ac;
    }

    public static ApplicationContext getApplicationContext() {
    	return ac;
    }
    
    /**
     * 通过类名和方法名去获取目标对象,再通过反射执行
     * 类名和方法名保存在jobDetail中
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        String targetClass = (String) context.getMergedJobDataMap().get(TARGET_CLASS);
        String targetMethod = (String) context.getMergedJobDataMap().get(TARGET_METHOD);
        String methodArgs = (String) context.getMergedJobDataMap().get(TARGET_ARGUMENTS);

        if (StringUtils.isEmpty(targetClass) || StringUtils.isEmpty(targetMethod))
            return;

        Object[] args = null;
        if (!StringUtils.isEmpty(methodArgs)) {
            methodArgs = methodArgs + " ";
            String[] argString = methodArgs.split("#&");
            args = new Object[argString.length];
            for (int i = 0; i < argString.length; i++) {
                args[i] = argString[i].trim();
            }
        }

        JobContext.className.set(targetClass);
        JobContext.methodName.set(targetMethod);
        JobContext.argStr.set(methodArgs);
        
        CacheContext.method.set(targetClass + "_" + targetMethod);

        long startTime = System.currentTimeMillis();
        
        try {
            Object target = ac.getBean(targetClass);
            if (null != target) {
                Class tc = target.getClass();
                Class[] parameterType = null;
                if (args != null) {
                    parameterType = new Class[args.length];
                    for (int i = 0; i < args.length; i++) {
                        parameterType[i] = String.class;
                    }
                }
                Method method = tc.getDeclaredMethod(targetMethod, parameterType);
                if (null != method) {

                    method.invoke(target, args);

                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new JobExecutionException(e);
        }

        log.error("[QuartzJobBean]" + targetClass + ", " + targetMethod + ", " + methodArgs
                + ", used time " + (System.currentTimeMillis() - startTime));
    }

}
BasicScheduler.java

public class BasicScheduler extends ApplicationObjectSupport implements
        ApplicationListener<ApplicationEvent> {

    private final static Log log = LogFactory.getLog(BasicScheduler.class);

    static SchedulerFactory sf = new StdSchedulerFactory();

    private static Scheduler scheduler;
    {
        try {
            scheduler = sf.getScheduler();
        } catch (SchedulerException e) {
        }
    }

    @Resource
    private BasicJobConfig basicJobConfig;
    
    @Resource
    private BasicQuartzJobDAO basicQuartzJobDAO;
    
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        if (event instanceof ContextRefreshedEvent) {
            ContextRefreshedEvent cre = (ContextRefreshedEvent) event;
            log.error("BasicScheduler Start. " + cre.getApplicationContext().getDisplayName());
            if (cre.getApplicationContext().getParent() == null
                    && cre.getApplicationContext().getDisplayName()
                            .equalsIgnoreCase("Root WebApplicationContext")) {
                ApplicationContext ac = getApplicationContext();
                QuartzJobBean.setAc(ac);
            }
        }
    }
    

    /**
     * Quartz启动任务
     * @param basicQuartzJob
     * @throws Exception
     */
    private void enable(BasicQuartzJob basicQuartzJob) throws Exception {
        CronTrigger trigger =
                (CronTrigger) scheduler.getTrigger(basicQuartzJob.getTriggerName(),
                        basicQuartzJob.getJobGroup());
        if (null == trigger) {
            JobDetail jobDetail =
                    new JobDetail(basicQuartzJob.getJobName(), basicQuartzJob.getJobGroup(),
                            QuartzJobBean.class);
            jobDetail.getJobDataMap().put(QuartzJobBean.TARGET_CLASS, basicQuartzJob.getJobClass());
            jobDetail.getJobDataMap().put(QuartzJobBean.TARGET_METHOD,
                    basicQuartzJob.getJobMethod());
            jobDetail.getJobDataMap().put(QuartzJobBean.TARGET_ARGUMENTS,
                    basicQuartzJob.getJobArguments());
            trigger =
                    new CronTrigger(basicQuartzJob.getTriggerName(), basicQuartzJob.getJobGroup(),
                            basicQuartzJob.getCronExpression());
            scheduler.scheduleJob(jobDetail, trigger);
            /**
             * trigger 有name jobName group jobGroup 如果没有设置jobName,则在调度时会用jobDetail的name和group赋值
             * trigger的jobName和jobGroup,必须和jobDetail的保持一致
             */
            if (log.isInfoEnabled()) {
                log.info(basicQuartzJob.toString() + ", add new.");
            }
        } else {
            trigger.setCronExpression(basicQuartzJob.getCronExpression());
            scheduler.rescheduleJob(trigger.getName(), trigger.getGroup(), trigger);
            if (log.isInfoEnabled()) {
                log.info(basicQuartzJob.toString() + ", modify exist.");
            }
        }
    }
    
    
}

job_class为任务类在spring中的bean对象名称
job_method为任务方法的名称
job_name为任务的名称
job_group对于同一个名称的任务在一个任务组中只能有一个任务实例,因此如果实现同一个任务,依据参数不同执行多个任务实例,请设置为不同的任务组

需要修改的一般仅限于job_argumentscron_expression

job_arguments代表的是任务的参数,如果有多个参数请用#&分开

cron_expression是用来指定何时执行任务。 
一个cron表达式有至少6个(也可能是7个)由空格分隔的时间元素。从左至右,这些元素的定义如下: 
1.秒(0–59) 
2.分钟(0–59) 
3.小时(0–23) 
4.月份中的日期(1–31) 
5.月份(1–12或JAN–DEC) 
6.星期中的日期(1–7或SUN–SAT) 
7.年份(1970–2099)

表 达 式 意 义
0 0/10 * * * ? 每隔10分钟一次
0 0 10,14,16 * * ? 每天上午10点,下午2点和下午4点
0 0,15,30,45 * 1-10 * ? 每月前10天每隔15分钟
30 0 0 1 1 ? 2012 在2012年1月1日午夜过30秒时
0 0 8-5 ? * MON-FRI 每个工作日的工作时间


























展开阅读全文

没有更多推荐了,返回首页