2016-04-06 12 views
14

मेरे पास conf/ निर्देशिका में एक कॉन्फ़िगरेशन फ़ाइल servers.conf है जो मेरे सर्वर नियंत्रक द्वारा पढ़ी जाती है जब भी रूट /servers मारा जाता है। यह निष्पादक नहीं है क्योंकि फ़ाइल को बदले जाने पर प्रत्येक क्रमिक हिट पर कॉन्फ़िगरेशन फ़ाइल को दोबारा पढ़ने की आवश्यकता होती है। अगर कॉन्फ़िगरेशन फ़ाइल में कोई समस्या है, तो मैं पेज हिट पर अपवाद फेंकने के बजाय उपयोगकर्ता ASAP को बता सकता हूं।मैं स्कैला प्ले फ्रेमवर्क में सर्वर स्टार्टअप पर एक क्रिया कैसे करूं?

वर्तमान में मैं अपने ServerController.scala में यह है:

case class Server(ip: String, port: String) 

/** 
    * This controller creates an `Action` to handle HTTP requests to the 
    * application's server page. 
    */ 
@Singleton 
class ServerController @Inject() extends Controller { 

    /** 
    * Create an Action to render an HTML page with a the list of servers. 
    * The configuration in the `routes` file means that this method 
    * will be called when the application receives a `GET` request with 
    * a path of `/servers`. 
    */ 
    def index = Action { 

    val serverList = ConfigFactory.load().getConfigList("servers") 
    val servers: List[Server] = serverList match { 
     case null => Nil 
     case _ => serverList map { s => 
     Server(s.getString("ip"), s.getString("port")) 
     } filter { s => 
     s.ip != null && s.port != null 
     }.toList 
    } 

    Ok(views.html.servers(servers)) 
    } 
} 

मेरा लक्ष्य सर्वर स्टार्टअप पर कॉन्फ़िग फ़ाइल पढ़ा है और जब मार्ग मारा जाता है ServerController को सर्वर की सूची पारित करने के लिए है अगर कोई हैं कॉन्फ़िगरेशन फ़ाइल में पढ़ने में समस्याएं। यदि समस्याएं हैं, तो मुझे तत्काल फेंकने का अपवाद चाहिए।

मुझे अपने आवेदन के लिए एक प्रविष्टि बिंदु नहीं मिल रहा है, हालांकि, मुझे नहीं पता कि स्टार्टअप पर कार्रवाई कैसे करें।

क्या कोई यह जानता है कि यह कैसे करें? मैं Play 2.5.x का उपयोग कर रहा हूँ।

+0

आप किस संस्करण का उपयोग कर रहे हैं? – Anton

+0

@ एंटोन क्षमा करें। सवाल संपादित किया। – erip

+0

क्या आपने इंडेक्स फ़ंक्शन के बाहर कोड के पूरे ब्लॉक को डालने पर विचार किया है? (यह तब निष्पादित होता है जब नियंत्रक केवल एक बार लॉन्च होता है, यानी उस नियंत्रक को किए गए किसी भी HTTP अनुरोध) – dlite922

उत्तर

15

यदि आप Play का नवीनतम संस्करण उपयोग कर रहे हैं, तो यह रूट पैकेज में Module नामक किसी भी वर्ग के लिए स्टार्टअप को देखता है (यानी, फ़ाइल के शीर्ष पर कोई package परिभाषा नहीं है)। Play 2.5.x के लिए नवीनतम एक्टिवेटर टेम्पलेट से लिया गया एक उदाहरण यहां दिया गया है, जिसे मैंने एप्लिकेशन स्टार्टअप और शट डाउन पर चलने वाले कोड के प्रदर्शन के लिए संशोधित किया है:

services/Say.scala में, यह "हैलो!" कहने के लिए एक सरल सेवा होगी। स्टार्टअप और "अलविदा!" पर जब आवेदन बंद हो जाता है:

package services 

import javax.inject._ 
import play.api.inject.ApplicationLifecycle 
import scala.concurrent.Future 

trait Say { 
    def hello(): Unit 
    def goodbye(): Unit 
} 

@Singleton 
class SayImpl @Inject() (appLifecycle: ApplicationLifecycle) extends Say { 
    override def hello(): Unit = println("Hello!") 
    override def goodbye(): Unit = println("Goodbye!") 

    // You can do this, or just explicitly call `hello()` at the end 
    def start(): Unit = hello() 

    // When the application starts, register a stop hook with the 
    // ApplicationLifecycle object. The code inside the stop hook will 
    // be run when the application stops. 
    appLifecycle.addStopHook {() => 
     goodbye() 
     Future.successful(()) 
    } 

    // Called when this singleton is constructed (could be replaced by `hello()`) 
    start() 
} 

Module.scala में,

import com.google.inject.AbstractModule 
import services._ 

/** 
* This class is a Guice module that tells Guice how to bind several 
* different types. This Guice module is created when the Play 
* application starts. 

* Play will automatically use any class called `Module` that is in 
* the root package. You can create modules in other locations by 
* adding `play.modules.enabled` settings to the `application.conf` 
* configuration file. 
*/ 
class Module extends AbstractModule { 

    override def configure() = { 
    // We bind the implementation to the interface (trait) as an eager singleton, 
    // which means it is bound immediately when the application starts. 
    bind(classOf[Say]).to(classOf[SayImpl]).asEagerSingleton() 
    } 
} 

कुछ आगे संसाधनों आप उपयोगी the Scala dependency injection (DI) documentation और the Guice documentation हैं मिल सकता है। Guice Play द्वारा उपयोग किया जाने वाला डिफ़ॉल्ट DI ढांचा है।

+0

अच्छा। ऐसा लगता है कि मैं जो चाहता हूं उसके करीब है। क्या आप जानते हैं कि किस निर्देशिका में 'root' रहना चाहिए? – erip

+1

अच्छा, यह 'root' नाम की निर्देशिका नहीं है। यह सिर्फ एक फ़ाइल है जो मूल पैकेज में रहती है, जिसका कहना है कि इसमें शीर्ष पर कोई 'पैकेज' घोषणा नहीं है। वैकल्पिक रूप से, आप मॉड्यूल को कहीं और परिभाषित कर सकते हैं, 'मॉड्यूल' निर्देशिका में कहें, और इसे अपने 'application.conf' में सक्षम करें: ' play.modules.enabled + = "com.example.modules" ', जहां 'com.example.modules' वह पैकेज होना चाहिए जिस पर आपका मॉड्यूल संबंधित है। – Eric

+0

ठीक है, तो मेरा 'रूट' पैकेज डिफ़ॉल्ट रूप से' ऐप/'में रहने की उम्मीद है? यही है, अगर मैं 'सेवा /' में 'Say.scala' डालता हूं और' root_cala ''root' के रूप में पैक 'ऐप /' में रहता है, तो इसे काम करना चाहिए? – erip

संबंधित मुद्दे