11

我使用 sprint boot 1.3、spring 4.2

在这个班

@Service
public class PaymentServiceImpl implements PaymentService {
    ....
    @Transactional
    @Override
    public void processPayment() {
        List<Payment> payments = paymentRepository.findDuePayment();
        processCreditCardPayment(payments);
    }
}

我想每隔 x 时刻调用一次 processPayment。

这个 x 时刻设置在数据库中。用户可以修改它。

所以我认为我不能使用注释。

我开始这个这个

@EntityScan(basePackageClasses = {MyApp.class,     Jsr310JpaConverters.class})
@SpringBootApplication
@EnableCaching
@EnableScheduling
public class MyApp {

    @Autowired
    private DefaultConfigService defaultConfigService;

    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }

    @Bean
    public TaskScheduler poolScheduler() {
        SimpleAsyncTaskExecutor taskScheduler = new SimpleAsyncTaskExecutor();

        DefaultConfigDto defaultConfigDto = defaultConfigService.getByFieldName("payment-cron-task");
        String cronTabExpression = "0 0 4 * * ?";
        if (defaultConfigDto != null && !defaultConfigDto.getFieldValue().isEmpty()) {
            cronTabExpression = "0 0 4 * * ?";
        }

        appContext.getBean("scheduler");

        taskScheduler.schedule(task, new CronTrigger(cronTabExpression));
        return scheduler;
    }

也许这不是好方法。

有什么建议吗?

如果我需要创建一个类似的属性,不知道是否要获取我的上下文

@Autowired
ConfigurableApplicationContext context;

然后主要是

public static void main(String[] args) {
        context = SpringApplication.run(MyApp.class, args);
}
4

2 回答 2

19

看这个问题似乎你想更新调度程序,而不重新启动。

您共享的代码仅确保从 DB 中选择配置,但如果不重新启动应用程序,它将不会刷新。

以下代码将使用 spring 上下文中可用的默认调度程序,并根据数据库中可用的 cron 设置动态计算下一次执行时间:

这是示例代码:

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;

@SpringBootApplication
@EnableScheduling
public class Perses implements SchedulingConfigurer {
    private static final Logger log = LoggerFactory.getLogger(Perses.class);
   
    @Autowired
    private DefaultConfigService defaultConfigService;

    @Autowired
    private PaymentService paymentService;

    public static void main(String[] args) {
        SpringApplication.run(Perses.class, args);
    }

    private String cronConfig() {
        String cronTabExpression = "*/5 * * * * *";
        if (defaultConfigDto != null && !defaultConfigDto.getFieldValue().isEmpty()) {
            cronTabExpression = "0 0 4 * * ?";
        }
        return cronTabExpression;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(new Runnable() {
            @Override
            public void run() {
                paymentService.processPayment();
            }
        }, new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                String cron = cronConfig();
                log.info(cron);
                CronTrigger trigger = new CronTrigger(cron);
                Date nextExec = trigger.nextExecutionTime(triggerContext);
                return nextExec;
            }
        });
    }
}
于 2016-05-20T00:05:04.023 回答
1

如果有人仍然有这个问题,一个更好的解决方案是在你想要的时候从数据库中获取价值而不需要做很多更改,每分钟运行一次 cron 并在当前分钟与数据库中的配置值增量之间获取 mod,如果这个 mod 等于 0 意味着它有运行就像它是一个数学倍数,所以如果你希望它每 5 分钟运行一次,例如 delta 应该是 5。

一个样品:

@Scheduled(cron = "0 */1 * * * *") //fire every minute
public void perform() {

    //running
    Integer delta = 5;//get this value from databse
    Integer minutes = getField(Calendar.MINUTE)//calendar for java 7;
    Boolean toRun = true;//you can also get this one from database to make it active or disabled
  
    toRun = toRun && (minutes % delta == 0);
    if (toRun && (!isRunning)) {
       isRunning = true;
       try {
         //do your logic here
       } catch (Exception e) { }
        isRunning = false;
    }
}

public Integer getField(int field) {

    Calendar now = Calendar.getInstance();

    if(field == Calendar.MONTH) {
        return now.get(field)+ 1; // Note: zero based!
    }else {
        return now.get(field);
    }
}

希望这有帮助:D

于 2021-01-25T15:05:49.637 回答