Czy powinienem używać typu Data w JAX-RS @PathParam?

9

Właśnie o tym myślę na serwerze JEE Glassfish przy użyciu Jersey.

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

Podoba mi się pomysł, aby móc powiedzieć ludziom korzystającym z usługi RESTful, że „Data tutaj jest wszystkim, co działa z klasą Date w Javie”. Jest to dość proste z punktu widzenia, że ​​mogą po prostu spojrzeć na specyfikację daty i będą już mieć działający model, z którym będą mogli testować.

Problemem, o który się martwię, jest to, że kiedy to robię, JAX-RS nie jest zbyt miły, gdy Date () nie lubi tego, co dostaje w konstruktorze. Ponieważ Date () generuje błąd, jeśli nie może przeanalizować tego, co zostało podane (np. Jeśli przekażesz ciąg „dzisiaj” zamiast prawdziwej daty), serwer JEE zwraca błąd 404.

Czy to dobra praktyka? Czy istnieje lepszy sposób, aby to zrobić, o czym nie myślę?

Jazzepi
źródło

Odpowiedzi:

8

Brzmi jak zły pomysł. Po pierwsze, konstruktor Date, na którym będziesz polegać, został uznany za przestarzały od wersji Java 1.1 na korzyść DateFormat.parseDate (), właśnie dlatego, że nie jest jasne, w jaki sposób łańcuchy powinny być parsowane w datach, ponieważ reguły są różne dla różnych lokalizacji.

Radzę trzymać się określonego formatu, najlepiej międzynarodowego formatu rrrr-MM-dd, i użyć DateFormat do parsowania daty z ciągu wewnątrz usługi, co wyjaśnia, jak korzystać z usługi internetowej, i pozwala postępować zgodnie ze standardową konwencją zwracania komunikatów o błędach dla usług internetowych, gdy coś pójdzie nie tak.

Theodore Murdock
źródło
11

Używam niestandardowej klasy DateParam:

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

Klasa jest zdefiniowana jako:

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;
  }
}

Jeśli parametr jest pusty, wówczas otrzymasz zerową datę. Można rozszerzyć DateParamo publiczne statyczne pole końcowe dla niezdefiniowanych wartości dat. Ułatwiłoby to testowanie niezdefiniowanych parametrów daty.

Jedną wadą jest to, że dla każdego DateParam tworzona jest nowa instancja SimpleDateFormat. Ponieważ jednak SimpleDateFormat nie jest bezpieczny dla wątków, nie możemy go łatwo ponownie użyć.

migu
źródło
3
1+. Java 8 wprowadziła bezpieczny wątek DateTimeFormatter. Dla Javy <= 7 ThreadLocal
użyłbym
3

Kto skorzysta z twojej usługi? Czy będą starali się sprawdzić specyfikacjęDate sprawdzić klasy i dowiedzieć się, jakie ciągi będzie analizować? Nie zrobiłbym tego, nawet gdybym był programistą Java, wiedziałbym, gdzie szukać ;-)

Myślę, że powinieneś najpierw powiedzieć swoim użytkownikom, jak będą wyglądać Twoje identyfikatory URI, np

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

a następnie poszukaj sposobu, aby Jersey pomógł ci w analizie wybranego formatu daty. Może to oznaczać użycie Datetypu parametru i być może określenie wyrażenia regularnego w @Pathadnotacji, np

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

lub używając innej klasy zdolnej do parsowania daty w twoim formacie. Jak obsługiwać identyfikatory URI, które nie pasują do specyfikacji, którą podajesz użytkownikom, to kolejna rzecz, którą powinieneś zdecydować, jak obsługiwać niezależnie od któregokolwiek z powyższych (zwróć domyślny zasób? Zwróć błąd 404?).

agnul
źródło