如何在基于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理的数据库。