#1 楼
您的问题是您误解了Servlet的目的。它旨在对HTTP请求执行操作,仅此而已。您只需要每天执行一次的后台任务。EJB是否可用?如果您的环境碰巧支持EJB(例如WildFly,JBoss,TomEE,Payara,GlassFish等真正的Java EE服务器),请使用
@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不可用?使用
@Schedule
如果您的环境不支持EJB(即您未使用的不是真正的Java EE服务器,而是使用了诸如Tomcat,Jetty等准系统的servlet容器),那么使用ScheduledExecutorService
。这可以通过ScheduledExecutorService
启动。这是一个启动示例:@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的环境中使用
ServletContextListener
/ java.util.Timer
最后但并非最不重要的是,永远不要在Java EE中直接使用
java.lang.Thread
和/或java.util.Timer
。这是麻烦的秘诀。在与JSF有关的同一问题上可以找到详细的解释:使用计时器在JSF托管Bean中生成线程以执行计划的任务。评论
@BalucS谢谢您,先生,您的解决方案对我有所帮助,我了解了ScheduledExecutorService,这对我来说是Java的新手。再次感谢您。
–pritsag
2011年1月15日7:36
@BalusC:将类UpdateCounts放在web.xml中的什么位置?
–阿什温
2012年6月13日9:38
@Ashwin web.xml是一个部署描述符。类UpdateCount与部署无关,因此不必将其放在web.xml中
–informatik01
13年8月12日在0:15
ScheduledExecutorService的一个关键问题:确保在执行程序中捕获所有异常。如果您的run方法逃脱了异常,则执行程序将静默停止执行。这是一个功能,而不是错误。阅读文档并进行一些谷歌搜索。
–罗勒·布尔克
14-10-18在17:50
@Agi:如果未按照示例正确调用scheduler.shutdownNow(),则会发生这种情况。如果未调用此函数,则调度线程确实将继续运行。
– BalusC
18年6月26日在15:12
#2 楼
我建议使用石英等库,以便定期运行任务。 servlet真正做什么?它会向您发送报告吗?评论
是的,它为我提供了每天创建的用户数以及数据库中的总用户数。
–pritsag
2011年1月14日13:09
hu?您能否描述系统的完整架构。我迷路了。
–扭曲者
2011年1月14日13:17
@Twister我是Java的新手,处于学习阶段,先生,对servlet的了解并不多。
–pritsag
2011年1月14日13:21
问题不在于servlet。您正在谈论什么应用程序? (ps:删除您的评论,尤其是我回答的评论是一个坏主意)
–扭曲者
2011年1月14日13:22
@twister,当用户点击该应用程序时,他将获得所有详细信息,例如今天创建了多少用户,到现在为止有多少用户被激怒等等。我想连续在后台运行servlet,以便用户可以获取更新我不知道这是不正确的解释。(ps:我知道这是个坏主意,抱歉。)
–pritsag
2011年1月14日13:26
#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();
}
}
评论
这绝对不是在Web应用程序中执行此操作的方法-而是查看@BalusC的上述答案-他在这里是正确的,我想您可以相信他的所有答案。
–吉屋
18年5月21日在13:46
评论
“连续运行”是什么意思?连续运行是什么意思?只要您的应用服务器运行,它就会一直运行
我不明白为什么它必须连续运行...如果有人想要“用户数”,那么他们会调用您的servlet方法,然后您将其提供给他们?
@trojanfoe实际上我想要每天的用户数,因此我将不得不每天手动运行servlet,而不是那样我想要连续运行servlet。所以我不需要每天运行servlet。
@pritsag:那里有一个servlet来满足用户请求,而不是运行批处理作业。