Javaを使用していて、アプリケーションでサーブレットを継続的に実行したいのですが、方法がわかりません。私のサーブレットには、データベース全体からのユーザーの合計数だけでなく、データベースからのユーザー数を毎日提供するメソッドがあります。そのため、サーブレットを継続して実行したいと考えています。
Javaを使用していて、アプリケーションでサーブレットを継続的に実行したいのですが、方法がわかりません。私のサーブレットには、データベース全体からのユーザーの合計数だけでなく、データベースからのユーザー数を毎日提供するメソッドがあります。そのため、サーブレットを継続して実行したいと考えています。
回答:
問題は、サーブレットの目的を誤解していることです。HTTPリクエストに基づいて動作することを目的としています。毎日1回だけ実行されるバックグラウンドタスクが必要な場合。
@Schedule
お使いの環境がEJB(つまり、WildFly、JBoss、TomEE、Payara、GlassFishなどの実際のJava EEサーバー)をサポートしている場合は、@Schedule
代わりにを使用してください。ここではいくつかの例を示します。
@Singleton
public class BackgroundJobManager {
@Schedule(hour="0", minute="0", second="0", persistent=false)
public void someDailyJob() {
// Do your job here which should run every start of day.
}
@Schedule(hour="*/1", minute="0", second="0", persistent=false)
public void someHourlyJob() {
// Do your job here which should run every hour of day.
}
@Schedule(hour="*", minute="*/15", second="0", persistent=false)
public void someQuarterlyJob() {
// Do your job here which should run every 15 minute of hour.
}
@Schedule(hour="*", minute="*", second="*/5", persistent=false)
public void someFiveSecondelyJob() {
// Do your job here which should run every 5 seconds.
}
}
はい、それだけです。コンテナが自動的にピックアップして管理します。
ScheduledExecutorService
環境がEJBをサポートしていない場合(つまり、実際のJava EEサーバーではなく、Tomcat、Jettyなどのベアボーンサーブレットコンテナーを使用していない場合)は、を使用しますScheduledExecutorService
。これはによって開始できますServletContextListener
。以下はキックオフの例です。
@WebListener
public class BackgroundJobManager implements ServletContextListener {
private ScheduledExecutorService scheduler;
@Override
public void contextInitialized(ServletContextEvent event) {
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new SomeDailyJob(), 0, 1, TimeUnit.DAYS);
scheduler.scheduleAtFixedRate(new SomeHourlyJob(), 0, 1, TimeUnit.HOURS);
scheduler.scheduleAtFixedRate(new SomeQuarterlyJob(), 0, 15, TimeUnit.MINUTES);
scheduler.scheduleAtFixedRate(new SomeFiveSecondelyJob(), 0, 5, TimeUnit.SECONDS);
}
@Override
public void contextDestroyed(ServletContextEvent event) {
scheduler.shutdownNow();
}
}
ジョブクラスは次のようになります。
public class SomeDailyJob implements Runnable {
@Override
public void run() {
// Do your daily job here.
}
}
public class SomeHourlyJob implements Runnable {
@Override
public void run() {
// Do your hourly job here.
}
}
public class SomeQuarterlyJob implements Runnable {
@Override
public void run() {
// Do your quarterly job here.
}
}
public class SomeFiveSecondelyJob implements Runnable {
@Override
public void run() {
// Do your quarterly job here.
}
}
java.util.Timer
/の使用について考えないでくださいjava.lang.Thread
たJava EE /サーブレットベースの環境で最後になりましたが、決して直接使用していないjava.util.Timer
および/またはjava.lang.Thread
Java EEの中で。これはトラブルのレシピです。詳しい説明は、同じ質問に関するこのJSF関連の回答にあります:タイマーを使用してスケジュールされたタスクのためのJSF管理対象Beanでのスレッドの生成。
ScheduledExecutorService
:エグゼキュータですべての例外を必ずキャプチャしてください。run
メソッドから例外がエスケープされると、エグゼキュータは警告なしで実行を停止します。これはバグではない機能です。ドキュメントを読んで、グーグルで勉強してください。
scheduler.shutdownNow()
例のようにが正しく呼び出されない場合に発生します。これが呼び出されない場合、スケジュールスレッドは実際に実行され続けます。
タスクを定期的に実行するには、quartzのようなライブラリを使用することをお勧めします。サーブレットは実際には何をしますか?レポートを送信しますか?
2つのクラスを実装し、呼び出しstartTask()
の中でmain
。
public void startTask()
{
// Create a Runnable
Runnable task = new Runnable() {
public void run() {
while (true) {
runTask();
}
}
};
// Run the task in a background thread
Thread backgroundThread = new Thread(task);
// Terminate the running thread if the application exits
backgroundThread.setDaemon(true);
// Start the thread
backgroundThread.start();
}
public void runTask()
{
try {
// do something...
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
cron4jを使用できます。http://www.sauronsoftware.it/projects/cron4j/manual.php