Uczę się JAX-RS (alias JSR-311) przy użyciu Jersey. Z powodzeniem utworzyłem Zasób root i bawię się parametrami:
@Path("/hello")
public class HelloWorldResource {
@GET
@Produces("text/html")
public String get(
@QueryParam("name") String name,
@QueryParam("birthDate") Date birthDate) {
// Return a greeting with the name and age
}
}
Działa to świetnie i obsługuje dowolny format w bieżących ustawieniach regionalnych rozumiany przez konstruktor Date (String) (np. RRRR / mm / dd i mm / dd / RRRR). Ale jeśli podam wartość, która jest niepoprawna lub niezrozumiała, otrzymuję odpowiedź 404.
Na przykład:
GET /hello?name=Mark&birthDate=X
404 Not Found
Jak mogę dostosować to zachowanie? Może inny kod odpowiedzi (prawdopodobnie „400 złych żądań”)? Co z logowaniem błędu? Może dodać opis problemu („zły format daty”) w niestandardowym nagłówku, aby ułatwić rozwiązywanie problemów? Lub zwróć całą odpowiedź na błąd wraz ze szczegółami, wraz z kodem statusu 5xx?
ExceptionMapper
interfejsu (co jest lepszym podejściem niż rozszerzanie). Zobacz więcej tutaj vvirlan.wordpress.com/2015/10/19/…Stwórz ponad klasę. To obsłuży 404 (NotFoundException) i tutaj w metodzie toResponse możesz podać swoją niestandardową odpowiedź. Podobnie istnieją ParamException itp., Które należy zmapować, aby uzyskać dostosowane odpowiedzi.
źródło
Jersey zgłasza wyjątek com.sun.jersey.api.ParamException, gdy nie zdoła usunąć parametrów, więc jednym z rozwiązań jest utworzenie wyjątku, który obsługuje te typy wyjątków:
źródło
Możesz także napisać klasę wielokrotnego użytku dla zmiennych z komentarzami QueryParam
użyj tego w następujący sposób:
Mimo że obsługa błędów jest w tym przypadku trywialna (generowanie odpowiedzi 400), użycie tej klasy pozwala ogólnie oddzielić obsługę parametrów, która może obejmować rejestrowanie itp.
źródło
DateParam
powyższej, która otaczaorg.joda.time.DateTime
zamiastjava.util.Calendar
. Używasz tego@QueryParam
raczej niżDateTime
samego siebie.JodaModule
który można zarejestrować za pomocą tejObjectMapper
registerModules
metody. Może obsługiwać wszystkie konwersje typu Joda.com.fasterxml.jackson.datatype.joda.JodaModule
Jedno oczywiste rozwiązanie: weź ciąg, przekonwertuj na datę sam. W ten sposób możesz zdefiniować żądany format, wychwytywać wyjątki i ponownie przesłać lub dostosować wysyłany błąd. Do parsowania SimpleDateFormat powinien działać poprawnie.
Jestem pewien, że istnieją sposoby na przechwycenie procedur obsługi typów danych, ale być może w tym przypadku wystarczy trochę prostego kodu.
źródło
Ja też lubię, że StaxMan prawdopodobnie zaimplementuje ten QueryParam jako String, a następnie obsłuży konwersję, w razie potrzeby ponownie przesyłając.
Jeśli zachowanie specyficzne dla ustawień narodowych jest pożądanym i oczekiwanym zachowaniem, skorzystaj z następujących opcji, aby zwrócić błąd 400 BŁĘDNE ŻĄDANIE:
throw new WebApplicationException(Response.Status.BAD_REQUEST);
Więcej informacji znajdziesz w JavaDoc dla javax.ws.rs.core.Response.Status .
źródło
Dokumentacja @QueryParam mówi
Jeśli chcesz kontrolować, jaka odpowiedź trafia do użytkownika, gdy parametru zapytania w postaci ciągu nie można przekonwertować na typ T, możesz zgłosić wyjątek WebApplicationException. Dropwizard zawiera następujące * klasy Param, których możesz użyć do swoich potrzeb.
BooleanParam, DateTimeParam, IntParam, LongParam, LocalDateParam, NonEmptyStringParam, UUIDParam. Zobacz https://github.com/dropwizard/dropwizard/tree/master/dropwizard-jersey/src/main/java/io/dropwizard/jersey/params
Jeśli potrzebujesz Joda DateTime, po prostu użyj Dropwizard DateTimeParam .
Jeśli powyższa lista nie odpowiada Twoim potrzebom, zdefiniuj własną, rozszerzając AbstractParam. Zastąp metodę analizy. Jeśli potrzebujesz kontroli nad treścią odpowiedzi na błąd, zastąp metodę błędu.
Dobry artykuł Cody Hale na ten temat znajduje się na stronie http://codahale.com/what-makes-jersey-interesting-parameter-classes/
Konstruktor Date (String arg) jest przestarzały. Używałbym klas daty Java 8, jeśli korzystasz z Java 8. W przeciwnym razie zalecana jest data i godzina Joda.
źródło
To jest właściwie właściwe zachowanie. Jersey spróbuje znaleźć moduł obsługi dla danych wejściowych i spróbuje skonstruować obiekt na podstawie danych wejściowych. W takim przypadku spróbuje utworzyć nowy obiekt Date o wartości X podanej konstruktorowi. Ponieważ jest to nieprawidłowa data, zgodnie z umową Jersey zwróci 404.
Możesz przepisać i ustawić datę urodzenia jako ciąg znaków, a następnie spróbować przeanalizować, a jeśli nie dostaniesz tego, czego chcesz, możesz zgłosić dowolny wyjątek za pomocą dowolnego mechanizmu odwzorowywania wyjątków (istnieje kilka ).
źródło
Miałem do czynienia z tym samym problemem.
Chciałem złapać wszystkie błędy w centralnym miejscu i je przekształcić.
Poniżej znajduje się kod tego, jak sobie z tym poradziłem.
Utwórz następującą klasę, która implementuje
ExceptionMapper
i dodaje@Provider
adnotację do tej klasy. Pozwoli to obsłużyć wszystkie wyjątki.Przesłoń
toResponse
metodę i zwróć obiekt odpowiedzi wypełniony dostosowanymi danymi.źródło
Podejście 1: przez rozszerzenie klasy WebApplicationException
Utwórz nowy wyjątek, rozszerzając wyjątek WebApplicationException
Teraz rzucaj „RestException”, gdy jest to wymagane.
Możesz zobaczyć pełną aplikację pod tym linkiem .
Podejście 2: Implementuj ExceptionMapper
Poniższy program odwzorowujący obsługuje wyjątek typu „DataNotFoundException”
Możesz zobaczyć pełną aplikację pod tym linkiem .
źródło
Tylko jako rozszerzenie odpowiedzi @Steven Lavine na wypadek, gdybyś chciał otworzyć okno logowania przeglądarki. Trudno mi było poprawnie zwrócić odpowiedź ( uwierzytelnianie MDN HTTP ) z filtra, na wypadek gdyby użytkownik nie został jeszcze uwierzytelniony
Pomogło mi to zbudować Odpowiedź, aby wymusić logowanie do przeglądarki, zwróć uwagę na dodatkową modyfikację nagłówków. Spowoduje to ustawienie kodu stanu na 401 i ustawienie nagłówka, który spowoduje, że przeglądarka otworzy okno dialogowe nazwy użytkownika / hasła.
źródło