分布式调度之Quartz

/**
 * @Author: rhb
 * @Date: 2020/9/29 19:22
 * @Description: quartz核心配置类
 */
@Configuration
public class QuartzConfig {

    @Value("${quartz.driverClassName}")
    private String driverClassName;
    @Value("${quartz.url}")
    private String url;
    @Value("${quartz.username}")
    private String username;
    @Value("${quartz.password}")
    private String password;
    @Value("${quartz.maxConnections}")
    private String maxConnections;
    @Value("${quartz.publickey}")
    private String publicKey;

    @Bean
    public Properties quartzProperties() throws Exception {
        password = ConfigTools.decrypt(publicKey, password);

        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        Properties prop = new Properties();

        // scheduler配置
        prop.put("org.quartz.scheduler.instanceName", "DouYinQuartzScheduler");         // 调度器的实例名
        prop.put("org.quartz.scheduler.instanceId", "AUTO");                            // 自动生成id
        prop.put("org.quartz.scheduler.skipUpdateCheck", "true");                       // 跳过更新

        // JobStore配置
        prop.put("org.quartz.jobStore.isClustered", "true");                                                 //启用集群
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");                                                // 表名前缀
        prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");                                      // 定义datasource名称
        prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");                    // 持久化
        prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate"); // JDBC的驱动程序
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE");
        prop.put("org.quartz.jobStore.txIsolationLevelSerializable","true");                                 // 防止数据库在高负载下锁定超时以及“持久”事务

        // ThreadPool配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");   // 线程池的名字
        prop.put("org.quartz.threadPool.threadCount", "5");                             // 指定线程数量
        prop.put("org.quartz.threadPool.threadPriority", "5");                          // 线程优先级(1-10)默认为5
        prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");

        // mysql数据源配置
        prop.put("org.quartz.dataSource.quartzDataSource.driver", driverClassName);
        prop.put("org.quartz.dataSource.quartzDataSource.URL", url);
        prop.put("org.quartz.dataSource.quartzDataSource.user", username);
        prop.put("org.quartz.dataSource.quartzDataSource.password", password);
        prop.put("org.quartz.dataSource.quartzDataSource.maxConnections", maxConnections);
        prop.put("org.quartz.dataSource.quartzDataSource.provider","hikaricp");
        prop.put("org.quartz.dataSource.quartzDataSource.maximumPoolSize","10");
        prop.put("org.quartz.dataSource.quartzDataSource.connectionTestQuery","SELECT 1");
        prop.put("org.quartz.dataSource.quartzDataSource.validationTimeout","5000");
        prop.put("org.quartz.dataSource.quartzDataSource.idleTimeout","0");

        //在quartz.properties中的属性被读取并注入后再初始化对象
        propertiesFactoryBean.setProperties(prop);
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    @Bean
    public JobFactory jobFactory(ApplicationContext applicationContext){
        AutowiredSpringBeanJobFactory jobFactory = new AutowiredSpringBeanJobFactory();
        jobFactory.setApplicationContext(applicationContext);
        return jobFactory;
    }

    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory){
        SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
        //可选,QuartzScheduler启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录
        schedulerFactoryBean.setOverwriteExistingJobs(true);
        //设置自动启动
        schedulerFactoryBean.setAutoStartup(true);
        schedulerFactoryBean.setJobFactory(jobFactory);
        try {
            schedulerFactoryBean.setQuartzProperties(quartzProperties());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return schedulerFactoryBean;
    }

    /**
     * 初始注入scheduler
    */
    @Bean(name = "Scheduler")
    public Scheduler scheduler(SchedulerFactoryBean schedulerFactoryBean) throws SchedulerException {
        return schedulerFactoryBean.getScheduler();
    }

    /**
     * quartz初始化监听器 : 这个监听器可以监听到工程的启动,在工程停止再启动时可以让已有的定时任务继续进行。
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    /**
     * 解决:Job的创建是有Quartz通过反射创建的,并未交由Spring容器创建。故原则上来说,是无法在Job实例中使用依赖注入的。
     */
    public final class AutowiredSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {
        /**
         * AutowireCapableBeanFactory: 是在BeanFactory的基础上实现对已存在实例的管理。
         * 可以使用这个接口集成其他框架,捆绑并填充并不由Spring管理生命周期并已存在的实例。
         * 参考: https://www.jianshu.com/p/14dd69b5c516
         */
        private AutowireCapableBeanFactory beanFactory;

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) {
            this.beanFactory = applicationContext.getAutowireCapableBeanFactory();
        }

        @Override
        protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
            Object jobInstance = super.createJobInstance(bundle);
            beanFactory.autowireBean(jobInstance);
            return jobInstance;
        }
    }

}
/**
 * @Author: rhb
 * @Date: 2020/9/30 15:11
 * @Description: Job基础服务
 */
