如何在基于Servlet的Web应用程序中运行背景任务?
题
我正在使用Java,我想在应用程序中保持servlet不断运行,但我没有得到如何做。我的servlet有一种方法,可以每天从数据库以及整个数据库中用户的总数中提供用户计数。因此,我想为此保持servlet不断运行。
解决方案
您的问题是您误解了 servlet. 。目的是根据HTTP请求采取行动,仅此而已。您只需每天运行一次的背景任务。
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服务器,而是使用BareletContainer,例如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 /基于Servlet的环境中
最后但并非最不重要的, 绝不 直接使用 java.util.Timer
和/或 java.lang.Thread
在Java Ee中。这是麻烦的秘诀。在同样的问题上,可以在此与JSF相关的答案中找到详尽的解释: 使用计时器的JSF托管BEAN中的产卵线程用于计划任务.
其他提示
我建议使用像石英这样的库来定期运行任务。 Servlet真正做什么?它给您发送报告吗?
实施两个类并致电 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 Scheduler之类的Anot Enterprise调度程序,可以配置为任务Maamgememt的数据库。
不隶属于 StackOverflow