Co zwrócić, jeśli metoda kontrolera Spring MVC nie zwraca wartości?

137

Używam jQuery $.getJSON()do wykonywania asynchronicznych wywołań do mojego prostego zaplecza Spring MVC. Większość metod kontrolera Spring wygląda następująco:

@RequestMapping(value = "/someURL", method = RequestMethod.POST)
public @ResponseBody SomePOJO getSomeData(@ModelAttribute Widget widget,
    @RequestParam("type") String type) {
    return someDAO.getSomeData(widget, type);
}   

Mam rzeczy skonfigurowane tak, aby każdy kontroler zwracał @ResponseBodyjako JSON, czego oczekuje po stronie klienta.

Ale co się dzieje, gdy żądanie nie powinno zwrócić żadnej treści po stronie klienta? Czy mogę dostać:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public @ResponseBody void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

Jeśli nie, jaka jest odpowiednia składnia do użycia w tym miejscu?

IAmYourFaja
źródło
Zakładam, że jeśli nic nie zwrócisz, nie zostanie odesłana żadna treść?
arahant
1
Myślę, że nadal zwróciłbym jakiś POJO, nawet jeśli w wersji 1 twojego rozwiązania po prostu opakowuje on wartość logiczną „sukcesu” lub coś podobnego. Następnie masz spójny wzorzec we wszystkich swoich metodach AJAX i coś, co jest łatwiejsze do zbudowania, gdy okaże się, że musisz coś zwrócić!
Millhouse
W przeciwieństwie do sugestii odpowiedzi, to, co masz na początku w drugim fragmencie, jest w porządku i jest prawidłowym sposobem obsługi POSTdanych.
Brett Ryan
W tym przypadku zwróci wartość null. @RestController public class RESTControllerExample {@RequestMapping (value = "/ workers", method = RequestMethod.GET) public void getEmployeeNames () {EmployeeSource.getEmployees (); System.out.println ("Gotowe"); }}
spandey

Odpowiedzi:

257

możesz zwrócić void, wtedy musisz oznaczyć metodę @ResponseStatus (value = HttpStatus.OK) nie potrzebujesz @ResponseBody

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}

Tylko metody get zwracają niejawność kodu stanu 200, wszystkie inne, które masz, wykonują jedną z trzech rzeczy:

  • Zwróć void i oznacz metodę za pomocą @ResponseStatus(value = HttpStatus.OK)
  • Zwróć obiekt i oznacz go @ResponseBody
  • Zwróć HttpEntityinstancję
ams
źródło
2
W przypadku wystąpienia wyjątku w czasie wykonywania w międzyczasie, zostanie zwrócony HTTP 500, a nie 200. Jeśli więc dojdzie do błędu interfejsu użytkownika, komunikat o wyjątku / błędzie zostanie wyświetlony poprawnie.
Lee Chee Kiam
27
Właściwie nie musisz ustawiać @ResponseStatusi nie powinieneś. Po prostu mając @ResponseBodyna voidprzewodnika jest w porządku wystarczy.
Brett Ryan,
11
Myślę, że lepiej będzie zwrócić 204 No Content zamiast 200 dla metod void
raspacorp
1
@raspacorp 200 jest poprawne dla POST, ponieważ nie ma mieć ciała.
Brett Ryan
8
@BrettRyan jako komentarz, przynajmniej dla REST API jest powszechną praktyką, że POST będzie używany do tworzenia treści, w którym to przypadku zwykle zwraca identyfikator utworzonej encji (-ów), w pełni utworzonych encji lub linku do operacji odczytu. Zwrot stanu 200 bez zawartości może być mylący z perspektywy interfejsu API REST.
raspacorp
43

