2015-11-12 106 views
12

DTO:如何自定義Spring @Valid驗證的默認錯誤消息?

public class User { 

    @NotNull 
    private String name; 

    @NotNull 
    private String password; 

    //.. 
} 

控制器:

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

默認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"} 

我想有我自定義的JSON爲每個錯誤發生。我如何實現這一目標?

回答

5

您可以使用Errors/BindingResult對象執行驗證。 將錯誤參數添加到您的控制器方法中,並在發現錯誤時自定義錯誤消息。

下面是示例示例,errors.hasErrors()在驗證失敗時返回true。

@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什麼的ApiErrors類? – user6123723

+0

org.springframework.validation.Errors from spring-context jar – kswaughs

+0

@kswaughs,我搜索了各處的ApiErrors,並且無法在任何地方找到它。我還在maven中包含了spring-context依賴,並且找不到任何東西。唯一的網頁結果是在你的答案中提到它的這個計算器頁面。你能幫忙嗎? – user238607

14

如果你想在每一個控制器的響應消息完全控制寫ControllerAdvice。例如,例如變換MethodArgumentNotValidException到自定義JSON對象:

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

我知道這是一種古老的問題,

但我正好碰上它,我發現了一些不錯的article這也一在github完美的例子。

基本上它使用了@ControllerAdvice,正如Spring文檔所建議的。

@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中類是一個簡單的對象來保存狀態,消息,錯誤)

2

一種方式來做到這一點是:

因此,例如捕捉400錯誤將通過重寫一個函數來實現在@NotNull註釋中添加消息。

DTO:

public class User { 

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

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

    //.. 
} 

控制器:

@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* 
} 
相關問題