सर्वलेट आधारित वेब एप्लिकेशन में पृष्ठभूमि कार्य कैसे चलाएं?


97

मैं जावा का उपयोग कर रहा हूं और मैं अपने आवेदन में लगातार एक सर्वलेट रखना चाहता हूं, लेकिन मुझे यह नहीं मिल रहा है कि यह कैसे करना है। मेरे सर्वलेट में एक विधि है जो एक डेटाबेस से उपयोगकर्ता की गणना दैनिक आधार पर करती है और साथ ही पूरे डेटाबेस से उपयोगकर्ताओं की कुल गणना भी करती है। इसलिए मैं सर्वलेट को उसके लिए लगातार चालू रखना चाहता हूं।


आपका क्या मतलब है, "लगातार चल रहा है"?
स्कफमैन

1
लगातार चलने से आपका क्या मतलब है? यह तब तक चलेगा जब तक आपका ऐप सर्वर चलता है
fmucar

2
मुझे समझ नहीं आता कि इसे लगातार क्यों चलाना पड़ता है ... अगर कोई 'यूजर काउंट' चाहता है तो वे आपके सर्वलेट मेथड को कॉल करते हैं और आप उन्हें देते हैं?
ट्रोजनफॉई

@trojanfoe वास्तव में मैं दैनिक आधार पर उपयोगकर्ता चाहता हूं, इसलिए इसके लिए मुझे हर रोज मैन्युअल रूप से सर्वलेट को चलाना होगा, ऐसा करने के बजाय मैं सर्वलेट को आकस्मिक रूप से चलाना चाहता हूं। इसलिए मुझे हर रोज सर्वलेट चलाने की आवश्यकता नहीं है।
प्रिटैग

1
@pritsag: एक सर्वलेट उपयोगकर्ता अनुरोधों की सेवा करने के लिए है, बैच की नौकरियों को चलाने के लिए नहीं।
स्कफमैन

जवाबों:


217

आपकी समस्या यह है कि आप सर्वलेट के उद्देश्य को गलत समझते हैं । यह HTTP अनुरोधों पर कार्रवाई करने का इरादा है, इससे ज्यादा कुछ नहीं। आप केवल एक पृष्ठभूमि कार्य चाहते हैं जो दैनिक आधार पर एक बार चलता है।

ईजेबी उपलब्ध है? उपयोग@Schedule

यदि आपका वातावरण EJB (जैसे कि WildFly, JBoss, TomEE, Payara, GlassFish, इत्यादि जैसे वास्तविक जावा 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.
    }

} 

हाँ, यह वास्तव में है। कंटेनर स्वचालित रूप से पिकअप और इसे प्रबंधित करेगा।

ईजेबी अनुपलब्ध? उपयोगScheduledExecutorService

यदि आपका वातावरण EJB का समर्थन नहीं करता है (अर्थात आप एक वास्तविक जावा ईई सर्वर का उपयोग नहीं कर रहे हैं, लेकिन एक टॉम्बैट, जेट्टी, इत्यादि जैसे नंगे कोने सर्वलेटकेंटर), तो उपयोग करें 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.
    }

}

जावा EE / सर्वलेट आधारित वातावरण में java.util.Timer/ का उपयोग करने के बारे में कभी मत सोचोjava.lang.Thread

अंतिम लेकिन कम से कम, जावा ईई में कभी भी सीधे उपयोग java.util.Timerऔर / या नहीं java.lang.Thread। यह परेशानी का नुस्खा है। इसी सवाल पर जेएसएफ से संबंधित जवाब में एक विस्तृत विवरण पाया जा सकता है: एक जेएसएफ में स्प्रेडिंग थ्रेड्स टाइमर का उपयोग करके अनुसूचित कार्यों के लिए प्रबंधित बीन


