web-dev-qa-db-ja.com

サーブレットベースのWebアプリケーションでバックグラウンドタスクを実行する方法

Javaを使用しており、アプリケーションでサーブレットを継続的に実行したいのですが、実行方法がわかりません。サーブレットには、毎日のデータベースと、データベース全体からのユーザーの合計数ですので、そのためにサーブレットを継続的に実行したいです。

89
pritsag

問題は、 servlet の目的を誤解していることです。 HTTPリクエストに基づいて行動することを目的としていますが、それ以上のものはありません。毎日1回実行されるバックグラウンドタスクのみが必要です。

EJBは利用可能ですか? @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.
    }

} 

はい、それだけです。コンテナは自動的にピックアップして管理します。

EJBは利用できませんか? 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 EE /サーブレットベースの環境でJava.util.Timer/Java.lang.Threadを使用することを考えないでください

最後になりましたが、neverは、Java EEでJava.util.Timerおよび/またはJava.lang.Threadを直接使用します。これはトラブルのレシピです。詳細な説明は、同じ質問に関するこのJSF関連の回答にあります。 タイマーを使用してスケジュールされたタスクのJSF管理Beanでスレッドを生成する

201
BalusC

タスクを定期的に実行するには、クォーツのようなライブラリを使用することをお勧めします。サーブレットは実際に何をしますか?レポートを送信しますか?

4
Twister

2つのクラスを実装し、mainstartTask()を呼び出します。

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();
    }
}
3
2
Rookie

複数の非jeeコンテナーが実行されている可能性のある実動システム。タスクmaamgememtにデータベースを使用するように構成できるQuartzスケジューラーのようなエンタープライズスケジューラーを使用します。

0
Jeryl Cook