§アクションの合成
この章では汎用的なアクションを定義するための方法をいくつか紹介します。
§アクションのおさらい
前のページで、アクションとは play.mvc.Result
値を返す Java のメソッドだということを説明しました。より正確には、Play はアクションを内部的には関数として管理しています。しかし、Java は第一級オブジェクトとしての関数をサポートしていないため、Java API では play.mvc.Action
のインスタンスでアクションを定義します。
public abstract class Action {
public abstract Result call(Http.Context ctx);
}
Play は、適切なアクションメソッドを呼び出すルートアクションを生成します。これにより、もっと込み入ったアクションの合成を行うことができます。
§アクションを組み合わせる
@With
アノテーションを利用すると、あるアクションメソッドのコードを他の play.mvc.Action
と組み合わせることができます。
@With(VerboseAction.class)
public static Result index() {
return ok("It works!");
}
VerboseAction
の定義は以下の通りです。
public class VerboseAction extends Action.Simple {
public Result call(Http.Context ctx) throws Throwable {
Logger.info("Calling action for " + ctx);
return delegate.call(ctx);
}
}
どこかのタイミングで delegate.call(...)
を呼び出して、ラップされているアクションに処理を委譲する必要があることに注意してください。
カスタムアクションアノテーションを使って複数のアクションを合成することもできます:
@Authenticated
@Cached(key="index.result")
public static Result index() {
return ok("It works!");
}
ノート:
play.mvc.Security.Authenticated
とplay.cache.Cached
アノテーションやそれに対応するアクションは Play に同梱されています。詳しくは、関連する API ドキュメントを参照してください。
§独自のアクションアノテーションを定義する
アクションの合成を独自のアノテーションで行えるようにマークすることもできます。そのためには、アノテーション自身に @With
アノテーションを付与してください。
@With(VerboseAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Verbose {
boolean value() default true;
}
この新しいアノテーションをアクションメソッドで利用するには、以下のようにします。
@Verbose(false)
public static Result index() {
return ok("It works!");
}
Action
側ではアノテーションを configuration
として受け取ることができます。
public class VerboseAction extends Action<Verbose> {
public Result call(Http.Context ctx) {
if(configuration.value) {
Logger.info("Calling action for " + ctx);
}
return delegate.call(ctx);
}
}
§コントローラにアノテーションを付与する
アクションを合成するアノテーションは何でも Controller
クラスに直接付与することができます。その場合、アノテーションはコントローラ内に定義された全てのアクションメソッドに適用されます。
@Authenticated
public Admin extends Controller {
…
}
§アクションからコントローラへオブジェクトを引き渡す
コンテキスト引数マップを使ってアクションからコントローラへオブジェクトを引き渡すことができます。
public class SecurityAction extends Action<Verbose> {
public Result call(Http.Context ctx) {
ctx.args.put("user", User.findById(1234));
}
}
次ページ: コンテントネゴシエーション