6

この回答の結果:https ://stackoverflow.com/a/10708026/694597 、汎用コントローラーを使用するときに特定のコントローラーに固有のビューを返す方法を考えています。

4

1 に答える 1

6

コントローラアクションでビューをレンダリングするときは、テンプレートエンジンによって生成されたプレーン関数を呼び出すだけです。

public Application extends Controller {
  public static Result index() {
    return ok(views.html.index.render(42));
  }
}

ここで、はタイプが。renderのオブジェクトのメソッドです。indexTemplate1<Integer, Html>

ここで問題となるのは、別のコントローラーに固有のビューを呼び出すことができる汎用コントローラーを作成する方法です。または単に:ビューを抽象化する方法は

制御の反転反射という2つの解決策があります。

単純なユースケースで両方を実装する方法を見てみましょう。Shower<T>タイプの任意の値のHTML表現を含むHTTP応答を計算できる次のジェネリッククラスがあるとしますT

public class Shower<T> {
  public Result show(T value) {
    // TODO return an HTML representation of `value`
  }
}

制御の反転

Shower<T>制御の反転を使用して実装Template1<T, Html>するには、レンダリングの実行に使用される値を挿入する必要があります。

public class Shower<T> {

  public final Template1<T, Html> template;

  public Shower(Template1<T, Html> template) {
    this.template = template;
  }

  public Result show(T value) {
    return ok(template.render(value));
  }

}

コントローラで使用するには、の静的インスタンスを作成し、Shower<T>使用するテンプレートを挿入します。

public class Application extends Controller {
  public static Shower<Foo> foo = new Shower<Foo>(views.html.Foo.show.ref());
}

反射

の各インスタンスに使用するテンプレートを明示的に挿入する必要があるのは定型的すぎるためShower<T>、命名規則に基づいて、たとえばタイプの値を表示するFooために、オブジェクトを探すだけで、リフレクションによってテンプレートを取得したくなる場合があります。showパッケージで名前が付けられていますviews.html.Foo

public class Shower<T> {

  private final Class<T> clazz;

  public Shower(Class<T> clazz) {
    this.clazz = clazz;
  }

  public Result show(T value) throws Exception {
    Class<?> object = Play.application().classLoader().loadClass("views.html." + clazz.getSimpleName() + ".show$");
    Template1<T, Html> template = (Template1<T, Html>)object.getField("MODULE$").get(null);
    return ok(template.render(value));
  }
}

(これが、リフレクションを使用してScalaオブジェクトにアクセスする方法です)

コントローラでは次のように使用できます。

public class Application extends Controller {
  public static Shower<Foo> foo = new Shower<Foo>(Foo.class);
}

長所と短所

リフレクションベースのソリューションは、コールサイトで必要な定型文が少なくて済みますが、命名規則に依存しているため、脆弱性が高くなります。さらに、このソリューションは実行時に失敗する場合にのみ失敗しますが、最初のソリューションはコンパイル時に不足しているテンプレートを表示します。大事なことを言い忘れましたが、リフレクションベースのソリューションは、リフレクションのためにパフォーマンスのオーバーヘッドを追加する可能性があります。

于 2012-05-24T18:06:07.603 に答える