Java Spring引导:从数据库获取@Scheduled cron值

Java Spring引导:从数据库获取@Scheduled cron值,java,spring-boot,cron,scheduled-tasks,Java,Spring Boot,Cron,Scheduled Tasks,我正在使用springboot,在使用数据库中现有的值调度cron任务时遇到问题 目前,我正在从属性文件中读取如下值: @Scheduled(cron= "${time.export.cron}") public void performJob() throws Exception { // do something } 这可以很好地工作,但我不想从属性文件中获取值,而是想从数据库表中获取它们。是否可能以及如何实现?要实现目标,必须在运行时配置调度程序。这意味着您需要使用更多的低级调度器

我正在使用
springboot
,在使用数据库中现有的值调度
cron任务时遇到问题

目前,我正在从属性文件中读取如下值:

@Scheduled(cron= "${time.export.cron}")
public void performJob() throws Exception {
   // do something
}

这可以很好地工作,但我不想从属性文件中获取值,而是想从数据库表中获取它们。是否可能以及如何实现?

要实现目标,必须在运行时配置调度程序。这意味着您需要使用更多的低级调度器API。当您已经准备好连接数据库时,您就可以配置调度程序了。我认为您需要放弃使用@Scheduled注释,手动管理您的调度程序

我认为这些主题有助于描述我的意思:


  • 但是,您可以使用通配符方法拦截bean创建并用自定义元数据替换注释上的原始注释,但为了实现它,您必须了解许多框架细节以及@Scheduled annatation processor的工作方式。

    您需要从包含值的数据库表中加载属性存储。 并将该数据库属性与应用程序属性合并

        @Autowired
        private DataSource dataSource;
    
        @Autowired
        private DatabaseConfiguration configuration;
    
        @Bean(name = "propertyConfig")
        public DatabaseConfiguration getDatabaseConfiguration() {
            DatabaseConfiguration configuration = new DatabaseConfiguration(dataSource, "propertyTable", "key", "value");
            return configuration;
        }
    
        @Bean(name = "dbProperty")
        public Properties getDBProperties(){
            Properties properties = ConfigurationConverter.getProperties(configuration);
            return properties;
        }
    

    有关更多帮助,请参考

    ,您可以在SpringBootApplication主类或任何配置类中添加bean以从数据库获取cron值。示例代码如下:

    @Autowired
    private CronRepository cronRepo;
    
    @Bean
    public int getCronValue()
    {
        return cronRepo.findOne("cron").getCronValue();
    }
    
    @Scheduled(cron="#{@getCronValue}")
    
    您应该创建一个表,并在数据库中提供合适的值。之后,您可以在
    @Scheduled
    中提供bean。示例代码如下:

    @Autowired
    private CronRepository cronRepo;
    
    @Bean
    public int getCronValue()
    {
        return cronRepo.findOne("cron").getCronValue();
    }
    
    @Scheduled(cron="#{@getCronValue}")
    

    希望它能解决您的问题。

    使用@Bean注释的方法就可以了。但由于SpringBoot只调用此方法1次,然后返回缓存版本,所以需要重新启动Spring以获取新值

    要使用SchedulingConfigurer从数据库获取新的运行时,请执行以下操作:

    @Configuration
    public class SchedulerConfig implements SchedulingConfigurer {
    
        @Autowired
        private YourService yourService;
    
        @Bean
        public YourJob yourJob() {
            return new YourJob();
        }
    
        @Override
        public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
            taskRegistrar.addTriggerTask(
                    () -> yourJob().performJob(),
                    (TriggerContext triggerContext) -> yourService.getCron()
            );
        }
    
    }
    

    注意:不要以这种方式使用@Scheduled。

    对于spring,属性来自何处、文件、数据库、,git,只要它们最终是属性。我尝试实现一个从数据库中获取字符串值的方法,并尝试将此字符串注入@Scheduled,但它说:注释属性Scheduled.cron的值必须是常量表达式您不需要更改
    @Scheduled
    上的任何内容,您只需要检索属性,并将它们传递到
    上下文:属性占位符
    ,或者如果您使用java配置,则使用
    ApplicationContextInitializer
    添加
    PropertySource
    来执行相同的操作。这对我来说很好,但我们需要在类级别添加@EnableScheduling来运行/执行@Scheduled(cron=“#{@getCronValue}”)美好的这对我帮助很大!谢谢。这很好,节省了我很多时间。非常感谢。我很好奇我是否正在更新DB上的cron time值,它是否会拾取最新的cron time还是旧的cron time?我尝试了这种方法,但我得到了一个错误“请求的bean当前正在创建中:是否存在无法解决的循环引用?”。这个解决方案的重点似乎是支持将来在不重新启动的情况下更改cron值,那么,当您的cron在数据库中发生更改时,您如何做到这一点呢?@KenClark每次cron作业触发时,它都会从数据库中读取数据,以便下次运行。