web-dev-qa-db-ja.com

Playフレームワークでオプションのクエリパラメーターを処理する方法

Scala=のような、機能しているPlay 2.0フレームワークベースのアプリケーションが既にあるとしましょう。

http:// localhost:9000/birthdays

すべての既知の誕生日のリストで応答します

オプションの「from」(日付)および「to」リクエストパラメータなどの結果を制限する機能を追加することで、これを強化したい

http:// localhost:9000/birthdays?from = 20120131&to = 20120229

(ここでの日付はyyyyMMddと解釈されます)

私の質問は、Scalaを使用したPlay 2.0でリクエストパラメーターのバインドと解釈を処理する方法です。特に、これらのパラメーターの両方をオプションにする必要がある場合です。

これらのパラメータは、「ルート」仕様で何らかの形で表現する必要がありますか?あるいは、応答するControllerメソッドは、何らかの方法でリクエストオブジェクトからパラメーターを選択する必要がありますか?これを行う別の方法はありますか?

67
magicduncan

オプションのパラメーターをOption[String](またはOption[Java.util.Date]としてエンコードしますが、独自のQueryStringBindable[Date]を実装する必要があります):

def birthdays(from: Option[String], to: Option[String]) = Action {
  // …
}

そして、次のルートを宣言します。

GET   /birthday       controllers.Application.birthday(from: Option[String], to: Option[String])
60

Javaユーザーに対してこれを行うよりクリーンでない方法は、デフォルトを設定しています:

GET  /users  controllers.Application.users(max:Java.lang.Integer ?= 50, page:Java.lang.Integer ?= 0)

そしてコントローラーで

public static Result users(Integer max, Integer page) {...}

もう1つの問題は、テンプレート内のページにリンクするたびにデフォルトを繰り返す必要があることです。

@routes.Application.users(max = 50, page = 0)
17
Somatik

ジュリアンの答えに加えて。 routesファイルに含めたくない場合。

RequestHeaderを使用して、コントローラーメソッドでこの属性を取得できます。

String from = request().getQueryString("from");
String to = request().getQueryString("to");

これにより、目的のリクエストパラメータが得られ、さらにroutesファイルがクリーンになります。

11
Dave Ranjan

これは、F.Optionを使用してJavaで書き直されたJulienの例です:(play 2.1以降で動作します)

import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
  // …
}

ルート:

GET   /birthday       controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])

任意のクエリパラメータを文字列として選択することもできます(自分で型変換を行う必要があります)。

public static Result birthdays(Option<String> from, Option<String> to) {
  String blarg = request().getQueryString("blarg"); // null if not in URL
  // …
}
7
Max

オプションのクエリパラメータについては、この方法で行うことができます

Routesファイルで、APIを宣言します

GET   /birthdays     controllers.Application.method(from: Long, to: Long)

APIにこれらのクエリパラメータが含まれていない場合、デフォルト値をこれらのパラメータに自動的に割り当てます。

GET   /birthdays    controllers.Application.method(from: Long ?= 0, to: Long ?= 10)

コントローラーアプリケーション内に記述されたメソッドでは、これらのパラメーターの値は、デフォルト値が割り当てられていない場合はデフォルト値が割り当てられていない場合はnullになります。

4
Himanshu Goel

これを行う私の方法には、カスタムQueryStringBindableの使用が含まれます。この方法で、ルートのパラメーターを次のように表現します。

GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)

Periodのコードは次のようになります。

public class Period implements QueryStringBindable<Period> {

  public static final String PATTERN = "dd.MM.yyyy";
  public Date start;

  public Date end;

  @Override
  public F.Option<Period> bind(String key, Map<String, String[]> data) {
      SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);

      try {
          start = data.containsKey("startDate")?sdf.parse(data.get("startDate")  [0]):null;
          end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
      } catch (ParseException ignored) {
          return F.Option.None();
      }
      return F.Option.Some(this);
  }

  @Override
  public String unbind(String key) {
      SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
      return "startDate=" + sdf.format(start) + "&amp;" + "endDate=" + sdf.format(end);
  }

  @Override
  public String javascriptUnbind() {
      return null;
  }

  public void applyDateFilter(ExpressionList el) {
      if (this.start != null)
          el.ge("eventDate", this.start);
      if (this.end != null)
          el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
  }

}

applyDateFilterは、クエリに日付フィルタリングを適用する場合にコントローラーで使用する便利な方法です。明らかに、ここで他の日付のデフォルトを使用するか、bindメソッドの開始日と終了日にnull以外のデフォルトを使用できます。

2
stian