web-dev-qa-db-ja.com

実行時にSpringの@Scheduled fixedDelayを変更する方法

バッチジョブを一定の間隔で実行する必要があり、実行時にこのバッチジョブの時間を変更できます。このために、Springフレームワークで提供される@Scheduledアノテーションに出会いました。しかし、実行時にfixedDelayの値をどのように変更するかはわかりません。私はいくつかのグーグルを試しましたが、有用なものは見つかりませんでした。

26
jsf

Triggerを使用して、次の実行時間を動的に設定できます。ここで私の答えを参照してください:

Springによるプログラムによるジョブのスケジュール(fixedRateを動的に設定)

24
ach

スプリングブートでは、アプリケーションプロパティを直接使用できます!

例えば:

_@Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds}000")
private void process() {
    // your impl here
}
_

プロパティが定義されていない場合は、デフォルト値を使用することもできます。たとえば、デフォルトの「60」(秒)を使用できます。

_@Scheduled(fixedDelayString = "${my.property.fixed.delay.seconds:60}000")
_

私が発見した他のこと:

  • メソッドは無効でなければなりません
  • メソッドにはパラメーターを指定しないでください
  • メソッドはprivateになります

private可視性を便利に使用できることがわかり、次のように使用しました。

_@Service
public class MyService {
    public void process() {
        // do something
    }

    @Scheduled(fixedDelayString = "${my.poll.fixed.delay.seconds}000")
    private void autoProcess() {
        process();
    }
}
_

privateであるため、スケジュールされたメソッドはサービスに対してローカルであり、サービスのAPIの一部にはなりません。

また、このアプローチでは、process()メソッドが値を返すことができますが、_@Scheduled_メソッドは値を返すことができません。たとえば、process()メソッドは次のようになります。

_public ProcessResult process() {
    // do something and collect information about what was done
    return processResult; 
}
_

処理中に発生したことに関する情報を提供します。

48
Bohemian

インターフェースを作成し、そのようなもの:

    public abstract class DynamicSchedule{
        /**
         * Delays scheduler
         * @param milliseconds - the time to delay scheduler.
         */
        abstract void delay(Long milliseconds);

        /**
         * Decreases delay period
         * @param milliseconds - the time to decrease delay period.
         */
        abstract void decreaseDelayInterval(Long milliseconds);

        /**
         * Increases delay period
         * @param milliseconds - the time to increase dela period
        */
        abstract void increaseDelayInterval(Long milliseconds);
}

次に、spring-contextプロジェクトのorg.springframework.schedulingにあるTriggerインターフェースを実装しましょう。

import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

import Java.util.Date;
import Java.util.concurrent.ScheduledFuture;

public class CustomDynamicSchedule extends DynamicSchedule implements Trigger {

    private TaskScheduler taskScheduler;
    private ScheduledFuture<?> schedulerFuture;

    /**
     * milliseconds
     */
    private long delayInterval;

    public CustomDynamicSchedule(TaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }


    @Override
    public void increaseDelayInterval(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval += delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public void decreaseDelayInterval(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval -= delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public void delay(Long delay) {
        if (schedulerFuture != null) {
            schedulerFuture.cancel(true);
        }
        this.delayInterval = delay;
        schedulerFuture = taskScheduler.schedule(() -> { }, this);
    }

    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        Date lastTime = triggerContext.lastActualExecutionTime();
        return (lastTime == null) ? new Date() : new Date(lastTime.getTime() + delayInterval);
    }
}

今の設定:

@Configuration
public class DynamicSchedulerConfig {
    @Bean
    public CustomDynamicSchedule getDynamicScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.initialize();
        return  new CustomDynamicSchedule(threadPoolTaskScheduler);
    }
}

および使用法:

@EnableScheduling
@Component
public class TestSchedulerComponent {

    @Autowired
    private CustomDynamicSchedule dynamicSchedule;

    @Scheduled(fixedDelay = 5000)
    public void testMethod() {
        dynamicSchedule.delay(1000l);
        dynamicSchedule.increaseDelayInterval(9000l);
        dynamicSchedule.decreaseDelayInterval(5000l);
    }

}
7
grep

私の知る限り、Spring APIでは、トリガーを変更するために必要な内部にアクセスできません。ただし、代わりにBeanを手動で構成することもできます。

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
    <property name="jobDetail" ref="jobDetail" />
    <property name="startDelay" value="10000" />
    <property name="repeatInterval" value="50000" />
</bean>

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
    <property name="triggers">
        <list>
            <ref bean="simpleTrigger" />
        </list>
    </property>
</bean>

次に、SchedulerFactoryBeanに記載されているように:

実行時にジョブを動的に登録するには、このSchedulerFactoryBeanへのBean参照を使用して、Quartz Scheduler(org.quartz.Scheduler)。これにより、新しいジョブとトリガーを作成したり、スケジューラ全体を制御および監視したりできます。

2
Víctor Romero