Как запустить фоновую задачу в веб-приложении на основе сервлета? - PullRequest
88 голосов
/ 14 января 2011

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

Ответы [ 5 ]

200 голосов
/ 14 января 2011

Ваша проблема в том, что вы неправильно поняли цель сервлета .Он предназначен для обработки 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 для запланированных задач с использованием таймера .

4 голосов
/ 14 января 2011

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

3 голосов
/ 05 марта 2018

Реализация двух классов и вызов 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();
    }
}
2 голосов
/ 22 декабря 2011

Вы можете использовать cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php

0 голосов
/ 21 февраля 2016

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

...