Documentation

§サブプロジェクト

複雑なプロジェクトを、ひとつの Play アプリケーションにまとめる必要はありません。大きなプロジェクトを小さないくつかのアプリケーションに分割したり、Play アプリケーションと関係のないロジックは標準的な Java や Scala のライブラリを抽出したくなることがあるでしょう。

マルチプロジェクト・ビルドについての SBT ドキュメント を読むといいでしょう。サブプロジェクトは独自のビルドファイルを持たず、親プロジェクトのビルドファイルを共有します。

§ライブラリをサブプロジェクトとして切り出す

アプリケーションをシンプルなライブラリプロジェクトに依存させることができます。build.sbt に、次のような sbt のプロジェクト定義を追加してください:

name := "my-first-application"

version := "1.0"

lazy val myFirstApplication = (project in file("."))
    .enablePlugins(PlayScala)
    .aggregate(myLibrary)
    .dependsOn(myLibrary)

lazy val myLibrary = project

最終行の小文字の project は、代入先の val の名前を使ってプロジェクトの名前とフォルダを決定する Scala マクロです。

この myFirstApplication は、ベースプロジェクトを宣言します。サブプロジェクトを持たない場合は特に設定する必要はありませんが、サブプロジェクトを持つ場合は宣言する必要があり、これによりベースプロジェクトがサブプロジェクトを集約 (つまり、ベースプロジェクトを実行すると、サブプロジェクトがコンパイル/テストされます) し、またサブプロジェクトに依存 (つまり、サブプロジェクトをベースプロジェクトのクラスパスに追加します) することを確認できます。

上記の例では myLibrary ディレクトリにサブプロジェクトを定義しました。サブプロジェクトは普通の sbt プロジェクトの一種であり、標準的なディレクトリ構成に従います:

myProject
 └ build.sbt
 └ app
 └ conf
 └ public
 └ myLibrary
   └ build.sbt
   └ src
     └ main
       └ java
       └ scala

myLibrary にも、独自の設定や依存性などを宣言する、専用の build.sbt ファイルがあります。

ビルド設定でサブプロジェクトを有効にした場合、それぞれのプロジェクトを個別にコンパイル、テスト、実行することができます。Play コンソールで projects コマンドを実行すると、全てのプロジェクトが表示されます:

[my-first-application] $ projects
[info] In file:/Volumes/Data/gbo/myFirstApp/
[info] 	 * my-first-application
[info] 	   my-library

デフォルトのプロジェクトは変数名がアルファベット順で最初の物になります。メインプロジェクトを指定したい場合は変数名を aaaMain 等にする事で可能になります。現在のプロジェクトを切り替えるには、project コマンドを使ってください:

[my-first-application] $ project my-library
[info] Set current project to my-library
>

Play アプリケーションを開発モードで起動している場合、依存するサブプロジェクトも自動的に再コンパイルされます。サブプロジェクトのコンパイルエラーも、ブラウザ上で確認できます:

§共通変数とコードの共有

ルートプロジェクトとサブプロジェクトで共通の設定やコードを共有したい場合は、ルートプロジェクトの project 内の Scala ファイルに配置することができます。例えば、次のような project/Common.scala があるとします:

import sbt._
import Keys._

object Common {
  val settings: Seq[Setting[_]] = Seq(
    organization := "com.example",
    version := "1.2.3-SNAPSHOT"
  )

  val fooDependency = "com.foo" %% "foo" % "2.4"
}

こうすることで、すべての build.sbt から、このファイルに定義されたあらゆるものを参照できるようになります:

name := "my-sub-module"

Common.settings

libraryDependencies += Common.fooDependency

§Webアプリケーションを複数のプロジェクトに分割する

Play アプリケーションの実体は、デフォルトの設定を持った標準的な sbt プロジェクトなので、他の Play アプリケーションに依存することができます。対応する build.sbt ファイルに、プロジェクトが Java または Scala いずれのプロジェクトであるかに応じて PlayJava もしくは PlayScala プラグインを追加することで、あらゆるサブモジュールを Play アプリケーションにすることができます。

