2015-11-12 14 views
12

DTO:Come personalizzare il messaggio di errore predefinito da primavera @Valida valida?

public class User { 

    @NotNull 
    private String name; 

    @NotNull 
    private String password; 

    //.. 
} 

Controller:

@RequestMapping(value = "/user", method = RequestMethod.POST) 
public ResponseEntity<String> saveUser(@Valid @RequestBody User user) { 
    //.. 
    return new ResponseEntity<>(HttpStatus.OK); 
} 

default errore JSON:

{"timestamp":1417379464584,"status":400,"error":"Bad Request","exception":"org.springframework.web.bind.MethodArgumentNotValidException","message":"Validation failed for argument at index 0 in method: public org.springframework.http.ResponseEntity<demo.User> demo.UserController.saveUser(demo.User), with 2 error(s): [Field error in object 'user' on field 'name': rejected value [null]; codes [NotNull.user.name,NotNull.name,NotNull.java.lang.String,NotNull]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.name,name]; arguments []; default message [name]]; default message [may not be null]],"path":"/user"} 

Vorrei avere il mio JSON personalizzata per ogni errore. Come lo realizzo?

risposta

5

È possibile eseguire la convalida con l'oggetto Errors/BindingResult. Aggiungi argomenti Errori al tuo metodo di controllo e personalizza il messaggio di errore quando vengono trovati errori.

Di seguito è riportato l'esempio di esempio, errors.hasErrors() restituisce true quando la convalida non è riuscita.

@RequestMapping(value = "/user", method = RequestMethod.POST) 
@ResponseBody 
public ResponseEntity<String> saveUser(@Valid @RequestBody User user, Errors errors) { 
    if (errors.hasErrors()) { 
     return new ResponseEntity(new ApiErrors(errors), HttpStatus.BAD_REQUEST); 
    } 
    return new ResponseEntity<>(HttpStatus.OK); 
} 
+0

@ksaughs Qual è la classe ApiErrors? – user6123723

+0

org.springframework.validation.Errors dal jar del contesto di primavera – kswaughs

+0

@kswaughs, ho cercato ApiErrors ovunque e non sono riuscito a trovarlo da nessuna parte. Ho anche incluso la dipendenza del contesto primaverile in Maven e non ho trovato nulla. Gli unici risultati web sono in questa pagina StackOverflow in cui la menzioni nella tua risposta. Potresti aiutare? – user238607

14

Se si vuole il pieno controllo del messaggio di risposta in ogni controller di scrivere la ControllerAdvice. Ad esempio, che ad esempio trasformare MethodArgumentNotValidException in un oggetto JSON personalizzato:

import org.springframework.core.Ordered; 
import org.springframework.core.annotation.Order; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.MethodArgumentNotValidException; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.ExceptionHandler; 
import org.springframework.web.bind.annotation.ResponseBody; 
import org.springframework.web.bind.annotation.ResponseStatus; 

import java.util.ArrayList; 
import java.util.List; 

import static org.springframework.http.HttpStatus.BAD_REQUEST; 

/** 
* Kudos http://www.petrikainulainen.net/programming/spring-framework/spring-from-the-trenches-adding-validation-to-a-rest-api/ 
* 
*/ 
@Order(Ordered.HIGHEST_PRECEDENCE) 
@ControllerAdvice 
public class MethodArgumentNotValidExceptionHandler { 

    @ResponseStatus(BAD_REQUEST) 
    @ResponseBody 
    @ExceptionHandler(MethodArgumentNotValidException.class) 
    public Error methodArgumentNotValidException(MethodArgumentNotValidException ex) { 
     BindingResult result = ex.getBindingResult(); 
     List<org.springframework.validation.FieldError> fieldErrors = result.getFieldErrors(); 
     return processFieldErrors(fieldErrors); 
    } 

    private Error processFieldErrors(List<org.springframework.validation.FieldError> fieldErrors) { 
     Error error = new Error(BAD_REQUEST.value(), "validation error"); 
     for (org.springframework.validation.FieldError fieldError: fieldErrors) { 
      error.addFieldError(fieldError.getField(), fieldError.getDefaultMessage()); 
     } 
     return error; 
    } 

    static class Error { 
     private final int status; 
     private final String message; 
     private List<FieldError> fieldErrors = new ArrayList<>(); 

     Error(int status, String message) { 
      this.status = status; 
      this.message = message; 
     } 

     public int getStatus() { 
      return status; 
     } 

     public String getMessage() { 
      return message; 
     } 

     public void addFieldError(String path, String message) { 
      FieldError error = new FieldError(path, message); 
      fieldErrors.add(error); 
     } 

     public List<FieldError> getFieldErrors() { 
      return fieldErrors; 
     } 
    } 
} 
4

So che questo è una specie di vecchia questione,

Ma ho appena correre in esso e ho trovato un po 'di buon article che ha anche un esempio perfetto in github.

In pratica utilizza @ControllerAdvice come suggerisce la documentazione di Spring.

Così, per esempio la cattura di 400 errore sarà raggiunto eseguendo l'override una funzione:

@ControllerAdvice 
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler { 

    @Override 
    protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) { 
     logger.info(ex.getClass().getName()); 
     // 
     final List<String> errors = new ArrayList<String>(); 
     for (final FieldError error : ex.getBindingResult().getFieldErrors()) { 
      errors.add(error.getField() + ": " + error.getDefaultMessage()); 
     } 
     for (final ObjectError error : ex.getBindingResult().getGlobalErrors()) { 
      errors.add(error.getObjectName() + ": " + error.getDefaultMessage()); 
     } 
     final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, ex.getLocalizedMessage(), errors); 
     return handleExceptionInternal(ex, apiError, headers, apiError.getStatus(), request); 
    } 
} 

(classe ApiError è un oggetto semplice per contenere lo stato, messaggi, gli errori)

2

Un modo per farlo è aggiunta di un messaggio nell'annotazione @NotNull.

DTO:

public class User { 

    @NotNull(message = "User name cannot be empty") 
    private String name; 

    @NotNull(message = "Password cannot be empty") 
    private String password; 

    //.. 
} 

Controller:

@RequestMapping(value = "/user", method = RequestMethod.POST) 
public ResponseEntity<String> saveUser(@Valid @RequestBody User user) { 
    //.. 
    return new ResponseEntity<>(HttpStatus.OK); 
} 
// Add one 
@ExceptionHandler(MethodArgumentNotValidException.class) 
public ResponseEntity<List<YourErrorResponse>> handleException(MethodArgumentNotValidException ex) { 
// Loop through FieldErrors in ex.getBindingResult(); 
// return *YourErrorReponse* filled using *fieldErrors* 
} 
Problemi correlati