Должен ли я использовать тип Date в JAX-RS @PathParam?

9

Это то, что я думаю сделать на сервере JEE Glassfish с использованием Jersey.

@GET
@Path("/{name}/{date}")
public String getMessages(@PathParam("name") String name, @PathParam("date") Date date)

Мне нравится идея о том, чтобы сказать людям, использующим этот веб-сервис RESTful, что «Дата здесь - это все, что работает с классом Date в Java». Это довольно просто с точки зрения того, что они могут просто взглянуть на спецификацию Date, и у них уже будет рабочая модель, с которой они смогут протестировать.

Проблема, о которой я беспокоюсь, состоит в том, что когда я делаю это, JAX-RS не очень хорош, когда Date () не нравится то, что он получает в конструкторе. Поскольку Date () выдает ошибку, если не может проанализировать то, что ему дано (например, если вы передаете ей строку «сегодня» вместо реальной даты), сервер JEE возвращает ошибку 404.

Это хорошая практика? Есть ли лучший способ сделать это, о котором я не думаю?

Jazzepi
источник

Ответы:

8

Похоже, плохая идея. С одной стороны, конструктор Date, на который вы бы положились, начиная с Java 1.1, устарел в пользу DateFormat.parseDate (), именно потому, что неясно, как строки должны быть разбиты на даты, так как правила различны для разных мест.

Я бы порекомендовал придерживаться определенного формата, предпочтительно интернационально понятного yyyy-MM-dd, и использовать DateFormat для анализа даты из строки внутри вашего сервиса, которая проясняет, как использовать веб-сервис, и позволяет вам Следуйте стандартному соглашению о возврате сообщений об ошибках для ваших веб-сервисов, когда что-то идет не так.

Теодор Мердок
источник
11

Я использую пользовательский класс DateParam:

@GET
@Path("/{name}/{date}")
public String getMessages(@PathParam("name") String name, @PathParam("date") DateParam date)
  Date date = date.getDate();

Класс определяется как:

public class DateParam {
  private final Date date;

  public DateParam(String dateStr) throws WebApplicationException {
    if (isEmpty(dateStr)) {
      this.date = null;
      return;
    }
    final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    try {
      this.date = dateFormat.parse(dateStr);
    } catch (ParseException e) {
      throw new WebApplicationException(Response.status(Status.BAD_REQUEST)
        .entity("Couldn't parse date string: " + e.getMessage())
        .build());
    }
  }

  public Date getDate() {
    return date;
  }
}

Если параметр пуст, вы получите нулевую дату. Вы можете расширить DateParamс помощью открытого статического конечного поля для неопределенных значений даты. Это сделает проверку на неопределенные параметры даты более понятной.

Одним из недостатков здесь является то, что для каждого DateParam создается новый экземпляр SimpleDateFormat. Однако, поскольку SimpleDateFormat не является потокобезопасным, мы не можем легко использовать его повторно.

Migu
источник
3
1+. Java 8 представила потокобезопасный DateTimeFormatter. Для Java <= 7 я бы использовалThreadLocal
Anthony Accioly
3

Кто будет использовать ваш сервис? Будут ли они искать спецификацию Dateкласса и выяснять, какие строки он будет анализировать? Я бы не стал, даже если бы я был программистом на Java, я бы знал, где искать ;-)

Я думаю, что вы должны сначала сказать своим пользователям, как будут выглядеть ваши URI, например

.../your-resource-name/yyyy-MM-dd

а затем найдите способ, чтобы Джерси помог вам разобрать любой формат даты, который вы выбрали. Это может означать использование Dateтипа параметра и, возможно, указание регулярного выражения в @Pathаннотации, например

@Path(/{name}/{date: [0-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9]/)

или используя другой класс, способный анализировать дату в вашем формате. Обработка URI, которые не соответствуют спецификации, которую вы даете своим пользователям, - это еще одна вещь, которую вы должны решить, как обрабатывать независимо от любого из вышеперечисленных (вернуть ресурс по умолчанию? Вернуть ошибку 404?).

agnul
источник