web-dev-qa-db-ja.com

Springのスケジュールされたタスクがアプリケーションの起動時に開始されない

アプリケーションにCRONを使用してセットアップされた@Scheduledタスクがあり、4時間ごとに実行されます。私が直面している問題は、CRONジョブがアプリケーションの起動直後に開始されないが、アプリケーションの起動後4時間で開始されることです。

タスク内で@PostConstructメソッドを使用してそれを呼び出そうとしましたが、初期化されていないSpringコンテキストが原因でエラーが発生します。

スケジュールされたタスクをアプリケーションの展開直後に実行し、展開後4時間ごとに実行する方法を教えてください。

編集:
スケジュールされたメソッドは他のBeanに依存しているため、@PostConstructは使用しません。他のBeanは、このPostConstructメソッドが何らかの理由で実行されたときに初期化されません。

4
v1shnu

0までに*/4 * * *「4時間ごと(0:00、4:00、8:00など)の0分に」を指定します。これは起動時ではなく、4時間ごとです。欲しいです。初期遅延とレートは次の方法で指定できます。

@Scheduled(initialDelay=0, fixedRate=4*60*60*1000)

ハードコードされた値が心配な場合でも、構成値を指定できます。

@Scheduled(initialDelay=0, fixedRateString = "${some.config.string}")
5
Tomas F.

アプリの構成に_@EnableScheduling_がありました。スケジュールされたタスククラスに@Scheduled(fixedDelay=5000)がありました。それでもうまくいきませんでした。

スケジュールされたタスククラスに_@Service_を追加しましたが、すべて正常に機能しました。

これを試したかどうかはわかりませんが、@ScheduledinitialDelayと一緒に使用できます

固定遅延および固定レートのタスクの場合、メソッドのfirst実行まで待機するミリ秒数を示す初期遅延を指定できます。

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-annotation-support-scheduled

@Scheduled(initialDelay=0, fixedRate=5000)
public void doSomething() {
    // something that should execute periodically
}

これにより、アプリケーションの実行時にスケジュールされたメソッドが実行されると思います。

1
px06

initialDelayルールでcron属性を使用できず、再起動するたびにこのジョブを実行することが意図されている場合は、アプリケーションクラスにCommandLineRunnerを実装できます。

@SpringBootApplication
public class MyApplication implements CommandLineRunner {

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

    @Autowired
    private TaskService taskService;

    @Override
    public void run(final String... args) throws Exception {

        taskService.run();
    }

}

これは最善の戦略ではありませんが、機能します。

1
Dherik

Beanの_init_method_属性で実行するメソッドを指定するだけです。

Java構成:@Bean(init_method="methodWhichStartsTask")

XML構成:_<bean id="someId" class="com.example.Clazz" init-method="methodWhichStartsTask"/>_

これにより、Beanが適切に初期化された直後にメソッドが呼び出され、メソッドがスケジュールされている場合は、その後4時間ごとに呼び出されます。

0
Andrei Balici

@Scheduled内のcronの代わりに、以下のようにfixedRateを使用します。デフォルトでは、initialDelayは-1で、すぐに開始するか、0に設定できます。

@Scheduled(fixedRate=4*60*60*1000)
public void test() {
    System.out.println("helloworld");
}

私も同じ状況でした。月の1日ごとに、またアプリケーションの起動時にcronスケジューラを実行する必要があります。

これは私がApplicationListenerを使用して達成した方法です。

import org.springframework.context.ApplicationListener;
import org.springframework.boot.context.event.ApplicationReadyEvent;

@Component
public class ApplicationReadyListner implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        // callYourTask();
    }
}
0
Vishal Patel