Cómo manejar parámetros de consulta opcionales en Play Framework
-
11-12-2019 - |
Pregunta
Digamos que ya tengo una aplicación basada en el marco Play 2.0 en funcionamiento en Scala que sirve una URL como:
http://localhost:9000/cumpleaños
que responde con una lista de todos los cumpleaños conocidos
Ahora quiero mejorar esto agregando la capacidad de restringir los resultados con parámetros de solicitud opcionales "desde" (fecha) y "hasta" como
http://localhost:9000/cumpleaños?from=20120131&to=20120229
(las fechas aquí se interpretan como aaaaMMdd)
Mi pregunta es cómo manejar la vinculación e interpretación de los parámetros de solicitud en Play 2.0 con Scala, especialmente teniendo en cuenta que ambos parámetros deben ser opcionales.
¿Deberían expresarse estos parámetros de alguna manera en la especificación de "rutas"?Alternativamente, ¿debería el método Controlador que responde separar los parámetros del objeto de solicitud de alguna manera?Hay otra manera de hacer esto?
Solución
Codifique sus parámetros opcionales como Option[String]
(o Option[java.util.Date]
, pero tendrá que implementar su propio QueryStringBindable[Date]
):
def birthdays(from: Option[String], to: Option[String]) = Action {
// …
}
y declare la siguiente ruta:
GET /birthday controllers.Application.birthday(from: Option[String], to: Option[String])
Otros consejos
Una forma menos limpia de hacer esto para que los usuarios de Java están configurando los valores predeterminados:
GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)
y en el controlador
public static Result users(Integer max, Integer page) {...}
Un problema más, tendrá que repetir los valores predeterminados cada vez que se enlaza a su página en la plantilla
@routes.Application.users(max = 50, page = 0)
Además de la respuesta de Julien.Si no desea incluirlo en el archivo rutas .
Puede obtener este atributo en el método del controlador usando Solicitud
String from = request().getQueryString("from");
String to = request().getQueryString("to");
Esto le dará los parámetros de solicitud deseados, además de mantener su archivo Limpiar.
Aquí está el ejemplo de Julien reescrito en Java, usando F.Option: (funciona a partir de juego 2.1)
import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
// …
}
ruta:
GET /birthday controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])
También puede seleccionar los parámetros de consulta arbitrarios como cadenas (tiene que hacer la conversión de tipo usted mismo):
public static Result birthdays(Option<String> from, Option<String> to) {
String blarg = request().getQueryString("blarg"); // null if not in URL
// …
}
Para los parámetros de consulta opcionales, puede hacerlo de esta manera
en el archivo de rutas, declare API
GET /birthdays controllers.Application.method(from: Long, to: Long)
También puede dar algún valor predeterminado, en caso de que API no contenga estos parámetros de consulta, asignará automáticamente los valores predeterminados a estos params
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
En el método escrito en la aplicación del controlador dentro de estos params tendrán valor null
si no hay valores predeterminados asignados a los valores predeterminados.
Mi forma de hacer esto implica usar un personalizado QueryStringBindable
.De esta manera expreso parámetros en rutas como:
GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)
El código para Period se ve así.
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
es solo un método conveniente que uso en mis controladores si quiero aplicar filtrado de fecha a la consulta.Obviamente, podría usar otras fechas predeterminadas aquí, o usar algún otro valor predeterminado que no sea nulo para las fechas de inicio y finalización en el bind
método.