我正在使用Java,但我想保持servlet在我的应用程序中连续运行,但是我没有得到如何做的信息。我的servlet有一种方法,可以每天提供数据库中用户的数量以及整个数据库中用户的总数。因此,我想为此继续保持servlet的运行。
我正在使用Java,但我想保持servlet在我的应用程序中连续运行,但是我没有得到如何做的信息。我的servlet有一种方法,可以每天提供数据库中用户的数量以及整个数据库中用户的总数。因此,我想为此继续保持servlet的运行。
Answers:
您的问题是您误解了servlet的目的。它旨在对HTTP请求执行操作,仅此而已。您只需要每天执行一次的后台任务。
@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.
}
}
是的,这就是全部。容器将自动进行拾取和管理。
ScheduledExecutorService
如果您的环境不支持EJB(即您不使用的不是真正的Java EE服务器,而是使用诸如Tomcat,Jetty等的准系统servlet容器),请使用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中使用java.util.Timer
和/或java.lang.Thread
在Java EE中使用。这是麻烦的秘诀。在与JSF相关的同一问题上可以找到详细的解释:使用timer在JSF管理的bean中生成线程以执行计划的任务。
ScheduledExecutorService
:确保在执行程序中捕获所有异常。如果从您的run
方法中逃脱了一个异常,则执行程序将静默停止执行。这是一个功能而不是错误。阅读文档并进行一些谷歌搜索。
scheduler.shutdownNow()
未按照示例正确调用,则会发生这种情况。如果未调用此函数,则调度线程确实将继续运行。
我建议使用石英等库,以便定期运行任务。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调度程序,可以将其配置为使用数据库来执行任务管理。