Как запустить фоновую задачу в веб-приложении на основе сервлета?

Я использую Java и хочу, чтобы сервлет постоянно работал в моем приложении, но я не понимаю, как это сделать. В моем сервлете есть метод, который ежедневно подсчитывает количество пользователей из базы данных, а также общее количество пользователей из всей базы данных. Поэтому я хочу, чтобы сервлет постоянно работал для этого.

5 ответов

Решение

Ваша проблема в том, что вы неправильно поняли цель сервлета. Он предназначен для обработки HTTP-запросов, не более того. Вы хотите просто фоновое задание, которое выполняется один раз в день.

EJB доступен? использование @Schedule

Если ваша среда поддерживает EJB (например, WildFly, JBoss AS/EAP, TomEE, GlassFish и т. Д.), Используйте @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.
    }

} 

Да, это действительно все. Контейнер будет автоматически забирать и управлять им.

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);
    }

    @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.
    }

}

Никогда не думай об использовании java.util.Timer / java.lang.Thread в Java EE

Никогда не используйте напрямую java.util.Timer и / или java.lang.Thread в Java EE. Это рецепт неприятностей. Подробное объяснение можно найти в этом ответе, связанном с JSF, на тот же вопрос: порождение потоков в управляемом компоненте JSF для запланированных задач с использованием таймера.

Я бы предложил использовать такую ​​библиотеку, как кварц, чтобы выполнять задачу через регулярные промежутки времени. Что на самом деле делает сервлет? Он отправляет вам отчет?

Реализуйте два класса и вызовите 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

В производственной системе может работать несколько контейнеров без поддержки jee. Используйте другой корпоративный планировщик, такой как Quartz scheduler, который можно настроить на использование базы данных для задачи maamgememt.

Другие вопросы по тегам