Cosa restituire se il metodo del controller Spring MVC non restituisce valore?


135

Sto usando jQuery $.getJSON()per effettuare chiamate asincrone al mio semplice backend Spring MVC. La maggior parte dei metodi del controller Spring è simile al seguente:

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

Ho impostato le cose in modo che ogni controller restituisca il @ResponseBodyJSON, che è ciò che il lato client si aspetta.

Ma cosa succede quando una richiesta non dovrebbe restituire alcun contenuto sul lato client? Posso avere:

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

In caso contrario, qual è la sintassi appropriata da utilizzare qui?


Presumo che se non restituisci nulla, non ci sarà alcun contenuto rispedito?
Arahant

1
Penso che avrei comunque restituito un POJO di qualche tipo, anche se nella versione 1 della tua soluzione avvolge solo un booleano "successo" o qualcosa di simile. Quindi hai un modello coerente in tutti i tuoi metodi AJAX e qualcosa che è più facile da costruire quando si scopre che devi restituire qualcosa!
Mulino

Contrariamente a quanto suggeriscono le risposte, quello che hai avuto per la prima volta nel secondo frammento è perfettamente perfetto e il modo corretto di gestire i POSTdati.
Brett Ryan,

In questo caso restituirà null. @RestController classe pubblica RESTControllerExample {@RequestMapping (value = "/ impiegati", metodo = RequestMethod.GET) void pubblico getEmployeeNames () {EmployeeSource.getEmployees (); System.out.println ("I am done"); }}
spandey,

Risposte:


256

puoi restituire void, quindi devi contrassegnare il metodo con @ResponseStatus (valore = HttpStatus.OK) non hai bisogno di @ResponseBody

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

Solo i metodi get restituiscono un'implicita di 200 codici di stato, tutti gli altri hai una delle tre cose:

  • Restituisce il vuoto e contrassegnare il metodo con @ResponseStatus(value = HttpStatus.OK)
  • Restituisce un oggetto e contrassegnalo con @ResponseBody
  • Restituisce HttpEntityun'istanza

2
Nel caso in cui si verifichi un'eccezione di runtime, HTTP 500 verrà restituito e non 200. Pertanto, se il front-end non riesce, il messaggio di eccezione / errore verrà visualizzato correttamente.
Lee Chee Kiam,

27
In realtà, non è necessario impostare @ResponseStatuse non dovrebbe. Avere semplicemente @ResponseBodyun voidgestore va abbastanza bene.
Brett Ryan,

11
Penso che sarà meglio restituire un 204 senza contenuto invece di un 200 per i metodi void
raspacorp

1
@raspacorp 200 è corretto per POST in quanto non è pensato per avere un corpo.
Brett Ryan,

8
@BrettRyan solo come commento, almeno per un'API REST è pratica comune che un POST verrà utilizzato per la creazione di contenuti, nel qual caso di solito restituisce l'id dell'entità (e) creata (e), le entità completamente create o un collegamento all'operazione di lettura. Un ritorno di 200 stati senza contenuto potrebbe creare confusione dal punto di vista dell'API REST.
raspacorp,

43

Puoi semplicemente restituire un ResponseEntity con l'intestazione appropriata:

@RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
public ResponseEntity updateDataThatDoesntRequireClientToBeNotified(...){
....
return new ResponseEntity(HttpStatus.OK)
}

Nel caso in cui qualcuno incontrasse lo stesso problema che ho fatto, questo non ha funzionato su una versione precedente di Spring (4.1.1), avrei ricevuto 500 errori. Ho aggiornato alla 4.2.0 e funziona alla grande
salsa

Questo è il mio modo preferito di restituire anche 200 vuoti. Dalla primavera 4.1 invece usa il modello builder: return ResponseEntity.ok (). Build ();
GreenTurtle,

3
Anche se sembra compilare, dà il seguente avvertimentoResponseEntity is a raw type. References to generic type ResponseEntity<T> should be parameterized
Gonzalo.-

8

È possibile restituire l'oggetto "ResponseEntity". L'uso dell'oggetto "ResponseEntity" è molto utile sia al momento della costruzione dell'oggetto risposta (che contiene il corpo della risposta e il codice di stato HTTP) sia al momento di ottenere informazioni dall'oggetto risposta.

Metodi come getHeaders (), getBody (), getContentType (), getStatusCode () ecc rendono molto semplice il lavoro di lettura dell'oggetto ResponseEntity.

Dovresti utilizzare l'oggetto ResponseEntity con un codice di stato http 204 (nessun contenuto), che è specificamente per specificare che la richiesta è stata elaborata correttamente e il corpo della risposta è intenzionalmente vuoto. Utilizzare codici di stato appropriati per trasmettere le informazioni giuste è molto importante, soprattutto se si sta creando un'API che verrà utilizzata da più applicazioni client.


3
impostazione @ResponseStatus(HttpStatus.NO_CONTENT)risolta XML Parsing Error: no root element foundper me nel browser
aliopi

3

Sì, puoi utilizzare @ResponseBody con il voidtipo restituito:

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

1
quindi quale sarà il tipo di ritorno .. è il codice di stato HTTP?
spandey,

@techBeginner In questo caso 200 (OK).
Lakatos Gyula,

2

Non c'è niente di sbagliato nel restituire un vuoto @ResponseBodye dovresti per POSTrichieste.

Utilizzare i codici di stato HTTP per definire gli errori all'interno delle routine del gestore delle eccezioni, mentre altri citano lo stato di successo. Un metodo normale che hai restituirà un codice di risposta 200che è quello che vuoi, qualsiasi gestore di eccezioni può quindi restituire un oggetto errore e un codice diverso (es 500.).


1

Ma man mano che il tuo sistema cresce di dimensioni e funzionalità ... penso che restituire sempre un json non sia affatto una cattiva idea. È più una questione architettonica / di "progettazione su larga scala".

Puoi pensare di ritirare sempre un JSON con due campi conosciuti: codice e dati. Dove code è un codice numerico che specifica l'esito positivo dell'operazione da eseguire e i dati sono tutti i dati aggiuntivi relativi all'operazione / servizio richiesto.

Dai, quando usiamo un back-end un fornitore di servizi, qualsiasi servizio può essere verificato per vedere se ha funzionato bene.

Quindi mi attengo, per non lasciare che Spring gestisca questo, esponendo le operazioni di ritorno ibrido (Alcuni dati di restituzione altro niente ...) .. instaurato assicurati che il tuo server esponga un'interfaccia più omogenea. È più semplice alla fine della giornata.


0

Ecco un esempio di codice che cosa ho fatto per un metodo asincrono

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

Non è necessario restituire nulla dal metodo in uso, tutto ciò che serve per utilizzare questa annotazione in modo che il metodo restituisca OK in ogni caso

@ResponseStatus(value = HttpStatus.OK)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.