Как обрабатывать необязательные параметры запроса в платформе Play
Предположим, что у меня есть уже работающее приложение для фреймворка Play 2.0 в Scala, которое обслуживает URL-адрес, например:
http://localhost:9000/birthdays
который отвечает списком всех известных дней рождения
Теперь я хочу улучшить это, добавив возможность ограничения результатов с необязательными параметрами "from" (date) и "to" request, такими как
http://localhost:9000/birthdays?from=20120131&to=20120229
(даты здесь интерпретируются как yyyyMMdd)
Мой вопрос заключается в том, как обрабатывать привязку и интерпретацию параметров запроса в Play 2.0 с помощью Scala, особенно учитывая, что оба этих параметра должны быть необязательными.
Должны ли эти параметры как-то выражаться в спецификации "маршруты"? В качестве альтернативы, должен ли метод реагирования Controller каким-либо образом отделить параметры от объекта запроса? Есть ли другой способ сделать это?
Ответы
Ответ 1
Кодируйте свои необязательные параметры как 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])
Ответ 2
Возможно, менее простой способ сделать это для пользователей 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)
Ответ 3
В дополнение к Жюльену ответ. Если вы не хотите включать его в файл маршрутов.
Вы можете получить этот атрибут в методе контроллера с помощью RequestHeader
String from=request().getQueryString("from");
String to=request().getQueryString("to");
Это даст вам требуемые параметры запроса, а также сохранит ваш файл маршрутов в чистоте.
Ответ 4
Здесь пример Жюльена переписан в java, используя F.Option: (работает с игрой 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
// …
}
Ответ 5
Мой способ сделать это включает использование QueryStringBindable
. Таким образом, я выражаю параметры в маршрутах как:
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());
}
}
applyDateFilter
- это просто метод convienence, который я использую в своих контроллерах, если я хочу применить фильтрацию даты к запросу. Очевидно, вы могли бы использовать другие значения по умолчанию по умолчанию здесь или использовать другое значение по умолчанию, кроме нуля, для даты начала и окончания в методе bind
.
Ответ 6
Для необязательных параметров запроса вы можете сделать это таким образом
В файле маршрутов объявите API
GET /birthdays controllers.Application.method(from: Long, to: Long)
Вы также можете указать значение по умолчанию, в случае, если API не содержит эти параметры запроса, он автоматически присваивает значения по умолчанию этим параметрам
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
В методе, написанном внутри контроллера Приложения, эти параметры будут иметь значение null
, если значения по умолчанию не назначены иначе по умолчанию.