@Slf4j
@Service
@Transactional
public class JobBaseServiceImpl implements JobBaseService {

    @Autowired
    SchedulerFactoryBean schedulerFactoryBean;

    private Scheduler scheduler;

    @PostConstruct
    public void init(){
        this.scheduler = schedulerFactoryBean.getScheduler();
    }

    @Override
    public Result addJob(JobDTO jobDTO) {
        try {
            Class cla = Class.forName(jobDTO.getClassJobPath());

            JobDetail jobDetail = JobBuilder.newJob(cla)
                    .withIdentity(jobDTO.getClassJobName(),jobDTO.getClassJobGroup())
                    .withDescription(jobDTO.getClassJobDescription())
                    .storeDurably(true)
                    .build();

            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobDTO.getClassJobCron());

            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(jobDTO.getClassJobName(),jobDTO.getClassJobGroup())
                    .withDescription(jobDTO.getClassJobDescription())
                    .withSchedule(cronScheduleBuilder)
                    .build();

            scheduler.scheduleJob(jobDetail,trigger);
        } catch (ClassNotFoundException e) {
            log.info("Job基础服务 | 添加失败 | 类路径错误");
            Assert.isTrue(false,"类路径错误");
        } catch (SchedulerException e) {
            log.info("Job基础服务 | 添加失败 | cron表达式错误");
            Assert.isTrue(false,"cron表达式错误");
        }
        return ResultUtils.success("添加成功");
    }

    @Override
    public Result deleteJob(JobDTO jobDTO) {
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobDTO.getClassJobName(), jobDTO.getClassJobGroup());
            JobKey jobKey = JobKey.jobKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());

            scheduler.pauseTrigger(triggerKey);
            scheduler.unscheduleJob(triggerKey);
            scheduler.deleteJob(jobKey);
        } catch (SchedulerException e) {
            log.info("Job基础服务 | 删除失败 | "+e.getMessage());
            Assert.isTrue(false,e.getMessage());
        }
        return ResultUtils.success("删除成功");
    }

    @Override
    public Result rescheduleJob(JobDTO jobDTO) {
        TriggerKey triggerKey = TriggerKey.triggerKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());

        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(jobDTO.getClassJobCron());

        try {
            CronTrigger cronTrigger = (CronTrigger) scheduler.getTrigger(triggerKey);

            cronTrigger.getTriggerBuilder().withSchedule(cronScheduleBuilder).build();

            scheduler.rescheduleJob(triggerKey,cronTrigger);
        } catch (SchedulerException e) {
            log.info("Job基础服务 | 重启失败 | "+e.getMessage());
            Assert.isTrue(false,e.getMessage());
        }

        return ResultUtils.success("重启成功");
    }

    @Override
    public Result pauseJob(JobDTO jobDTO) {
        JobKey jobKey = JobKey.jobKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());
        try {
            scheduler.pauseJob(jobKey);
        } catch (SchedulerException e) {
            log.info("Job基础服务 | 暂停失败 | "+e.getMessage());
            Assert.isTrue(false,e.getMessage());
        }
        return ResultUtils.success("暂停成功");
    }

    @Override
    public Result resumeJob(JobDTO jobDTO) {
        JobKey jobKey = JobKey.jobKey(jobDTO.getClassJobName(),jobDTO.getClassJobGroup());
        try {
            scheduler.resumeJob(jobKey);
        } catch (SchedulerException e) {
            log.info("Job基础服务 | 恢复失败 | "+e.getMessage());
            Assert.isTrue(false,e.getMessage());
        }
        return ResultUtils.success("恢复成功");
    }

}
        <!--quartz依赖-->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.zaxxer</groupId>
                    <artifactId>HikariCP-java7</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
        </dependency>

        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
            <version>3.3.1</version>
        </dependency>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值