wake-up-neo.com

Umgang mit optionalen Abfrageparametern im Play Framework

Nehmen wir an, ich habe in Scala) eine bereits funktionierende, auf dem Play 2.0-Framework basierende Anwendung, die eine URL wie die folgende enthält:

http: // localhost: 9000/geburtstage

daraufhin werden alle bekannten Geburtstage aufgelistet

Ich möchte dies jetzt verbessern, indem ich die Möglichkeit hinzufüge, die Ergebnisse mit optionalen "from" (Datum) - und "to" -Anforderungsparametern wie "from" (Datum) einzuschränken

http: // localhost: 9000/geburtstage? von = 20120131 & bis = 20120229

(Daten hier interpretiert als JJJJMMTT)

Meine Frage ist, wie mit der Bindung und Interpretation von Anforderungsparametern in Play 2.0 mit Scala umgegangen werden soll, insbesondere angesichts der Tatsache, dass beide Parameter optional sein sollten.

Sollten diese Parameter irgendwie in der "Strecken" -Spezifikation ausgedrückt werden? Alternativ sollte die antwortende Controller-Methode die Parameter irgendwie vom Anforderungsobjekt trennen? Gibt es eine andere Möglichkeit, dies zu tun?

67
magicduncan

Codieren Sie Ihre optionalen Parameter als Option[String] (Oder Option[Java.util.Date], Sie müssen jedoch Ihren eigenen QueryStringBindable[Date] Implementieren):

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

Und erkläre die folgende Route:

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

Eine vielleicht weniger saubere Methode, dies für Java Benutzer zu tun, ist das Setzen von Standardwerten:

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

Und in der Steuerung

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

Ein weiteres Problem: Sie müssen die Standardeinstellungen jedes Mal wiederholen, wenn Sie auf Ihre Seite in der Vorlage verlinken

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

Zusätzlich zu Juliens Antwort. Wenn Sie es nicht in die Datei routes aufnehmen möchten.

Sie können dieses Attribut in der Controller-Methode mit RequestHeader abrufen

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

Dies gibt Ihnen die gewünschten Anforderungsparameter und hält Ihre Routen -Datei sauber.

11
Dave Ranjan

Hier ist Juliens Beispiel, das mit F.Option in Java umgeschrieben wurde: (funktioniert ab Play 2.1)

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

Route:

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

Sie können auch beliebige Abfrageparameter als Zeichenfolgen auswählen (Sie müssen die Typkonvertierung selbst durchführen):

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

Für optionale Abfrageparameter können Sie dies auf diese Weise tun

Deklarieren Sie in der Routendatei die API

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

Sie können auch einen Standardwert angeben. Wenn die API diese Abfrageparameter nicht enthält, weist sie diesen Parametern automatisch die Standardwerte zu

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

In der in der Controller-Anwendung geschriebenen Methode haben diese Parameter den Wert null, wenn keine Standardwerte zugewiesen wurden, anderenfalls Standardwerte.

4
Himanshu Goel

Meine Art, dies zu tun, beinhaltet die Verwendung eines benutzerdefinierten QueryStringBindable. Auf diese Weise drücke ich Parameter in Routen wie folgt aus:

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

Der Code für Period sieht so aus.

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 ist nur eine Convienence-Methode, die ich in meinen Controllern verwende, wenn ich die Abfrage nach Datum filtern möchte. Offensichtlich können Sie hier andere Datumsvorgaben verwenden oder eine andere Vorgabe als null für Start- und Enddatum in der bind -Methode verwenden.

2
stian