关于Spring boot中的Quartz配置启动开关问题(启动、停止)

最近在做一个项目,项目中有多个模块,总体构架为SpringBoot +Quartz+其他(其他的不是重点啦)。

问题提出:

项目中会有Quartz做的定时任务模块,至于怎么使用Quartz网上一搜一大把,在这里不再细讲,

我要说的是,在开发和实际部署环境中如何避免定时任务重复执行?

例如:项目开发完成后已经部署到服务器,但是后期肯定是需要维护的呀,

那么问题来了,你在本地开发环境启动项目的时候,如果不做处理,呵呵。。。

结果可想而知,同一个定时任务,必然会执行两遍,如果是N个人维护这个程序,任务必将执行N+1次(服务器 一次)。

当然,前提是你们用的同一个数据库,大多数情况下为了偷懒(其实也是为了数据一致性啦),

程序猿一般会使用真实的服务器来运行程序。

 

那么如何在修改其他(非定时任务)模块时,在开发环境中关闭Quartz的定时任务呢?当然还不能影响服务器的任务执行。

在网上漂了大半天,也没有实际有效的解决办法,下面说说我的解决办法吧,如果你有更好的办法,也很希望你能告诉我,让我们共同进步。

首先,不同的环境我是有不同的配置文件的,主配置文件内容如下:

spring:
  profiles:
    #    生产环境
    # active: prd
    #    开发环境
    active: dev

备注:我用的YML文件格式,其他格式类似,遵循其道即可。

在实际配置文件中加入开关(自定义的名字,可以改为你喜欢的名字)选项:

开发环境:

    # 开启定时任务 true为启动 false为关闭
    scheduling:
        enabled: false

 生产环境:

    # 开启定时任务 true为启动 false为关闭
    scheduling:
        enabled: true

 配置文件到此为止,简单吧,以下代码是QuartzSchedule中控制Schedule的配置和执行。

------------ 分割线 --------------------------------------------------

以下内容可能根据不同的人来说并不相同,请不要说你找不到这些代码,

你找一下你的Schedule是在哪里控制的,加入开关控制即可。

 

我在网上搜了好久也没有好的控制办法,经过对Quartz代码的解读,我发现Quartz的初始化是SpringBoot在内部自动加载的,

很难去不让它加载,不然你要修改Quartz的内部代码,不是不可以,但这必然不是我们想要的。

 

于是我想了个曲线救国的方式:Schedule可以初始化和加载,去控制它的执行,这个Schedule是程序运行时初始化的,

必然是单独运行的,所以修改它不会影响服务器的定时任务。

SchedulerFactoryBean factory = new SchedulerFactoryBean()

这个是我程序中的调度工厂类,你的可能会不同,但大同小异,这个会生成具体的Schedule实体,此处初始化时会设置Schedule的相关属性:

@Configuration
public class ScheduleConfig
{
    //Jerry add for schedule control at 2020-2-22
    @Value("${jmbj.scheduling.enabled}")
    private Boolean scheduleEnableFlg;
    @Bean
    public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
    {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setDataSource(dataSource);

        // quartz参数
        Properties prop = new Properties();
        prop.put("org.quartz.scheduler.instanceName", "JmbjScheduler");
        prop.put("org.quartz.scheduler.instanceId", "AUTO");
        // 线程池配置
        prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
        prop.put("org.quartz.threadPool.threadCount", "20");
        prop.put("org.quartz.threadPool.threadPriority", "5");
        // JobStore配置
        prop.put("org.quartz.jobStore.class", "org.quartz.impl.jdbcjobstore.JobStoreTX");
        // 集群配置
        prop.put("org.quartz.jobStore.isClustered", "true");
        prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");

        // sqlserver 启用
        // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
        prop.put("org.quartz.jobStore.misfireThreshold", "12000");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        factory.setQuartzProperties(prop);

        factory.setSchedulerName("JmbjScheduler");
        // 延时启动
        factory.setStartupDelay(1);
        factory.setApplicationContextSchedulerContextKey("applicationContextKey");
        // 可选,QuartzScheduler
        // 启动时更新己存在的Job,这样就不用每次修改targetObject后删除qrtz_job_details表对应记录了
        factory.setOverwriteExistingJobs(true);

        //Jerry edit at 2020-2-22
        if (!scheduleEnableFlg) {
            factory.setAutoStartup(false);
        }else
        {
            // 设置自动启动,默认为true
            factory.setAutoStartup(true);
        }
        return factory;
    }
}

上面的属性中,如果要关闭schedule必须将自动启动的选项设置为false,其他属性按你的需要进行设置即可。

 

