2012-02-18 10 views
6

Ho un metodo di azione definita come questo in uno dei miei controllori:Come restituire lo stato di errore e gli errori di convalida da questo controller Spring MVC?

@RequestMapping(method = RequestMethod.POST) 
public @ResponseBody Post create(@Valid Post post, BindingResult bindingResult) { 
    if (bindingResult.hasErrors()) { 
     // how to return an error status + error messages from here? 
    } else { 
     postRepository.persist(post); 
     return post; 
    } 
} 

Quando il messaggio viene mantenuto con successo, ho tornare il palo al client. Ma quando ha errori di convalida, voglio restituire un codice di stato di errore e tutti i messaggi di errore di convalida al client.

Qual è il modo migliore per farlo?

+0

Stai progettando API o gestione modulo? –

+0

Sto progettando un'API REST. –

risposta

7

Sine si sta Desigining un API REST, è necessario creare il proprio Pojo (aka. Resource) che rappresenterà gli errori di comportamento o di convalida dispari, come affermato da horaceman. Ti mostrerò come lo facciamo nella nostra applicazione.

Poiché utilizziamo JSON come rappresentazione di dati, desideriamo ricevere le seguenti informazioni se si verificano eccezioni impreviste.

{ "status" : "EXCEPTION", "exceptionName" : "MyCustomException", "exceptionMsg" : "ex.unsupportedOperation" } 

Questo è un esempio ovviamente. Una buona soluzione è che possiamo trattare exceptionMsg come chiave nel nostro frontend per visualizzare il messaggio corretto i18n o visualizzarlo all'utente così com'è (in questo caso usiamo messaggi più descrittivi).

Ora, quando tutto va bene facciamo qualcosa di simile:

{ "status" : "OK", "data" : {(...)} } 

Data elemento è opzionale. Possiamo inviare qualsiasi cosa di cui abbiamo bisogno per notificare il frontend, o saltarlo completamente.

L'ultimo scenario sarebbe tuo - errori di convalida. In questo caso trasmettiamo solitamente seguente contenuto:

{ "status" : "VALIDATION_FAILED", "errors" : [ "fieldName" : "username", "errorCode" : "validation.requiredField", "errorMsg" : "Username is required."] } 

così chiaramente client API riceveranno informazioni che la validazione ha fallito e nei campi appropriati - dettagli esatti su cosa è andato storto. Ovviamente errors è un array (o List), quindi forniamo sempre tutti i dettagli necessari.

Come faccio? Facile, questi oggetti sono semplici POJOS che vengono tradotti in JSON usando Jackson. Questo mi dà possibilità illimitate di rappresentazione JSON. Quello che faccio è che sto preparando POJO che rappresenta gli errori di convalida (ad esempio) e lo aggiungo come alla mia istanza ModelAndView. Quindi mi baso su Spring per fare il corretto marshalling JSON.

Nel tuo caso hai l'annotazione @ResponseBody con l'istanza Post, quindi per quanto ne so non potrai farlo. Il tuo setup sta dicendo "Beh, non importa cosa succede, restituisci sempre un'istanza di Post". Quello che dovresti fare è sostituirlo con il semplice ModelAndView, fornirlo con il corretto Model in base alla convalida e restituirlo all'API del client.

+0

Grazie! 1k raggiunto: D –

3

penso che vogliate effettuare una chiamata ajax nel controller. si restituisce un oggetto post nel metodo, quindi è impossibile restituire un altro oggetto (come un messaggio di errore con il codice). che ne dici di restituire un ExecutionResult?

ExecutionResult{ 
private int statusCode; 
private String message; 
private Object yourPost; 
//get and set methods here... 
} 
3

Per @ResponseBody rimuovere BindigResult dalla firma del metodo e consentire il rilascio di BindException.Vorrei quindi utilizzare un metodo @ExceptionHandler per restituire un oggetto che contiene gli errori come descritto da Likacz.

@RequestMapping(method = RequestMethod.POST) 
public @ResponseBody Post create(@Valid Post post) { 
    postRepository.persist(post); 
    return post; 
} 

@ExceptionHandler 
public ValidationErrors handleException(BindException ex) { 
    // ... 
} 
+0

Si noti che se si desidera restituire 'ValidationErrors' nel corpo della risposta, il metodo' handleException' avrà bisogno di '@ ResponseBody'. – CorayThan

Problemi correlati