在服务器端为servlet JSP MVC网站运行定期任务

jss*_*hah 19 java servlets scheduled-tasks

我使用servlet和JSP开发了一个Web应用程序.我本身并没有使用任何框架,而是使用我自己的自制MVC框架.我使用MySQL作为后端.

我想做以下事情:

  1. 每小时清理数据库中的一些数据
  2. 在某个XML文件中每15分钟生成并存储有关数据的统计信息

问题是:目前我的所有代码都是从客户端收到的请求运行的.

如何在服务器端运行定期任务?

我现在的一个解决方案是在控制器的init函数中创建一个线程.还有其他选择吗?

Bal*_*usC 41

您可以使用ServletContextListener在webapp的启动时执行一些初始化.运行定期任务的标准Java API方式是Timer和的组合TimerTask.这是一个启动示例:

public void contextInitialized(ServletContextEvent event) {
    Timer timer = new Timer(true);
    timer.scheduleAtFixedRate(new CleanDBTask(), 0, oneHourInMillis);
    timer.scheduleAtFixedRate(new StatisticsTask(), 0, oneQuartInMillis);
}
Run Code Online (Sandbox Code Playgroud)

两个任务的位置如下:

public class CleanDBTask extends TimerTask {
    public void run() {
        // Implement.
    }
}
Run Code Online (Sandbox Code Playgroud)

利用Timer然而,不使用Java EE建议.如果任务抛出异常,那么整个Timer线程都会被终止,你基本上需要重新启动整个服务器才能让它再次运行.该Timer也是在系统时钟的变化很敏感.

较新的和更强大的java.util.concurrent方式将是一个组合ScheduledExecutorService,只是一个Runnable.这是一个启动示例:

private ScheduledExecutorService scheduler;

public void contextInitialized(ServletContextEvent event) {
    scheduler = Executors.newSingleThreadScheduledExecutor();
    scheduler.scheduleAtFixedRate(new CleanDBTask(), 0, 1, TimeUnit.HOURS);
    scheduler.scheduleAtFixedRate(new StatisticsTask(), 0, 15, TimeUnit.MINUTES);
}

public void contextDestroyed(ServletContextEvent event) {
    scheduler.shutdownNow();
}
Run Code Online (Sandbox Code Playgroud)

  • 只想添加BalusC的精彩答案,即如果在运行中遇到异常,`ScheduledExecutorService`的`scheduleAtFixedRate`和`scheduleWithFixedDelay`方法将禁止将来的执行.所以请记住处理您的例外情况.`如果任务的任何执行遇到异常,则后续执行被禁止 (2认同)