ドキュメント

§Play 2.1の新機能

§Scala 2.10への移行

PlayのランタイムAPI全体がScala 2.10に移行され、アプリケーションはこの新しい言語リリースで提供される優れた新機能を利用できるようになりました。

同時に、*ビルドシステム*(sbt)で使用されるScalaバージョンと、ランタイムで使用されるScalaバージョンの間の依存関係を解消しました。 これにより、Scala言語の実験的または不安定なブランチでPlayをビルドおよびテストすることが容易になります。

§scala.concurrent.Futureへの移行

Scala 2.10で提供される最も優れた機能の1つは、Scalaで非同期コードを管理するための新しい標準scala.concurrent.Futureライブラリです。 PlayはこのAPIに基づいており、その優れた非同期HTTPおよびストリーミング機能は、同じAPIを使用する他のライブラリと直接互換性があります.

Akka、またはこの新しいAPIを使用する今後の非同期データストアドライバーでPlayを使用することがさらに簡単になります。

同時に、実行コンテキストモデルを簡素化し、アプリケーションの各部分でコードを実行するために使用される基盤となるExecutionContextを簡単に選択できるようにしました。

§モジュール化

Playプロジェクトは多くのサブプロジェクトに分割されているため、プロジェクトに必要な最小限の依存関係のセットを選択できます。

アプリケーションに必要なオプションの依存関係の正確なセットを、以下のリストから選択する必要があります。

playコ プロジェクトは、外部の依存関係が非常に限られており、他のコンポーネントなしで最小限の非同期高性能 HTTP サーバーとして使用できます。

§プロジェクトのモジュール化を促進

Play 2.1 は、独自のプロジェクトでコンポーネントをさらに構成して再利用できるように、サブルーターの構成をサポートしています。

たとえば、サブプロジェクトは、次のように独自のネームスペースを使用して、独自のルーターコンポーネントを定義できます。

conf/my.subproject.routes

GET   /                   my.subproject.controllers.Application.index

次に、次のようにルーターを配線することで、このコンポーネントをメインアプリケーションに統合できます。

# The home page
GET   /                   controllers.Application.index

# Include a sub-project
->    /my-subproject      my.subproject.Routes