以上配置加载后会去实例化schedule对象,如下图所示:

 @Autowired
    private Scheduler scheduler;

    @Autowired
    private SysJobMapper jobMapper;

    //Jerry add for schedule control at 2020-2-22
    @Value("${jmbj.scheduling.enabled}")
    private Boolean scheduleEnableFlg;
    /**
     * 项目启动时,初始化定时器 
     * 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据)
     */
    @PostConstruct
    public void init() throws SchedulerException, TaskException {

        //Jerry edit at 2020-2-22
        if (scheduleEnableFlg) {
            List<SysJob> jobList = jobMapper.selectJobAll();
            for (SysJob job : jobList) {
                updateSchedulerJob(job, job.getJobGroup());
            }
            log.info("定时任务已启动。");
        } else {
//            scheduler.shutdown();
            log.info("定时任务未启动。");
        }
    }

  这个是从配置文件中读取控制开关。

@Value("${jmbj.scheduling.enabled}")
    private Boolean scheduleEnableFlg;

以上是初始化Schedule后会去数据库中查找设置的定时任务:

如果是开发环境必然也是没必要去查询数据库了,这样必然也不会去执行定时任务啦!

 

需要注意的地方:开始还将schedule设置了shutdown();可以设置,但是没有必要,因为schedule中没有任何任务,所以不关闭也无所谓,性能嘛,我觉得可以忽略,但未测试。切记设置自动启动未false!!

