Pytanie Jak uruchomić zadanie w tle w aplikacji internetowej opartej na serwletach?


Używam języka Java i chcę, aby serwlet ciągle działał w mojej aplikacji, ale nie wiem, jak to zrobić. Mój serwlet ma metodę, która codziennie podaje liczbę użytkowników z bazy danych, a także całkowitą liczbę użytkowników z całej bazy danych. Dlatego chcę, aby serwlet ciągle działał.


76
2018-01-14 12:39


pochodzenie


Co masz na myśli mówiąc "ciągle działa"? - skaffman
co masz na myśli przez ciągłe bieganie? Będzie działać tak długo, jak długo będzie działać serwer aplikacji - fmucar
Nie rozumiem, dlaczego ma działać nieprzerwanie ... jeśli ktoś chce "liczby użytkowników", to oni wywołują twoją metodę serwletu i dajesz im to? - trojanfoe
@trojanfoe Właściwie chcę codzienny licznik użytkowników, więc będę musiał ręcznie uruchamiać serwlet, więc zamiast wykonywać to, chcę uruchomić serwer contineously.so nie będę musiał codziennie uruchamiać serwletu. - pritsag
@pritsag Serwlety nie są sposobem na rozwiązanie tego problemu - jeśli chcesz "statystyki" zebrane w ciągu dnia, użyj innej technologii. - trojanfoe


Odpowiedzi:


Twoim problemem jest to, że źle rozumiesz cel serwlet. Ma zamiar działać na żądanie HTTP, nic więcej. Chcesz tylko zadanie w tle, które działa raz dziennie.

EJB jest dostępny? Posługiwać się @Schedule

Jeśli Twoje środowisko obsługuje EJB (np. WildFly, JBoss AS / EAP, TomEE, GlassFish, itp.), Użyj @Schedule zamiast.

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

} 

Tak, to naprawdę wszystko. Kontener automatycznie go odbiera i zarządza nim.

EJB jest niedostępny? Posługiwać się ScheduledExecutorService

Jeśli twoje środowisko nie obsługuje EJB (tj. Nie jest prawdziwym serwerem Java EE, np. Tomcat, Jetty itp.), Użyj ScheduledExecutorService. Może to zostać zainicjowane przez ServletContextListener. Oto przykład kickoff:

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

}

Gdzie klasy prac wyglądają tak:

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

}

Nigdy nie myśl o użyciu java.util.Timer/java.lang.Thread w Java EE

Nigdy nie używaj bezpośrednio java.util.Timer i / lub java.lang.Thread w Java EE. To przepis na kłopoty. Szczegółowe wyjaśnienie można znaleźć w tej odpowiedzi związanej z JSF na to samo pytanie: Rozgałęzienie wątków w komponencie bean zarządzanym JSF dla zaplanowanych zadań przy użyciu licznika czasu.


173
2018-01-14 13:45



@BalucS Dziękuję, proszę pana, twoje rozwiązanie pomogło mi i dowiedziałem się o usługach ScheduledExecutorService, które były dla mnie nowością, ponieważ jestem nowy w java. Jeszcze raz dziękuję. - pritsag
Doskonałe wyjaśnienie i kod. - London guy
@Ashwin web.xml jest Deskryptor wdrażania. Klasa UpdateCount nie jest związane z wdrażaniem, więc nie trzeba go umieszczać web.xml - informatik01
Jedna ważna kwestia związana z a ScheduledExecutorService: Upewnij się, że zdobyć wszystko wyjątki w twoim executorze. Jeśli wyjątek ucieknie z twojego run metoda, executor cicho przerywa wykonywanie. To jest funkcja, a nie błąd. Przeczytaj dokument i przestudiuj go, korzystając z usług Google. - Basil Bourque
@Agi: to się stanie, jeśli scheduler.shutdownNow() nie jest poprawnie wywoływany zgodnie z przykładem. Jeśli nie zostanie to wywołane, wątek z harmonogramem rzeczywiście będzie działał. - BalusC


Sugerowałbym użycie biblioteki takiej jak kwarc, aby uruchomić zadanie w regularnych odstępach czasu. Co naprawdę robi serwlet? Wysyła ci raport?


3
2018-01-14 13:08



tak, daje mi liczbę użytkowników utworzonych na dzień, a także liczbę użytkowników w mojej bazie danych. - pritsag
w jakiej formie? Poczta ? - Twister
huuu? Czy możesz opisać PEŁNĄ architekturę twojego systemu. Zgubiłem się. - Twister
@Twister I m nowy w Javie i fazie uczenia się i naprawdę nie wiem o serwletach. - pritsag
Problem nie dotyczy serwletu. O czym jest ta aplikacja, o której mówisz? (ps: to jest zły pomysł, aby usunąć twoje komentarze, w szczególności komentarze, na które odpowiedziałem) - Twister


Możesz użyć cron4j. http://www.sauronsoftware.it/projects/cron4j/manual.php


1
2017-12-22 08:13





Wprowadź dwie klasy i zadzwoń startTask() w 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



To zdecydowanie NIE jest sposób, aby to zrobić w aplikacji internetowej - spójrz na powyższą odpowiedź @BalusC - jest tutaj poprawny i powiedziałbym, że możesz zaufać wszystkim jego odpowiedziom. - Yoshiya


W systemie produkcyjnym, w którym może działać wiele kontenerów non-jee. Użyj programu anot enterprise scheduler, takiego jak scheduler kwarcowy, który można skonfigurować do korzystania z bazy danych dla zadania maamgememt.


0
2018-02-21 15:31