How do I customize default error message from spring @Valid validation?

前端 未结 10 774
孤街浪徒
孤街浪徒 2020-12-22 23:04

DTO:

public class User {

    @NotNull
    private String name;

    @NotNull
    private String password;

    //..
}

Controller:

相关标签:
10条回答
  • 2020-12-22 23:32

    One way to do it is adding message in @NotNull annotation on entity properties. And adding @Valid annotation in controller request body.

    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*
    }
    
    0 讨论(0)
  • 2020-12-22 23:33

    For customized the error message in JSON format then do the below steps.

    - Create one @Component called CommonErrorHandler

    @Component
    public class CommonErrorHandler {
    public  Map<String,Object> getFieldErrorResponse(BindingResult result){
    
            Map<String, Object> fielderror = new HashMap<>();
            List<FieldError>errors= result.getFieldErrors();
            for (FieldError error : errors) {
                fielderror.put(error.getField(), error.getDefaultMessage());
            }return fielderror;
        }
    
         public ResponseEntity<Object> fieldErrorResponse(String message,Object fieldError){
            Map<String, Object> map = new HashMap<>();
            map.put("isSuccess", false);
            map.put("data", null);
            map.put("status", HttpStatus.BAD_REQUEST);
            map.put("message", message);
            map.put("timeStamp", DateUtils.getSysDate());
            map.put("filedError", fieldError);
            return new ResponseEntity<Object>(map,HttpStatus.BAD_REQUEST);
        }
    }
    

    -- Add InvalidException class

    public class InvalidDataException extends RuntimeException {
    
    /**
     * @author Ashok Parmar
     */
        private static final long serialVersionUID = -4164793146536667139L;
    
        private BindingResult result;
    
        public InvalidDataException(BindingResult result) {
            super();
            this.setResult(result);
        }
    
        public BindingResult getResult() {
            return result;
        }
    
        public void setResult(BindingResult result) {
            this.result = result;
        }
    
    }
    

    - Introduce @ControllerAdvice class

    @ControllerAdvice
    public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
    
    @ExceptionHandler(InvalidDataException.class)
        public ResponseEntity<?> invalidDataException(InvalidDataException ex, WebRequest request) {
    
            List<FieldError> errors = ex.getResult().getFieldErrors();
            for (FieldError error : errors) {
                logger.error("Filed Name ::: " + error.getField() + "Error Message :::" + error.getDefaultMessage());
            }
            return commonErrorHandler.fieldErrorResponse("Error", commonErrorHandler.getFieldErrorResponse(ex.getResult()));
        }
        }
    

    -- Use in controller with @Valid and throw exception

    public AnyBeans update(**@Valid** @RequestBody AnyBeans anyBeans ,
                BindingResult result) {
            AnyBeans resultStr = null;
            if (result.hasErrors()) {
                **throw new InvalidDataException(result);**
            } else {
                    resultStr = anyBeansService.(anyBeans );
                    return resultStr;
            }
        }
    

    -- Output will be in JSON format

    {
      "timeStamp": 1590500231932,
      "data": null,
      "message": "Error",
      "isSuccess": false,
      "status": "BAD_REQUEST",
      "filedError": {
        "name": "Name is mandatory"
      }
    }
    

    Hope this will be work. :-D

    0 讨论(0)
  • 2020-12-22 23:34

    You can do something like this

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
          protected ResponseEntity<Error> handleGlobalExceptions(MethodArgumentNotValidException ex,
              WebRequest request) {
            log.catching(ex);
            return new ResponseEntity<>(createErrorResp(HttpStatus.BAD_REQUEST,
                ex.getBindingResult().getFieldErrors().stream().map(err -> err.getDefaultMessage())
                    .collect(java.util.stream.Collectors.joining(", "))),
                HttpStatus.BAD_REQUEST);
          }
    
    0 讨论(0)
  • 2020-12-22 23:36
    {
      "message": "string",
      "errors": [
        {
          "field": "string",
          "message": "string",
          "error_code": "string"
        }
      ],
      "resource": "string",
      "description": "string"
    }
    
    0 讨论(0)
  • 2020-12-22 23:39

    Add some information too. If you use just @Valid, you need to catch BindException. If you use @Valid @RequestBody catch MethodArgumentNotValidException

    Some sources:
    HandlerMethodArgumentResolverComposite.getArgumentResolver(MethodParameter parameter):129 - search which HandlerMethodArgumentResolver support such parameter RequestResponseBodyMethodProcessor.supportsParameter(MethodParameter parameter) - return true if parameter has annotation @RequestBody

    RequestResponseBodyMethodProcessor:139 - throw MethodArgumentNotValidException ModelAttributeMethodProcessor:164 - throw BindException

    0 讨论(0)
  • 2020-12-22 23:44
    @ControllerAdvice(annotations = RestController.class)
    public class GlobalExceptionHandler implements ApplicationContextAware {
    
        @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseStatus(HttpStatus.OK)
        @ResponseBody
        public ApplicationError validationException(MethodArgumentNotValidException e) {
    
            e.printStackTrace();
            return new ApplicationError(SysMessageEnum.MSG_005, e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题