# The static assets
GET   /public/*file       controllers.Assets.at(file)

設定では、実行時に/my-subproject URLへの呼び出しは最終的にmy.subproject.controllers.Application.indexアクションを呼び出します。

注:メインアプリケーションとの名前の衝突の問題を回避するために、サブプロジェクトに属するコントローラー クラス内に常にサブパッケージを定義してください(この特定の例ではmy.subproject)。また、サブプロジェクトのアセットコントローラーが同じ名前空間に定義されていることを確認する必要があります。

この機能の詳細については、サブプロジェクトでの作業を参照してください。

§Java API での Http.Context の伝播

Play 2.0 では、非同期コールバック中に HTTP コンテキストが失われました。これは、これらのコードフラグメントが HTTP リクエストを処理する元の スレッドとは異なるスレッドで実行されるためです。

以下を検討してください。

public static Result index() {
  return async(
    aServiceSomewhere.getData().map(new Function<String,Result>(data) {
      // Ouch! You try to access the request data in an asynchronous callback
      String user = session().get("user"); 
      return ok("Here is the result " + user + ": " + data);
    })
  );
}

このコードはこのようには機能していませんでした。基盤となる非同期アーキテクチャについて考えると、正当な理由がありますが、それでも Java 開発者にとっては非常に驚くべきことでした。

最終的にこの問題を解決し、複数のスレッドにまたがるスタックにわたって Http.Context を伝播する方法を見つけました。そのため、このコードは現在この方法で機能しています。

§Java API のためのより良いスレッディングモデル

可変データ構造上で非同期コードを実行している間、コードを適切に同期しないと競合状態が発生する可能性が高くなります。 Play は高度な非同期およびノンブロッキングコードを推奨しており、Java データ構造はほとんどが可変でスレッドセーフではないため、同期の問題に対処するのはコードの責任です。

以下を検討してください。

public static Result index() {

  final HashMap<String,Integer> result = new HashMap<String,Integer>();

  aService.doSomethingAsync().map(new Function<String,String>(key) {
    Integer i = result.get(key);
    if(i != null) {
      result.set(key, i++);
    }
    return key;
  });

  aService.doSomethingElse().map(new Function<String,String>(key) {
    result.remove(key);
    return null;
  });

  ...
}

このコードでは、2 つコールバックが共有 result HashMap にアクセスしている間に、2 つの異なるスレッドで同時に実行された場合、競合状態が発生する可能性が非常に高くなります。そして、その結果、基盤となる Java HashMap の実装のために、アプリケーションに疑似デッドロックが発生する可能性があります。

これらの問題を回避するために、フレームワークレベルでコールバック実行の同期を管理することにしました。 Play 2.1 は、同じ Http.Context に対して 2 つのコールバックを同時に実行することはありません。このコンテキストでは、すべてのコールバック実行は順番に実行されます(同じスレッドで実行されるという保証はありません)。

§管理されたコントローラー クラスのインスタンス化

デフォルトでは、Play は URL をコントローラーメソッドに静的にバインドします。つまり、フレームワークによってコントローラーインスタンスは作成されず、指定された URL に応じて適切な静的メソッドが呼び出されます。ただし、特定の状況では、コントローラーの作成を管理したい場合があります。その場合に、新しいルーティング構文が役立ちます。

@ で始まるルート定義は、Global::getControllerInstance メソッドによって管理されます。そのため、次のルート定義が与えられます。

GET     /                  @controllers.Application.index()

Play は getControllerInstance メソッドを呼び出し、そのメソッドは controllers.Application のインスタンスを返します(デフォルトでは、これはデフォルトコンストラクターを介して行われます)。したがって、依存性注入フレームワークまたは手動でコントローラークラスのインスタンス化を管理する場合は、アプリケーションの Global クラスで getControllerInstance をオーバーライドすることで実行できます。

この例が示すようにSpring などの依存性注入フレームワークを Play アプリケーションに接続できます。

§新しい Scala JSON API

新しい Scala JSON API は、JSON ツリーの変換や検証などの優れた機能を提供します。 Scala Json コンビネータードキュメントで新しいドキュメントを確認してください。

§新しいフィルター API と CSRF 保護

Play 2.1 は、HTTP リクエストまたはレスポンスの各部分を完全にノンブロッキングな方法でインターセプトできる、新しく非常に強力なフィルター API を提供します。

そのため、古い Action[A] タイプに代わる、EssentialAction と呼ばれる新しいより単純なタイプを導入しました。これは次のように定義されます。

RequestHeader => Iteratee[Array[Byte], Result]

その結果、フィルターは次のように定義されます。

EssentialAction => EssentialAction

: 古い Action[A] タイプは、互換性のために引き続き使用できます。

標準 Play ディストリビューションの一部である filters プロジェクトには、CSRF セキュリティ問題に対する自動トークン管理を提供する CSRF など、標準フィルターのセットが含まれています。

§RequireJS

play 2.0 では、Javascript のデフォルトの動作は、Google Closure の commonJS モジュールサポートを使用することでした。 2.1 では、代わりに requireJS を使用するように変更されました。

これは実際には、Play がステージ、dist、start モードでのみファイルを縮小して結合することを意味します。 dev モードでは、Play はクライアント側で依存関係を解決します。

この機能を使用する場合は、ビルドファイルの設定ブロックにモジュールを追加する必要があります

requireJs := "main.js"

この機能の詳細については、RequireJS ドキュメントページを参照してください。

§コンテンツネゴシエーション

コンテンツネゴシエーションのサポートが改善されました。たとえば、コントローラーは Accept-Language リクエストヘッダー値に設定されている品質値に従って、最も適切な言語を自動的に選択するようになりました。

同じリソースの複数の表現をサポートし、Accept リクエストヘッダー値に従って最適なものを自動的に選択する Web サービスを記述することも容易になりました。

val list = Action { implicit request =>
  val items = Item.findAll
  render {
    case Accepts.Html() => Ok(views.html.list(items))
    case Accepts.Json() => Ok(Json.toJson(items))
  }
}

詳細については、Scala および Java のコンテンツネゴシエーションのドキュメントページを参照してください。

次: 移行ガイド


このドキュメントに誤りを見つけましたか?このページのソースコードはこちらにあります。ドキュメントガイドラインを読んだ後、プルリクエストを送信してください。質問やアドバイスがあれば、コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。