Używam Spring MVC do prostego interfejsu API JSON, z @ResponseBody
podejściem opartym na poniższym. (Mam już warstwę usługi produkującą bezpośrednio JSON.)
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
// TODO: how to respond with e.g. 400 "bad request"?
}
return json;
}
Pytanie, w danym scenariuszu, jaki jest najprostszy i najczystszy sposób odpowiedzi na błąd HTTP 400 ?
Natknąłem się na takie podejścia jak:
return new ResponseEntity(HttpStatus.BAD_REQUEST);
... ale nie mogę go tutaj użyć, ponieważ typem zwracanym przez moją metodę jest String, a nie ResponseEntity.
java
spring
spring-mvc
http-error
Jonik
źródło
źródło
ResponseEntity
. Działa to ładnie i jest tylko prostą zmianą oryginalnego kodu - dzięki!Coś takiego powinno działać, nie jestem pewien, czy istnieje prostszy sposób:
źródło
body
i parametryrequest
).Niekoniecznie najbardziej kompaktowy sposób na zrobienie tego, ale dość czysty IMO
Edytuj, możesz użyć @ResponseBody w metodzie obsługi wyjątków, jeśli używasz Spring 3.1+, w przeciwnym razie użyj
ModelAndView
czegoś lub czegoś.https://jira.springsource.org/browse/SPR-6902
źródło
ERROR org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver - Failed to invoke @ExceptionHandler method: public controller.TestController$MyError controller.TestController.handleException(controller.TestController$BadThingException) org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
Czy w odpowiedzi brakuje czegoś?javax.validation.ValidationException
zamiast tego. (Wiosna 3.1.4)Chciałbym nieznacznie zmienić implementację:
Najpierw tworzę
UnknownMatchException
:Zwróć uwagę na użycie @ResponseStatus , który zostanie rozpoznany przez Spring's
ResponseStatusExceptionResolver
. Zgłoszenie wyjątku spowoduje utworzenie odpowiedzi o odpowiednim statusie odpowiedzi. (Pozwoliłem sobie również na zmianę kodu stanu,404 - Not Found
który uważam za bardziej odpowiedni dla tego przypadku użycia, ale możesz się go trzymać,HttpStatus.BAD_REQUEST
jeśli chcesz).Następnie zmieniłbym
MatchService
na następujący podpis:Wreszcie, chciałbym zaktualizować sterownik i delegatem na sprężyny
MappingJackson2HttpMessageConverter
do obsługi serializacji JSON automatycznie (jest ona dodawana domyślnie jeśli dodać Jackson na ścieżce klas i dodać albo@EnableWebMvc
lub<mvc:annotation-driven />
do swojej konfiguracji, patrz dokumenty referencyjne ):Uwaga: bardzo często oddzielane są obiekty domeny od obiektów widoku lub obiektów DTO. Można to łatwo osiągnąć, dodając małą fabrykę DTO, która zwraca obiekt JSON możliwy do serializacji:
źródło
Match
i jakimś innym przedmiotem.Oto inne podejście. Utwórz niestandardową
Exception
adnotację z@ResponseStatus
, podobnie jak następująca.I w razie potrzeby wyrzuć.
Sprawdź dokumentację Spring tutaj: http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc-ann-annotated-exceptions .
źródło
Jak wspomniano w niektórych odpowiedziach, istnieje możliwość utworzenia klasy wyjątku dla każdego statusu HTTP, który chcesz zwrócić. Nie podoba mi się pomysł stworzenia klasy dla każdego statusu dla każdego projektu. Oto, co wymyśliłem zamiast tego.
Przejdźmy do kodu
Następnie tworzę klasę porad kontrolera
Aby go użyć
http://javaninja.net/2016/06/throwing-exceptions-messages-spring-mvc-controller/
źródło
Używam tego w mojej aplikacji do rozruchu wiosennego
źródło
Najłatwiej jest rzucić
ResponseStatusException
źródło
W przypadku Spring Boot nie jestem do końca pewien, dlaczego było to konieczne (otrzymałem
/error
awarię, mimo że@ResponseBody
zostało zdefiniowane na@ExceptionHandler
), ale samo w sobie nie działało:Nadal zwrócił wyjątek, najwyraźniej dlatego, że nie zdefiniowano żadnych produktywnych typów mediów jako atrybutu żądania:
Więc dodałem je.
I to doprowadziło mnie do posiadania „obsługiwanego kompatybilnego typu nośnika”, ale nadal nie działało, ponieważ mój
ErrorMessage
był wadliwy:JacksonMapper nie traktował tego jako „konwertowalnego”, więc musiałem dodać getters / setters, a także dodałem
@JsonProperty
adnotacjęNastępnie otrzymałem wiadomość zgodnie z przeznaczeniem
źródło
Możesz także
throw new HttpMessageNotReadableException("error description")
skorzystać z domyślnej obsługi błędów Springa .Jednak, podobnie jak w przypadku domyślnych błędów, nie zostanie ustawiona treść odpowiedzi.
Uważam, że są one przydatne podczas odrzucania żądań, które mogły zostać jedynie ręcznie wykonane, potencjalnie wskazując na wrogie zamiary, ponieważ ukrywają fakt, że żądanie zostało odrzucone na podstawie głębszej, niestandardowej weryfikacji i jego kryteriów.
Hth, dtk
źródło
HttpMessageNotReadableException("error description")
jest przestarzałe.Innym sposobem jest użycie
@ExceptionHandler
z@ControllerAdvice
scentralizować wszystkie ładowarki w tej samej klasie, jeśli nie trzeba umieścić metod obsługi w każdym kontrolerze chcesz zarządzać wyjątek.Twoja klasa obsługi:
Twój niestandardowy wyjątek:
Teraz możesz zgłaszać wyjątki od dowolnego kontrolera i definiować inne moduły obsługi w swojej klasie porad.
źródło
Myślę, że ten wątek ma najłatwiejsze, najczystsze rozwiązanie, które nie poświęca narzędzi wojennych JSON, które zapewnia Spring:
https://stackoverflow.com/a/16986372/1278921
źródło