100

我正在使用 Java,我想保持一个 servlet 在我的应用程序中持续运行,但我不知道如何去做。我的 servlet 有一种方法可以每天计算数据库中的用户计数以及整个数据库中的用户总数。所以我想保持 servlet 持续运行。

4

5 回答 5

221

您的问题是您误解了servlet的用途。它旨在对 HTTP 请求采取行动,仅此而已。您只需要一个每天运行一次的后台任务。

EJB 可用吗?采用@Schedule

如果您的环境恰好支持 EJB(即真正的 Java EE 服务器,例如 WildFly、JBoss、TomEE、Payara、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.
    }

    @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 服务器,而是准系统 servletcontainer,例如 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 EE / Servlet 的环境中使用java.util.Timer/java.lang.Thread

最后但同样重要的是,永远不要直接在 Java EE 中使用java.util.Timer和/或。java.lang.Thread这是麻烦的秘诀。可以在这个与 JSF 相关的答案中找到关于同一问题的详细解释:Spawning threads in a JSF managed bean for scheduled tasks using a timer

于 2011-01-14T13:45:39.570 回答
4

我建议使用像石英这样的库来定期运行任务。servlet 究竟做了什么?它向您发送报告?

于 2011-01-14T13:08:04.263 回答
3

实现两个类并调用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();
    }
}
于 2018-03-05T17:49:56.027 回答
2

您可以使用 cron4j。http://www.sauronsoftware.it/projects/cron4j/manual.php

于 2011-12-22T08:13:51.010 回答
0

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

于 2016-02-21T15:31:16.113 回答