サーブレットベースの Web アプリケーションでバックグラウンド タスクを実行するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/4691132

質問

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

役に立ちましたか?

解決

あなたの問題は、その目的を誤解していることです。 サーブレット. 。これは 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.util.Timer/java.lang.Thread Java EE / サーブレットベースの環境で

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

他のヒント

定期的にタスクを実行するために、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();
    }
}

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top