Как обрабатывать необязательные параметры запроса в платформе Play
-
11-12-2019 - |
Вопрос
Допустим, у меня есть уже функционирующее приложение на базе платформы Play 2.0 в Scala, которое обслуживает такой URL-адрес:
http://localhost:9000/дни рождения
который отвечает списком всех известных дней рождения
Теперь я хочу улучшить это, добавив возможность ограничивать результаты с помощью дополнительных параметров запроса «от» (дата) и «до», таких как
http://localhost:9000/birthdays?from=20120131&to=20120229
(здесь даты интерпретируются как ггггММдд)
Мой вопрос заключается в том, как обрабатывать привязку и интерпретацию параметров запроса в Play 2.0 с помощью Scala, особенно с учетом того, что оба этих параметра должны быть необязательными.
Должны ли эти параметры быть каким-то образом выражены в спецификации «маршрутов»?В качестве альтернативы, должен ли отвечающий метод контроллера каким-то образом отделять параметры от объекта запроса?Есть ли другой способ сделать это?
Решение
Закодируйте свои дополнительные параметры как 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])
Другие советы
Возможно, менее чистый способ выполнения этого для пользователей Java устанавливает по умолчанию:
GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)
.
и в контроллере
public static Result users(Integer max, Integer page) {...}
.
Еще одна проблема, вам придется повторить значения по умолчанию всякий раз, когда вы ссылаетесь на свою страницу в шаблоне
@routes.Application.users(max = 50, page = 0)
. В дополнение к ответу Джульен.Если вы не хотите включить его в маршруты .
Вы можете получить этот атрибут в методе контроллера, используя requestever
.
String from = request().getQueryString("from");
String to = request().getQueryString("to");
Это даст вам желаемые параметры запроса, плюс держите ваши маршруты файл .
Вот пример Джульен, переписанный в Java, используя f.option: (работает как 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
// …
}
. Для дополнительных параметров запроса вы можете сделать это таким образом
в файле маршрутов, объявить API
GET /birthdays controllers.Application.method(from: Long, to: Long)
.
Вы также можете дать некоторое значение по умолчанию, в случае, если API не содержит эти параметры запроса, он автоматически назначает значения по умолчанию для этих параметров
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
.
В способе написано Внутреннее приложение контроллера Эти слова будут иметь значение null
, если значения по умолчанию не назначаются значения по умолчанию.
Мой способ сделать это включает в себя пользовательский генеракодицетагкод.Таким образом, я экспрессирую параметры в маршрутах как:
GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.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) + "&" + "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());
}
}
.
QueryStringBindable
- это просто метод содействия, который я использую в моем контроллерах, если я хочу применить фильтрацию даты в запрос.Очевидно, что вы можете использовать другие данные по умолчанию здесь или использовать некоторые другие по умолчанию, чем NULL для начала и окончания даты окончания в методе applyDateFilter
.