Documentation

§アクションの合成

この章では汎用的なアクションを定義するための方法をいくつか紹介します。

§アクションのおさらい

前のページで、アクションとは play.mvc.Result 値を返す Java のメソッドだということを説明しました。より正確には、Play はアクションを内部的には関数として管理しています。しかし、Java は第一級オブジェクトとしての関数をサポートしていないため、Java API では play.mvc.Action のインスタンスでアクションを定義します :

public abstract class Action {
  public abstract Promise<Result> call(Context ctx) throws Throwable;
}

Play は、適切なアクションメソッドを呼び出すルートアクションを生成します。これにより、もっと込み入ったアクションの合成を行うことができます。

§アクションを組み合わせる

VerboseAction の定義は以下の通りです。

public class VerboseAction extends play.mvc.Action.Simple {
    public F.Promise<Result> call(Http.Context ctx) throws Throwable {
        Logger.info("Calling action for " + ctx);
        return delegate.call(ctx);
    }
}

@With アノテーションを利用すると、あるアクションメソッドのコードを他の play.mvc.Action と組み合わせることができます。

@With(VerboseAction.class)
public Result verboseIndex() {
    return ok("It works!");
}

どこかのタイミングで delegate.call(...) を呼び出して、ラップされているアクションに処理を委譲する必要があることに注意してください。

カスタムアクションアノテーションを使って複数のアクションを合成することもできます:

@Security.Authenticated
@Cached(key = "index.result")
public Result authenticatedCachedIndex() {
    return ok("It works!");
}

注意: play.mvc.Security.Authenticatedplay.cache.Cached アノテーションやそれに対応するアクションは Play に同梱されています。詳しくは、関連する API ドキュメントを参照してください。

注意: すべてのリクエストは、play.mvc.Action の個別のインスタンスによって扱われなければなりません。シングルトンパターンが使われていると、複数のリクエスト間におけるシナリオにおいて、リクエストは正しくルーティングされません。例えば Play の DI コンテナに Spring を使っている場合、アクションのビーンが prototype スコープであることを確認する必要があります。

§独自のアクションアノテーションを定義する

アクションの合成を独自のアノテーションで行えるようにマークすることもできます。そのためには、アノテーション自身に @With アノテーションを付与してください。

@With(VerboseAnnotationAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface VerboseAnnotation {
    boolean value() default true;
}

Action 側ではアノテーションを configuration として受け取ることができます。

public class VerboseAnnotationAction extends Action<VerboseAnnotation> {
    public F.Promise<Result> call(Http.Context ctx) throws Throwable {
        if (configuration.value()) {
            Logger.info("Calling action for " + ctx);
        }
        return delegate.call(ctx);
    }
}

この新しいアノテーションをアクションメソッドで利用するには、以下のようにします。

@VerboseAnnotation(false)
public Result verboseAnnotationIndex() {
    return ok("It works!");
}

§コントローラにアノテーションを付与する

アクションを合成するアノテーションは何でも Controller クラスに直接付与することができます。その場合、アノテーションはコントローラ内に定義された全てのアクションメソッドに適用されます。

@Authenticated
public class Admin extends Controller {
    
  …
    
}

注意: Controller クラスに付与した アクションを合成するアノテーションを、アクションメソッドよりも先に実行したい場合は、application.conf 内で play.http.actionComposition.controllerAnnotationsFirst = true を設定します。ただし、サードパーティのモジュールを使っている場合、アノテーションの実行順序に依存しているかもしれないことに気をつけて下さい。

§アクションからコントローラへオブジェクトを引き渡す

コンテキスト引数マップを使ってアクションからコントローラへオブジェクトを引き渡すことができます。

public class PassArgAction extends play.mvc.Action.Simple {
    public F.Promise<Result> call(Http.Context ctx) throws Throwable {
        ctx.args.put("user", User.findById(1234));
        return delegate.call(ctx);
    }
}

その後、以下のようにこの引数をアクション内で取得することができます:

@With(PassArgAction.class)
public static Result passArgIndex() {
    Object user = ctx().args.get("user");
    return ok(Json.toJson(user));
}

Next: コンテントネゴシエーション


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