9
@BalucS धन्यवाद सर, आपके समाधान से मुझे मदद मिली और मैंने शेड्यूल्ड एक्ज़ीक्यूटर सर्विस के बारे में सीखा जो मेरे लिए नया था java के लिए नया था। फिर से धन्यवाद।
प्रातः

@ बाल्स्क: वेब.एक्सएमएल में क्लास अपडेटकंट्स को कहां रखा जाना चाहिए?
अश्विन

1
@Ashwin web.xml एक परिनियोजन वर्णक है । वर्ग UpdateCount तैनाती के साथ संबंधित नहीं है, तो यह में रखा जाना करने के लिए नहीं है web.xml
informatik01

12
एक के साथ एक महत्वपूर्ण मुद्दा ScheduledExecutorService: अपने निष्पादक में सभी अपवादों को पकड़ना सुनिश्चित करें । यदि कोई अपवाद आपकी runविधि से बच जाता है , तो निष्पादक चुपचाप निष्पादित करना बंद कर देता है। यह एक बग नहीं एक सुविधा है। डॉक्टर पढ़ें और कुछ गुगली के साथ अध्ययन करें।
बेसिल बोर्क

1
@ एगी: ऐसा होगा यदि scheduler.shutdownNow()उदाहरण के अनुसार सही ढंग से लागू नहीं किया गया है। यदि इसे लागू नहीं किया जाता है, तो शेड्यूल थ्रेड वास्तव में चालू रहेगा।
BalusC

4

मैं नियमित अंतराल पर कार्य चलाने के लिए क्वार्ट्ज जैसी लाइब्रेरी का उपयोग करने का सुझाव दूंगा। सर्वलेट वास्तव में क्या करता है? यह आपको एक रिपोर्ट भेजता है?


हां, यह मुझे प्रति दिन बनाए गए उपयोगकर्ता की गिनती और मेरे डेटाबेस में कुल उपयोगकर्ताओं की गिनती देता है।
प्रिटैग

1
huuu? क्या आप अपने सिस्टम की पूर्ण वास्तुकला का वर्णन कर सकते हैं। मैं हार गया हूं।
ट्विस्टर

@ Twister im जावा में और सीखने के चरण में श्रीमान और वास्तव में सर्वलेट्स के बारे में ज्यादा नहीं जानते।
प्रातः

समस्या सर्वलेट के बारे में नहीं है। जिस एप्लिकेशन के बारे में आप बात कर रहे हैं, वह क्या है? (पीएस: यह आपकी टिप्पणियों को हटाने के लिए एक बुरा विचार है, विशेष रूप से टिप्पणियों का मैंने जवाब दिया)
ट्विस्टर

@Wister जब उपयोगकर्ता एप्लिकेशन को हिट करेगा, तो उसे सभी विवरण मिल जाएंगे जैसे कि आज उपयोगकर्ता कितने सृजित हैं, अब तक कितने उपयोगकर्ताओं को तरस गए हैं और आदि मैं सर्वलेट रन को पृष्ठभूमि में चलाना चाहता हूं ताकि उपयोगकर्ता को अपडेट मिल सके । मैं जानता हूं कि यह उचित अन्वेषण नहीं है। (ps: मुझे पता है कि यह एक बुरा विचार था। उस के लिए बहुत अच्छा।)
प्रिटैग

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

3
यह निश्चित रूप से वेब एप्लिकेशन में ऐसा करने का तरीका नहीं है - इसके बजाय @BalusC द्वारा दिए गए उत्तर को देखें - वह यहां सही है और मैं कहूंगा कि आप उसके सभी उत्तरों पर भरोसा कर सकते हैं।
योशिय्या


0

एक उत्पादन प्रणाली में कई गैर-जी कंटेनर चल सकते हैं। क्वार्ट्ज शेड्यूलर की तरह एनॉट एंटरप्राइज शेड्यूलर का उपयोग करें जिसे टास्क मैमगेमट के लिए डेटाबेस का उपयोग करने के लिए कॉन्फ़िगर किया जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.