![Lv.7 カスタムActionはサーブレットフィルターみたいなもの [play framework2.0] [java]](https://soylatte.jp/wp-content/themes/soy-magazine/assets/images/no-thumbnail.png)
アクションはメソッドだけど、クラスとして定義されたものをメソッドとして使っている、
というのが実際のところ。
※第一級関数(first class function)
関数をオブジェクトとして扱って、ほかの関数の引数として使ったり、データ構造に含めたりできる関数のことをこう呼ぶらしい。
関数をオブジェクトとして扱って、ほかの関数の引数として使ったり、データ構造に含めたりできる関数のことをこう呼ぶらしい。
第一級関数※がJavaでは定義できないのが理由らしいです。
play.mvc.ActionがルートActionとしてデフォルトで用意してあるので、こちらを継承して
独自Actionを定義することも可能です。
独自で用意するアクションは、意味合い的にはサーブレットフィルターが近い
かもしれないです。
(play.mvc.Actionのコード)
[java toolbar=”false”]
public abstract class Action<T> extends Results {
public T configuration;
public Action<?> delegate;
public abstract Result call(Context ctx)
throws Throwable;
public static abstract class Simple
extends Action<Void> {}
}[/java]
public abstract class Action<T> extends Results {
public T configuration;
public Action<?> delegate;
public abstract Result call(Context ctx)
throws Throwable;
public static abstract class Simple
extends Action<Void> {}
}[/java]
目次
Actionを作る!使う!
※ちなみにverboseとは、「くどい」「冗長な」という意味らしい。
まずはアクションを作る。
[java toolbar=”false”]
public class VerboseAction extends Action.Simple {
public Result call(Http.Context ctx) throws Throwable {
Logger.info(“Calling action for ” + ctx);
//こうすることで処理を引き継げる(委譲)
return delegate.call(ctx);
}
}[/java]
public class VerboseAction extends Action.Simple {
public Result call(Http.Context ctx) throws Throwable {
Logger.info(“Calling action for ” + ctx);
//こうすることで処理を引き継げる(委譲)
return delegate.call(ctx);
}
}[/java]
※ミックスして使える、と公式ドキュメントに書いてあるけど、コンパイル通らない。なにか前提条件があるのだろうか。
[java light=”true”]
@With(Authenticated.class, Cached.class)
public static Result index() {
return ok(“It works!”);
}[/java]
@With(Authenticated.class, Cached.class)
public static Result index() {
return ok(“It works!”);
}[/java]
使い方は、こう。
[java toolbar=”false”]
@With(VerboseAction.class)
public static Result index() {
return ok(“It works!”);
}[/java]
@With(VerboseAction.class)
public static Result index() {
return ok(“It works!”);
}[/java]
カスタムActionアノテーション
まずアノテーションの定義をする。
[java toolbar=”false”]
@With(VerboseAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Verbose {
boolean value() default true;
}[/java]
@With(VerboseAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Verbose {
boolean value() default true;
}[/java]
※Classに直接アノテーションを書くこともできる。
[java light=”true”]
@Authenticated
public Admin extends Controller {
…
}[/java]
@Authenticated
public Admin extends Controller {
…
}[/java]
次にControllerクラスでActionメソッドにアノテーションを適用する。※
[java toolbar=”false”]
@Verbose(false)
public static Result index() {
return ok(“It works!”);
}
[/java]
@Verbose(false)
public static Result index() {
return ok(“It works!”);
}
[/java]
そしてVerboseインターフェースをジェネリクスに指定したActionを継承した
Verboseアクションクラスを作る。
[java toolbar=”false”]
public class VerboseAction extends Action<Verbose> {
public Result call(Http.Context ctx) throws Throwable{
if(configuration.value()) {
// @Verbose(true)だとこっち。
Logger.info(“action kita! ” + ctx);
}else{
// @Verbose(false)だとこっち。
Logger.info(“no action “);
}
return delegate.call(ctx);
}
}[/java]
public class VerboseAction extends Action<Verbose> {
public Result call(Http.Context ctx) throws Throwable{
if(configuration.value()) {
// @Verbose(true)だとこっち。
Logger.info(“action kita! ” + ctx);
}else{
// @Verbose(false)だとこっち。
Logger.info(“no action “);
}
return delegate.call(ctx);
}
}[/java]
これで動きました。
アセスメント
- カスタムActionの作り方が分かる
- カスタムActionアノテーションの使い方が分かる
参照した公式ドキュメントは、Action compositionです。