2015-11-12 7 views
12

DTO:Wie kann ich die Standardfehlermeldung aus der spring @ Valid Validierung anpassen?

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); 
} 

Standard json Fehler:

{"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"} 

Ich mag würde meine Gewohnheit json haben für jeden Fehler ist aufgetreten. Wie erreiche ich das?

Antwort

5

Sie können die Validierung mit dem Objekt Errors/BindingResult durchführen. Fügen Sie der Controller-Methode das Argument Fehler hinzu und passen Sie die Fehlermeldung an, wenn Fehler gefunden wurden.

Unten ist das Beispielbeispiel errors.hasErrors() gibt true zurück, wenn die Validierung fehlgeschlagen ist.

@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 Was die ApiErrors Klasse ist? – user6123723

+0

org.springframework.validation.Errors aus Frühling-Kontext-Glas – kswaughs

+0

@kswaughs, suchte ich nach ApiErrors überall und konnte es nirgendwo finden. Ich habe auch die Abhängigkeit vom Frühjahrskontext in Maven aufgenommen und konnte nichts finden. Die einzigen Web-Ergebnisse sind auf dieser Stackoverflow-Seite, wo Sie es in Ihrer Antwort erwähnen. Könntest du helfen? – user238607

14

Wenn Sie die volle Kontrolle über die Antwortnachricht in jedem Controller wollen schreiben einen ControllerAdvice. Zum Beispiel, dass Beispiel MethodArgumentNotValidException in einem benutzerdefinierten JSON-Objekt verwandeln:

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

Ich weiß, diese Art der alten Frage,

Aber ich laufe einfach hinein und fand ich ein paar ziemlich gute article die auch eine hat perfektes Beispiel in github.

Im Grunde verwendet es @ControllerAdvice wie Frühjahr Dokumentation schlägt.

So zum Beispiel fangen 400 Fehler durch Überschreiben einer Funktion erreicht werden:

@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); 
    } 
} 

(ApiError Klasse ist eine einfache Objektstatus zu halten, Nachricht, Fehler)

2

Eine Möglichkeit, es zu tun ist, Hinzufügen einer Nachricht in Annotation @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* 
} 
Verwandte Themen