Câu hỏi Làm thế nào để chạy một tác vụ nền trong một ứng dụng web dựa trên servlet?


Tôi đang sử dụng Java và tôi muốn giữ một servlet liên tục chạy trong ứng dụng của tôi, nhưng tôi không nhận được làm thế nào để làm điều đó. Servlet của tôi có một phương thức cho phép đếm số người dùng từ cơ sở dữ liệu hàng ngày cũng như tổng số người dùng từ toàn bộ cơ sở dữ liệu. Vì vậy, tôi muốn giữ cho servlet liên tục chạy cho điều đó.


76
2018-01-14 12:39


gốc


Ý bạn là gì, "liên tục chạy"? - skaffman
những gì bạn có nghĩa là bằng cách liên tục chạy? Nó sẽ chạy miễn là máy chủ ứng dụng của bạn chạy - fmucar
Tôi không hiểu tại sao nó phải chạy liên tục ... nếu ai đó muốn 'đếm người dùng' thì họ gọi phương thức servlet của bạn và bạn đưa nó cho họ? - trojanfoe
@trojanfoe Trên thực tế tôi muốn usercount trên cơ sở hàng ngày, vì vậy cho rằng tôi sẽ phải chạy servlet bằng tay hàng ngày để thay vì làm điều đó tôi muốn chạy servlet contineously.so tôi sẽ không cần chạy servlet mỗi ngày. - pritsag
@pritsag Servlets không phải là cách để giải quyết vấn đề này - nếu bạn muốn 'số liệu thống kê' được thu thập trong suốt cả ngày thì hãy sử dụng một số công nghệ khác. - trojanfoe


Các câu trả lời:


Vấn đề của bạn là bạn hiểu sai mục đích của servlet. Đó là ý định để hành động trên các yêu cầu HTTP, không có gì nhiều hơn nữa. Bạn chỉ muốn một nhiệm vụ nền chạy một lần trên cơ sở hàng ngày.

EJB có sẵn? Sử dụng @Schedule

Nếu môi trường của bạn xảy ra để hỗ trợ EJB (ví dụ: WildFly, JBoss AS / EAP, TomEE, GlassFish, v.v.), thì hãy sử dụng @Schedule thay thế.

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

} 

Vâng, đó thực sự là tất cả. Vùng chứa sẽ tự động đón và quản lý nó.

EJB không khả dụng? Sử dụng ScheduledExecutorService

Nếu môi trường của bạn không hỗ trợ EJB (nghĩa là không phải là máy chủ Java EE thực, ví dụ: Tomcat, Jetty, v.v.), hãy sử dụng ScheduledExecutorService. Điều này có thể được bắt đầu bởi một ServletContextListener. Đây là một ví dụ khởi đầu:

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

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        scheduler.shutdownNow();
    }

}

Nơi các lớp công việc trông như thế này:

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

}

Đừng bao giờ nghĩ đến việc sử dụng java.util.Timer/java.lang.Thread trong Java EE

Không bao giờ trực tiếp sử dụng java.util.Timer và / hoặc java.lang.Thread trong Java EE. Đây là công thức cho rắc rối. Một giải thích phức tạp có thể được tìm thấy trong câu trả lời liên quan đến JSF này trên cùng một câu hỏi: Tạo đề tài trong một bean được quản lý JSF cho các tác vụ được lên lịch sử dụng bộ hẹn giờ.


173
2018-01-14 13:45



@ BalucS Cảm ơn bạn sir, giải pháp của bạn đã giúp tôi và tôi đã học được về ScheduledExecutorService đó là mới với tôi như tôi m mới java.Thank bạn một lần nữa. - pritsag
Giải thích rõ ràng và mã. - London guy
@Ashwin web.xml là một Trình mô tả triển khai. Lớp UpdateCount không liên quan đến triển khai, vì vậy nó không phải được đưa vào web.xml - informatik01
Một vấn đề quan trọng với ScheduledExecutorService: Chắc chắn rằng chụp tất cả các ngoại lệ trong thi hành của bạn. Nếu một ngoại lệ thoát khỏi run phương pháp, người thực thi âm thầm ngừng thực hiện. Đây là một tính năng, không phải là một lỗi. Đọc tài liệu và nghiên cứu với một số googling. - Basil Bourque
@Agi: điều đó sẽ xảy ra nếu scheduler.shutdownNow() không được gọi đúng theo ví dụ. Nếu điều này không được gọi, thì chuỗi lịch trình sẽ thực sự tiếp tục chạy. - BalusC


Tôi sẽ đề nghị sử dụng một thư viện như thạch anh để chạy nhiệm vụ đều đặn. Servlet thực sự làm gì? Nó gửi cho bạn một báo cáo?


3
2018-01-14 13:08



có, nó mang lại cho tôi số lượng người dùng được tạo mỗi ngày và cũng là tổng số người dùng trong cơ sở dữ liệu của tôi. - pritsag
ở dạng nào? Thư ? - Twister
huuu? Bạn có thể mô tả cấu trúc ĐẦY ĐỦ của hệ thống của bạn không. Tôi bị lạc. - Twister
@ Twister i m mới cho java và trong giai đoạn học tập sir và thực sự không konw nhiều về servlets. - pritsag
Vấn đề không phải là về servlet. Ứng dụng của bạn đang nói về cái gì? (ps: nó là một ý tưởng tồi để xóa bình luận của bạn, đặc biệt là ý kiến ​​tôi trả lời) - Twister


Bạn có thể sử dụng cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php


1
2017-12-22 08:13





Triển khai hai lớp và gọi startTask() trong 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();
    }
}

1
2018-03-05 17:49



Điều này chắc chắn KHÔNG phải là cách để làm điều đó trong một ứng dụng web - nhìn vào câu trả lời ở trên bởi @BalusC để thay thế - anh ấy đúng ở đây và tôi sẽ nói bạn có thể tin tưởng tất cả các câu trả lời của anh ấy. - Yoshiya


Trong một hệ thống sản xuất có thể có nhiều thùng chứa không chạy jee. Sử dụng công cụ lập kế hoạch doanh nghiệp anot như lịch trình Quartz có thể được cấu hình để sử dụng cơ sở dữ liệu cho nhiệm vụ maamgememt.


0
2018-02-21 15:31