注意: 名前の衝突を避けるために、サブプロジェクト内の Assets コントローラを含むコントローラが、メインプロジェクトとは異なる名前空間を使っていることを確認してください。

§ルートファイルを分割する

route ファイルを、より小さなファイルに分割することもできます。この機能は、堅牢で、再利用性の高いマルチモジュール Play アプリケーションを作るときにとても便利です。

§以下のビルド設定を検討してみましょう

build.sbt:

name := "myproject"

lazy val admin = (project in file("modules/admin")).enablePlugins(PlayScala)

lazy val main = (project in file("."))
    .enablePlugins(PlayScala).dependsOn(admin).aggregate(admin)

modules/admin/build.sbt

name := "myadmin"

libraryDependencies ++= Seq(
  "mysql" % "mysql-connector-java" % "5.1.35",
  jdbc,
  anorm
)

§プロジェクト構成

build.sbt
app
  └ controllers
  └ models
  └ views
conf
  └ application.conf
  └ routes
modules
  └ admin
    └ build.sbt
    └ conf
      └ admin.routes
    └ app
      └ controllers
      └ models
      └ views
project
  └ build.properties
  └ plugins.sbt

注意: 設定ファイルおよび route ファイルの名前はプロジェクト構成全体でユニークでなければならず、application.conf ファイルと routes ファイルはそれぞれひとつだけです。サブプロジェクトに routes または設定ファイルを定義する場合は、サブプロジェクトに特化した名前を使います。例えば、admin 中の route ファイルは admin.route と呼ばれます。開発モードのサブプロジェクトにおいて特別な設定セットを使う際、例えば PlayKeys.devSettings += ("play.http.router", "admin.Routes").のように、その設定セットをビルドファイルに書くとなお良いでしょう。

conf/routes:

GET /index                  controllers.Application.index()

->  /admin admin.Routes

GET     /assets/*file       controllers.Assets.at(path="/public", file)

modules/admin/conf/admin.routes:

GET /index                  controllers.admin.Application.index()

GET /assets/*file           controllers.admin.Assets.at(path="/public/lib/myadmin", file)

注意: リソースは単一のクラスローダから提供されるので、リソースパスはルートプロジェクトのクラスパスから見た相対パスでなければなりません。
サブプロジェクトのリソースは target/web/public/main/lib/{module-name} に生成されるので、Assets.at メソッドが行っているように play.api.Application#resources(uri) を使った場合、そのリソースには /public/lib/{module-name} でアクセスできるようになります。

§アセットとコントローラクラスは controllers.admin パッケージ以下に無ければなりません

modules/admin/controllers/Assets.scala:

package controllers.admin
import play.api.http.LazyHttpErrorHandler
object Assets extends controllers.AssetsBuilder(LazyHttpErrorHandler)

Java のユーザは、以下のようにして同様のことを実現できます:

// Assets.java
package controllers.admin;
import play.api.mvc.*;

public class Assets {
  public static Action<AnyContent> at(String path, String file) {
    return controllers.Assets.at(path, file);
  }
}

コントローラも同様です:

modules/admin/controllers/Application.scala:

package controllers.admin

import play.api._
import play.api.mvc._
import views.html._

object Application extends Controller {

  def index = Action { implicit request =>
    Ok("admin")
  }
}

§admin でのリバースルーティング

通常のコントローラの場合は以下のように呼び出します:

controllers.admin.routes.Application.index

Assets の場合は以下のようにします:

controllers.admin.routes.Assets.at("...")

§ブラウザ経由の場合

http://localhost:9000/index

上記 URL は、以下を呼び出します。

controllers.Application.index

また

http://localhost:9000/admin/index

上記 URL は、以下を呼び出します。

controllers.admin.Application.index

Next: Play エンハンサ


このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。