转载请注明出处,如有其它办法,欢迎一起讨论。

 

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
### 回答1: Spring Boot可以很方便地整合Quartz,只需要在pom.xml添加相关依赖,然后在配置文件配置Quartz相关属性即可。 具体步骤如下: 1. 在pom.xml添加Quartz依赖: ``` <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.2</version> </dependency> ``` 2. 在配置文件配置Quartz相关属性: ``` spring.quartz.job-store-type=jdbc spring.quartz.jdbc.initialize-schema=always spring.quartz.properties.org.quartz.scheduler.instanceName=myScheduler spring.quartz.properties.org.quartz.scheduler.instanceId=AUTO spring.quartz.properties.org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX spring.quartz.properties.org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate spring.quartz.properties.org.quartz.jobStore.dataSource=myDS spring.quartz.properties.org.quartz.jobStore.tablePrefix=QRTZ_ spring.quartz.properties.org.quartz.dataSource.myDS.driverClassName=com.mysql.jdbc.Driver spring.quartz.properties.org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz?useUnicode=true&characterEncoding=utf-8&useSSL=false spring.quartz.properties.org.quartz.dataSource.myDS.user=root spring.quartz.properties.org.quartz.dataSource.myDS.password=root ``` 3. 创建Job类和Trigger类: ``` @Component public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("Hello, Quartz!"); } } @Configuration public class QuartzConfig { @Bean public JobDetail myJobDetail() { return JobBuilder.newJob(MyJob.class) .withIdentity("myJob") .storeDurably() .build(); } @Bean public Trigger myTrigger() { return TriggerBuilder.newTrigger() .forJob(myJobDetail()) .withIdentity("myTrigger") .withSchedule(CronScheduleBuilder.cronSchedule("/5 * * * * ?")) .build(); } } ``` 4. 在启动注入SchedulerFactoryBean并启动Quartz: ``` @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Autowired private SchedulerFactoryBean schedulerFactoryBean; @PostConstruct public void startQuartz() throws SchedulerException { schedulerFactoryBean.getScheduler().scheduleJob(quartzConfig.myJobDetail(), quartzConfig.myTrigger()); } } ``` 这样就完成了Spring Boot整合Quartz配置。在启动应用程序时,Quartz会自动创建表并启动定时任务。 ### 回答2: Spring Boot是基于Spring Framework的快速应用开发框架,而Quartz是一个任务调度框架,可以帮助我们定义和执行各种类型的后台作业。本文将为你介绍如何使用Spring Boot整合Quartz框架。 1. 添加依赖 在Spring Boot使用Quartz需要添加以下依赖: ``` <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz-jobs</artifactId> <version>2.3.0</version> </dependency> ``` 2. 配置Job 在Quartz,Job是需要执行的任务,我们需要定义一个类来实现这个Job。 ``` public class MyJob implements Job { @Override public void execute(JobExecutionContext context) throws JobExecutionException { // 任务逻辑 } } ``` 3. 配置Trigger 在Quartz,Trigger用于定义任务执行的时间和频率。 ``` public class MyTrigger { public Trigger getTrigger() { return TriggerBuilder.newTrigger() .withIdentity("myTrigger", "group1") .withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")) .forJob("myJob", "group1") .build(); } } ``` 在上面的代码,我们使用Cron表达式来定义Job的执行时间。 4. 配置Scheduler 在Quartz,Scheduler是最核心的部分,它负责管理所有的Job和Trigger,并按照预定的时间执行任务。 ``` @Configuration public class SchedulerConfig { @Autowired private ApplicationContext applicationContext; @Bean public SchedulerFactoryBean schedulerFactoryBean() throws IOException { SchedulerFactoryBean factory = new SchedulerFactoryBean(); factory.setQuartzProperties(quartzProperties()); factory.setJobFactory(springBeanJobFactory()); return factory; } @Bean public Properties quartzProperties() throws IOException { PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties")); propertiesFactoryBean.afterPropertiesSet(); return propertiesFactoryBean.getObject(); } @Bean public SpringBeanJobFactory springBeanJobFactory() { AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory(); jobFactory.setApplicationContext(applicationContext); return jobFactory; } @Bean public Scheduler scheduler() throws IOException { return schedulerFactoryBean().getScheduler(); } @Bean public JobDetail myJobDetail() { return JobBuilder.newJob(MyJob.class) .withIdentity("myJob", "group1") .storeDurably() .build(); } @Bean public Trigger myTrigger() { return new MyTrigger().getTrigger(); } @PostConstruct public void init() throws SchedulerException, IOException { scheduler().addJob(myJobDetail(), true); scheduler().scheduleJob(myTrigger()); scheduler().start(); } } ``` 在上面的代码,我们创建了一个SchedulerFactoryBean用于创建Scheduler实例,并在配置创建了多个Bean,包括JobDetail、Trigger和自定义的SpringBeanJobFactory。 最后,在@PostConstruct注解下,我们将Job和Trigger添加到Scheduler实例,并启动Scheduler开始任务调度。 5. 编写Quartz.properties文件 在resources目录下创建quartz.properties文件,用于配置Quartz的一些属性。 ``` org.quartz.scheduler.instanceName = MyScheduler org.quartz.threadPool.threadCount = 3 org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.dataSource = myDS org.quartz.jobStore.tablePrefix = QRTZ_ org.quartz.dataSource.myDS.driver = com.mysql.jdbc.Driver org.quartz.dataSource.myDS.URL = jdbc:mysql://localhost:3306/mydb org.quartz.dataSource.myDS.user = myuser org.quartz.dataSource.myDS.password = mypassword org.quartz.dataSource.myDS.maxConnections = 10 ``` 以上就是使用Spring Boot整合Quartz框架的全部步骤,通过以上步骤,我们可以轻松地创建和调度各种类型的后台任务。 ### 回答3: Spring Boot 是一个基于 Spring 框架的快速开发框架,使得构建Spring应用程序非常容易。Quartz 是一个用于作业调度的开源框架,可以通过定义任务和调度器来实现任务的自动化调度。Spring BootQuartz 框架的整合,则可以帮助开发人员更加便捷地实现任务调度。 Spring Boot整合Quartz的步骤如下: 1.在 pom.xml 添加 Quartz 的依赖: ```xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.3.0</version> </dependency> ``` 2.创建一个 Job 类,在该类实现具体要执行的任务逻辑,并继承 org.quartz.Job 接口: ```java public class HelloWorldJob implements Job{ public void execute(JobExecutionContext context) throws JobExecutionException { System.out.println("Hello World."); } } ``` 3.在配置文件添加 quartz 相关的配置,例如在 application.properties 文件添加如下配置: ``` spring.quartz.job-store-type=jdbc spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=123456 spring.quartz.jdbc.initialize-schema=always ``` 4.创建 SchedulerFactoryBean 类,用于创建调度器,并将 Job 注册到调度器: ```java @Configuration public class QuartzConfig { @Autowired private DataSource dataSource; @Bean public JobDetail jobDetail() { return JobBuilder.newJob(HelloWorldJob.class) .withIdentity("helloJob") .storeDurably() .build(); } @Bean public Trigger trigger() { SimpleScheduleBuilder scheduleBuilder = SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(10) .repeatForever(); return TriggerBuilder.newTrigger() .forJob(jobDetail()) .withIdentity("helloTrigger") .withSchedule(scheduleBuilder) .build(); } @Bean public SchedulerFactoryBean schedulerFactory() { SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean(); schedulerFactoryBean.setDataSource(dataSource); schedulerFactoryBean.setJobDetails(jobDetail()); schedulerFactoryBean.setTriggers(trigger()); return schedulerFactoryBean; } } ``` 在 SchedulerFactoryBean 类,首先创建了一个 JobDetail 类,用于描述 Job 相关的信息。然后,通过调用 TriggerBuilder 类的 newTrigger() 方法创建了一个 trigger,用于描述 Job 调度的策略和时间。最后,通过调用 SchedulerFactoryBean 的 setJobDetails() 方法和 setTriggers() 方法将 Job 和 trigger 注册到调度器。 5.启动应用程序,任务就会开始按照调度器定义的策略自动运行。 总的来说,Spring Boot整合Quartz非常容易,只需添加相应的依赖、编写 Job 类和 SchedulerFactoryBean 类,并在配置文件添加相关的配置即可获得方便的任务调度功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简码笔记

您的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值