Как запустить фоновую задачу в веб-приложении на основе сервлета?
Я использую 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.