如何在基于 servlet 的 Web 应用程序中运行后台任务? [英] How to run a background task in a servlet based web application?

查看:33
本文介绍了如何在基于 servlet 的 Web 应用程序中运行后台任务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

你的问题是你误解了servlet

一>.它旨在处理 HTTP 请求,仅此而已.您只需要一个每天运行一次的后台任务.

EJB 可用吗?使用 @Schedule

如果您的环境恰好支持 EJB(即真正的 Java EE 服务器,例如 WildFly、JBoss、TomEE、Payara、GlassFish 等),则使用 @Schedule 代替.以下是一些示例:

@Singleton公共类 BackgroundJobManager {@Schedule(小时=0",分钟=0",秒=0",持久=假)公共无效 someDailyJob() {//在这里做你的工作,它应该在每天开始的时候运行.}@Schedule(小时=*/1",分钟=0",秒=0",持久=假)公共无效 someHourlyJob() {//在这里做你应该每天每小时运行的工作.}@Schedule(小时=*",分钟=*/15",秒=0",持久=假)公共无效 someQuarterlyJob() {//在这里完成你的工作,它应该每 15 分钟运行一次.}@Schedule(小时=*",分钟=*",秒=*/5",持久=假)公共无效 someFiveSecondelyJob() {//在这里做你的工作,它应该每 5 秒运行一次.}}

是的,仅此而已.容器会自动提取和管理它.

EJB 不可用?使用 ScheduledExecutorService

如果您的环境不支持 EJB(即您使用的不是真正的 Java EE 服务器,而是一个准系统 servletcontainer,例如 Tomcat、Jetty 等),则使用 ScheduledExecutorService.这可以通过 ServletContextListener<启动/a>.这是一个启动示例:

@WebListener公共类 BackgroundJobManager 实现了 ServletContextListener {私有的 ScheduledExecutorService 调度器;@覆盖公共无效上下文初始化(ServletContextEvent 事件){调度程序 = 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);}@覆盖public void contextDestroyed(ServletContextEvent 事件){scheduler.shutdownNow();}}

工作类别如下所示:

public class SomeDailyJob 实现 Runnable {@覆盖公共无效运行(){//在这里做你的日常工作.}}

public class SomeHourlyJob 实现 Runnable {@覆盖公共无效运行(){//在这里做你的每小时工作.}}

public class SomeQuarterlyJob 实现 Runnable {@覆盖公共无效运行(){//在这里做你的季度工作.}}

public class SomeFiveSecondelyJob 实现 Runnable {@覆盖公共无效运行(){//在这里做你的季度工作.}}

永远不要考虑在基于 Java EE/Servlet 的环境中使用 java.util.Timer/java.lang.Thread

最后但并非最不重要的是,从不在 Java EE 中直接使用 java.util.Timer 和/或 java.lang.Thread.这是麻烦的秘诀.可以在关于同一问题的与 JSF 相关的答案中找到详细的解释:在 JSF 托管 bean 中为使用计时器的计划任务生成线程.

I'm using Java and I want to keep a servlet continuously running in my application, but I'm not getting how to do it. My servlet has a method which gives counts of the user from a database on a daily basis as well as the total count of the users from the whole database. So I want to keep the servlet continuously running for that.

解决方案

Your problem is that you misunderstand the purpose of the servlet. It's intented to act on HTTP requests, nothing more. You want just a background task which runs once on daily basis.

EJB available? Use @Schedule

If your environment happen to support EJB (i.e. a real Java EE server such as WildFly, JBoss, TomEE, Payara, GlassFish, etc), then use @Schedule instead. Here are some examples:

@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.
    }

} 

Yes, that's really all. The container will automatically pickup and manage it.

EJB unavailable? Use ScheduledExecutorService

If your environment doesn't support EJB (i.e. you're not using not a real Java EE server, but a barebones servletcontainer such as Tomcat, Jetty, etc), then use ScheduledExecutorService. This can be initiated by a ServletContextListener. Here's a kickoff example:

@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();
    }

}

Where the job classes look like this:

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.
    }

}

Do not ever think about using java.util.Timer/java.lang.Thread in a Java EE / Servlet based environment

Last but not least, never directly use java.util.Timer and/or java.lang.Thread in Java EE. This is recipe for trouble. An elaborate explanation can be found in this JSF-related answer on the same question: Spawning threads in a JSF managed bean for scheduled tasks using a timer.

这篇关于如何在基于 servlet 的 Web 应用程序中运行后台任务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