如何在基于servlet的Web应用程序中运行后台任务?

我正在使用Java,我想保持一个servlet在我的应用程序不断运行,但我没有得到如何做到这一点。 我的servlet有一个方法,每天从数据库中计算用户的数量,以及整个数据库的用户总数。 所以我想让这个servlet继续运行。

你的问题是你误解了servlet的用途。 它只是用来处理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. } } 

是的,这是真的。 容器将自动取出并pipe理它。

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 EE中使用java.util.Timer / java.lang.Thread

永远不要在Java EE中直接使用java.util.Timer和/或java.lang.Thread 。 这是麻烦的秘诀。 在JSF相关的答案中可以find一个详细的解释: 在一个JSF托pipebean中为使用计时器的计划任务产生线程 。

我会build议使用像石英这样的库来定期运行任务。 servlet真的做什么? 它发送给你一个报告?

在可能有多个非jee容器运行的生产系统中。 使用像Quartz调度程序这样的企业调度程序,它可以configuration为使用任务pipe理的数据库。