Możesz po prostu zwrócić ResponseEntity z odpowiednim nagłówkiem:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public ResponseEntity updateDataThatDoesntRequireClientToBeNotified(...){
....
return new ResponseEntity(HttpStatus.OK)
}
Biju Kunjummen
źródło
Gdyby ktoś napotkał ten sam problem, co ja, to nie działało na starszej wersji wiosny (4.1.1), otrzymywałem 500 błędów. Zaktualizowałem do 4.2.0 i działa świetnie
sos
To także mój preferowany sposób zwrotu pustych 200. Od wiosny 4.1 zamiast tego używaj wzorca budującego: return ResponseEntity.ok (). Build ();
GreenTurtle
5
Chociaż wydaje się, że się kompiluje, daje następujące ostrzeżenieResponseEntity is a raw type. References to generic type ResponseEntity<T> should be parameterized
Gonzalo.
8

Możesz zwrócić obiekt „ResponseEntity”. Korzystanie z obiektu „ResponseEntity” jest bardzo wygodne zarówno podczas konstruowania obiektu odpowiedzi (zawierającego treść odpowiedzi i kod stanu HTTP), jak i podczas pobierania informacji z obiektu odpowiedzi.

Metody takie jak getHeaders (), getBody (), getContentType (), getStatusCode () itp. Sprawiają, że odczytanie obiektu ResponseEntity jest bardzo łatwe.

Należy używać obiektu ResponseEntity z kodem stanu HTTP 204 (brak treści), który służy konkretnie do określenia, że ​​żądanie zostało przetworzone poprawnie, a treść odpowiedzi jest celowo pusta. Używanie odpowiednich kodów stanu do przekazywania właściwych informacji jest bardzo ważne, zwłaszcza jeśli tworzysz interfejs API, który będzie używany przez wiele aplikacji klienckich.

Harley
źródło
3
ustawienie @ResponseStatus(HttpStatus.NO_CONTENT)rozwiązane XML Parsing Error: no root element founddla mnie w przeglądarce
aliopi
3

Tak, możesz użyć @ResponseBody z voidtypem zwrotu:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
@ResponseBody
public void updateDataThatDoesntRequireClientToBeNotified(...) {
    ...
}
user1338062
źródło
1
więc jaki będzie typ zwrotu… czy to kod statusu HTTP?
spandey
@techBeginner W tym przypadku 200 (OK).
Lakatos Gyula
2

Nie ma nic złego w zwracaniu unieważnienia @ResponseBodyi należy o to POSTpoprosić.

Zamiast tego użyj kodów stanu HTTP, aby zdefiniować błędy w procedurach obsługi wyjątków, ponieważ inni wspominają o stanie sukcesu. Normalna metoda, jaką masz, zwróci kod odpowiedzi, 200którego chcesz, każdy program obsługi wyjątków może następnie zwrócić obiekt błędu i inny kod (tj 500.).

Brett Ryan
źródło
1

Ale w miarę jak twój system rośnie pod względem rozmiaru i funkcjonalności ... myślę, że zwracanie zawsze jsona nie jest wcale złym pomysłem. To bardziej kwestia architektoniczna / „projektowanie na dużą skalę”.

Możesz pomyśleć o zachowaniu zawsze JSON z dwoma znanymi polami: kodem i danymi. Gdzie kod jest kodem numerycznym określającym powodzenie operacji do wykonania, a dane to wszelkie dodatkowe dane związane z żądaną operacją / usługą.

Chodź, kiedy korzystamy z zaplecza dostawcy usług, każdą usługę można sprawdzić, aby sprawdzić, czy działa dobrze.

Więc trzymam się, żeby wiosna nie zarządzała tym, ujawniając hybrydowe operacje zwrotne (niektóre zwracają dane, inne nic ...) .. natychmiast upewnij się, że twój serwer udostępnia bardziej jednorodny interfejs. Pod koniec dnia jest prostsze.

Zwycięzca
źródło
0

Oto przykładowy kod, który zrobiłem dla metody asynchronicznej

@RequestMapping(value = "/import", method = RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
public void importDataFromFile(@RequestParam("file") MultipartFile file) 
{
    accountingSystemHandler.importData(file, assignChargeCodes);
}

Nie musisz zwracać niczego ze swojej metody, wszystko czego potrzebujesz, aby użyć tej adnotacji aby Twoja metoda w każdym przypadku zwracała OK

@ResponseStatus(value = HttpStatus.OK)
AbdusSalam
źródło