• springboot使用quartz解决调用不到spring注入service的问题


    @

    前言

    在很多刚使用quartz的小伙伴的体验中,如果说没有碰到这个问题的话,那可能就是还没有往深入的走,也或许有其他的解决方案。

    然后wangwang我呢,也找了很久的资料才找到的。然后跟自己的项目需求相结合就成了这个亚子。

    后面会放参考博客内容的:(本次为简单参考为主,不做过多讲解)
    在这里插入图片描述


    一、先图解一下本次文件内容

    在这里插入图片描述


    二、放代码....

    MyJobFactory.java

    package com.bj.quartz.config;
    
    import groovy.util.logging.Slf4j;
    import org.quartz.spi.TriggerFiredBundle;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.scheduling.quartz.SpringBeanJobFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    @Slf4j
    public class MyJobFactory extends SpringBeanJobFactory
            implements ApplicationContextAware {
    
        @Autowired
        private transient AutowireCapableBeanFactory beanFactory;
    
        @Override
        public void setApplicationContext(final ApplicationContext context) {
            beanFactory = context.getAutowireCapableBeanFactory();
        }
    
        @Override
        protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
            final Object job = super.createJobInstance(bundle);
            beanFactory.autowireBean(job);
            return job;
        }
    
    }
    
    

    QuartzConfiguration.java

    package com.bj.quartz.config;
    
    import org.quartz.Scheduler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.PropertiesFactoryBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    
    import java.io.IOException;
    import java.util.Properties;
    
    @Configuration
    public class QuartzConfiguration {
    
        @Autowired
        private MyJobFactory myJobFactory;
    
        //创建调度器工厂
        @Bean(name = "SchedulerFactory")
        public SchedulerFactoryBean schedulerFactoryBean(){
            SchedulerFactoryBean factoryBean=new SchedulerFactoryBean();
            factoryBean.setJobFactory(myJobFactory);
            return factoryBean;
        }
    
    
        @Bean(name="scheduler")
        public Scheduler scheduler(){
            return schedulerFactoryBean().getScheduler();
        }
    }
    
    

    配置完这些之后,其实就可以了,你就可以通过控制scheduler去生成jobDetail,trigger之类的。并且不用担心spring管理的容器无法注入进来的问题

    可能有些人说,这么就这么一点点呢,当然咯quartz的内容往往不止这一些,还有一些持久化的策略之类的,甚至可以提供搭建一个定时任务的控制平台。只不过暂时我这个就只有这些,能开机就使用的定时任务。

    接下来的就是我本次需求的两个重点测试:1、定时任务自动停止,2、定时任务中参数改变策略

    不需要的小伙伴也可以不看。。。。


    三、测试代码

    0、创建定时任务

    initQuartz.java

    这个是写的一个自启动的时候就编译一个定时任务规则的类

    package com.bj.quartz.init;
    
    import com.bj.quartz.service.TScheduleTriggerParamService;
    import org.quartz.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.ApplicationArguments;
    import org.springframework.boot.ApplicationRunner;
    import org.springframework.stereotype.Component;
    
    
    @Component
    public class initQuartz implements ApplicationRunner {
        //job1的定时任务
        @Value("${jobName1}")
        private String jobName;
        @Value("${groupName1}")
        private String groupName;
        @Value("${cron1}")
        private String cron;
    
        //job2的定时任务
        @Value("${jobName2}")
        private String jobName2;
        @Value("${groupName2}")
        private String groupName2;
        @Value("${cron2}")
        private String cron2;
    
        @Autowired
        private Scheduler scheduler;
    
        private static final Logger logger = LoggerFactory.getLogger(initQuartz.class);
    
    
        @Override
        public void run(ApplicationArguments applicationArguments) throws Exception {
            logger.info("================quartz启动成功==============");
            //创建job1
            addQuartz(jobName,groupName,cron);
            //创建job2
            addQuartz(jobName2,groupName2,cron2);
    
        }
    
        public void addQuartz(String jobName, String jobGroup, String cron){
            try {
            //JobName+JobGroup=Primary Key
            //根据jobName和jobGroup生成TriggerKey
            TriggerKey triggerKey =
                    TriggerKey.triggerKey(jobName, jobGroup);
            //根据TriggerKey到Scheduler调度器中获取触发器
            CronTrigger cronTrigger = (CronTrigger)
                    scheduler.getTrigger(triggerKey);
    
            System.out.println("创建调度器");
            //创建任务详情
            JobDetail jobDetail=
                    JobBuilder.newJob((Class<? extends Job>) Class.forName(jobName))
                            .withIdentity(jobName,jobGroup)
                            .build();
    
            //往Job任务中传递参数
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
    
            //创建表达式调度器
            CronScheduleBuilder cronSchedule =
                    CronScheduleBuilder.cronSchedule(cron);
    
            //创建Trigger
            cronTrigger= TriggerBuilder.newTrigger()
                    .withIdentity(jobName, jobGroup)
                    .withSchedule(cronSchedule)
                    .build();
    
            //将jobDetail和Trigger注入到scheduler调度器中
            scheduler.scheduleJob(jobDetail,cronTrigger);
        }catch (Exception e){
            e.printStackTrace();
        }
        }
    
    
    
    }
    
    

    1、定时任务自动停止

    任务类
    Myjob1.java

    package com.bj.quartz.job;
    
    import com.bj.util.ControllerUtil;
    import org.quartz.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @Component
    public class Myjob1 implements Job {
    
        @Value("${jobName1}")
        private String jobName;
        @Value("${groupName1}")
        private String groupName;
        @Value("${cron1}")
        private String cron;
    
    
        @Autowired
        private Scheduler scheduler;
    
        @Override
        public void execute(JobExecutionContext jobExecutionContext) {
            //任务主体
            taskBody(jobExecutionContext);
        }
    
        /**
         * 任务主体
         */
        private void taskBody(JobExecutionContext jobExecutionContext){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //获取任务详情中的dataMap集合
            JobDetail jobDetail = jobExecutionContext.getJobDetail();
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
            System.out.println("这是我的myjob1111111定时任务"+sdf.format(new Date()));
            System.out.println("本方法的一个参数有:"+jobDataMap.size());
            System.out.println("job:"+jobDataMap.get("job")+"level"+jobDataMap.get("level"));
            System.out.println("-------------------------------");
    
            String BockStartTime = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
            long timeSize=0;
            try {
                /*
                * 拿当前时间和规定时间相比较
                * */
                timeSize = this.compareTime2(BockStartTime, "20200402172430");
            } catch (ParseException e) {
                e.printStackTrace();
            }
    
            /*
            * 如果大于0则代表任务该停下来
            * */
            if(timeSize>0){
                System.err.println("stop job 任务!!!");
                //调用停止定时任务的方法
                this.stopQuary(jobName,groupName);
            }
        }
    
        /**
         * 关闭quary定时任务
         */
        private void stopQuary(String jobName, String groupName){
            TriggerKey triggerKey = TriggerKey.triggerKey(jobName, groupName);
            try {
                /*
                *停止触发器
                * */
                scheduler.pauseTrigger(triggerKey);
                /*
                 *移除触发器
                 * */
                scheduler.unscheduleJob(triggerKey);
                scheduler.deleteJob(JobKey.jobKey(jobName, groupName));
            } catch (SchedulerException e) {
                e.printStackTrace();
            }
        }
    	/**
    	 * TODO 取两个时间的差
    	 * @param day1
    	 * @param day2
    	 * @return 秒
    	 * @throws ParseException
    	 */
    	public  long compareTime2(String day1, String day2)
    			throws ParseException {
    		SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
    		Date rjsj = df.parse(day1);
    		Date dksj = df.parse(day2);
    		long stateTimeLong = rjsj.getTime();
    		long endTimeLong = dksj.getTime();
    		long day = (stateTimeLong - endTimeLong) / 1000L;
    		return day;
    	}
    
    
    }
    
    

    2、定时任务中参数改变策略

    Myjob2.java

    package com.bj.quartz.job;
    
    import com.bj.entity.TScheduleTriggerParam;
    import com.bj.quartz.service.TScheduleTriggerParamService;
    import com.bj.quartz.util.paramMap;
    import groovy.util.logging.Slf4j;
    import org.quartz.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    
    
    @Component
    @Slf4j
    public class Myjob2 implements Job {
    
        @Autowired
        private  TScheduleTriggerParamService tScheduleTriggerParamService;
    
        @Override
        public void execute(JobExecutionContext jobExecutionContext) {
            //任务主体
            taskBody(jobExecutionContext);
        }
        private void taskBody(JobExecutionContext jobExecutionContext){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            //获取任务详情中的dataMap集合
            JobDetail jobDetail = jobExecutionContext.getJobDetail();
            JobDataMap jobDataMap = jobDetail.getJobDataMap();
            //更新params里面的值
            List<TScheduleTriggerParam> params =
                    tScheduleTriggerParamService.queryScheduleParamLst(1);
            for (TScheduleTriggerParam param : params) {
                jobDataMap.put(param.getName(),param.getValue());
            }
            System.err.println("这是我的myjob定时任务"+sdf.format(new Date()));
            System.err.println("本方法的一个参数有:"+jobDataMap.size());
            System.err.println("name:"+jobDataMap.get("name")+"score"+jobDataMap.get("score"));
            System.out.println("-------------------------------");
            //我自己提供的一个Map值
            HashMap jobMap1 = paramMap.getJobMap1();
            System.out.println("自己建的map:"+jobMap1.get("hh"));
        }
    }
    
    

    这个我就得唠唠嗑了,参数的设置可能有三种方式:
    1、使用一个静态常量的map类,然后每次调用修改参数的service的时候同时把map类中的数据重新替换掉,
    2、使用redis进行存储,如果是多集群的话,
    3、每次使用job任务的时候都到数据库去查询一下参数并且更替掉。

    根据自身情况来吧。。


    后言

    不过说实话,如果是需要深入了解的还是得看看官方文档之类的。
    像w3c中的quartz。

    还有我看到的比较详细的:触发器介绍
    本次参考后解决问题的博客:Springboot整合quartz框架(附代码)

    我是wangwang,感谢能看到这里。
    在这里插入图片描述

    欢迎在评论区进行评论。

  • 相关阅读:
    PHP-FPM 不完全指南
    【权限设计】如何以“权限”为单位的进行权限设计(二)
    【权限设计】如何以“用户”为单位的进行权限设计(一)
    【权限设计】一个案例,三个角色,简单说下B端产品的权限设计
    gdb调试报错:Missing separate debuginfos, use: debuginfo-install glibc-XXX
    java之 ------ 文件拷贝
    高速排序C++实现
    error: internal error: unable to execute QEMU command &#39;migrate&#39;: this feature or command is not cur
    MySQL查询报错 ERROR: No query specified
    广告倒计时欢迎界面的实现
  • 原文地址:https://www.cnblogs.com/liwangwang/p/12627433.html
Copyright © 2020-2023  润新知