2016-04-06 17 views
14

Tôi có một tập tin cấu hình servers.conf trong thư mục conf/ được đọc bởi ServerController của tôi bất cứ khi nào tuyến đường /servers bị trúng. Điều này không thực hiện được vì nó yêu cầu đọc lại tệp cấu hình trên mỗi lần truy cập liên tiếp khi tệp sẽ không thay đổi. Hơn nữa nếu có vấn đề với tập tin cấu hình, tôi có thể nói cho người dùng càng sớm càng tốt hơn là ném một ngoại lệ lên một lần truy cập trang.Làm cách nào để thực hiện tác vụ khởi động máy chủ trong Khung công tác Scala Play?

Hiện nay tôi có điều này trong ServerController.scala tôi:

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

Mục tiêu của tôi là phải có máy chủ đọc các tập tin cấu hình lúc khởi động và thông qua danh sách các máy chủ để các ServerController khi tuyến đường được đánh nếu không có vấn đề đọc trong tập tin cấu hình. Nếu có vấn đề, tôi muốn một ngoại lệ được ném ngay lập tức.

Tôi dường như không thể tìm thấy điểm nhập cho ứng dụng của mình, vì vậy tôi không biết cách thực hiện các tác vụ khi khởi động.

Có ai biết cách thực hiện việc này không? Tôi đang sử dụng Play 2.5.x.

+0

Bạn đang sử dụng phiên bản Play nào? – Anton

+0

@Anton Xin lỗi. Đã chỉnh sửa câu hỏi. – erip

+0

Bạn đã cân nhắc đặt toàn bộ khối mã bên ngoài hàm chỉ mục chưa? (Nó thực thi khi Bộ điều khiển được khởi chạy chỉ một lần, tức là mọi yêu cầu HTTP được thực hiện cho bộ điều khiển đó) – dlite922

Trả lời

15

Nếu bạn đang sử dụng phiên bản Play mới nhất, nó sẽ khởi động cho bất kỳ lớp nào có tên là Module nằm trong gói gốc (nghĩa là không có định nghĩa package ở đầu tệp). Dưới đây là ví dụ lấy từ mẫu Activator mới nhất cho Play 2.5.x, mà tôi đã sửa đổi để trình diễn mã chạy khi khởi động và tắt ứng dụng:

Trong services/Say.scala, đây sẽ là một dịch vụ đơn giản để nói "Xin chào!" khi khởi nghiệp và "Tạm biệt!" khi ứng dụng tắt:

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

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

Một số nguồn lực hơn nữa bạn có thể thấy hữu ích là the Scala dependency injection (DI) documentationthe Guice documentation. Guice là khung DI mặc định được Play sử dụng.

+0

Tốt. Điều này có vẻ khá gần với những gì tôi muốn. Bạn có biết trong đó thư mục 'root' nên sống không? – erip

+1

Vâng, nó không phải là một thư mục có tên là 'root'. Nó chỉ là một tập tin nằm trong gói gốc, nghĩa là nó không có khai báo 'gói' ở trên cùng. Ngoài ra, bạn có thể định nghĩa mô-đun ở một nơi khác, nói trong thư mục 'modules' và kích hoạt nó trong' application.conf' của bạn như sau: 'play.modules.enabled + =" com.example.modules "', trong đó 'com.example.modules' phải là gói mà module của bạn thuộc về. – Eric

+0

Phải, vì vậy gói 'root' của tôi dự kiến ​​sẽ tồn tại trong' app/'theo mặc định? Tức là, nếu tôi đặt 'Say.scala' trong' service/'và' Module.scala' trong 'app /' được đóng gói thành 'root', nó sẽ hoạt động? – erip

Các vấn đề liên quan