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?
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])
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)
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.
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
// …
}
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.
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) + "&" + "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.