如何在 Spring 引导应用程序中记录验证错误

How to log validation errors in Spring boot application

我在我的 REST 服务中使用 SpringBoot(spring-boot-starter-web 1.5.16.RELEASE)和 hibernate-validator 6.0.11.Final。

用适当的验证约束注释的 DTO 对象(更新:我在控制器的参数上使用 @Valid 注释)并且验证按预期工作。

我希望将所有验证错误(发送给客户端的错误)记录在日志文件中。

我想应该有一些简单的方法来启用这种消息(例如应用程序属性中的标志),但我在任何地方都找不到它。

如有任何建议,我们将不胜感激。

更新: 在这种情况下,您可以在控制器方法中使用 @Valid bean 声明之后定义的 BindingResult 对象,例如

@RequestMapping(value = "/foo")
public String foo(@Valid POJO object, BindingResult result) {
   List<FieldError> errors = result.getFieldErrors();
   for (FieldError error : errors ) {
     log.error(error.getDefaultMessage());
   } 
}

或者您最好使用 @ExceptionHandler 作为异常类型 MethodArgumentNotValidException


旧答案: 如果您正在验证像

这样的 beans
Set<ConstraintViolation<POJO>> violations = validator.validate(pojo);

然后你可以迭代违规并记录它们,比如

for (ConstraintViolation<POJO> violation : violations) {
   log.error(violation.getMessage()); 
}

复制自:https://www.baeldung.com/javax-validation

您必须使用@ControllerAdvice 定义全局异常处理程序以捕获所有与 JSR 303 相关的错误。 甚至您在这里为自己的业务异常定义异常处理程序并根据需要记录它们。

 @ControllerAdvice
    class ApiException{
     @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ResponseBody
        public ValidationErrorDTO processValidationError(MethodArgumentNotValidException ex) {
            BindingResult result = ex.getBindingResult();
            List<FieldError> fieldErrors = result.getFieldErrors();

          //log errors here

            return processFieldErrors(fieldErrors);
        }

      private ValidationErrorDTO processFieldErrors(List<FieldError> fieldErrors) {
            ValidationErrorDTO dto = new ValidationErrorDTO();

            for (FieldError fieldError: fieldErrors) {
                String localizedErrorMessage = resolveLocalizedErrorMessage(fieldError);
                dto.addFieldError(fieldError.getField(), localizedErrorMessage);
            }

            return dto;
        }

    }

    public class ValidationErrorDTO {

        private List<FieldErrorDTO> fieldErrors = new ArrayList<>();

        public ValidationErrorDTO() {

        }

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

    }

事实证明 org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver 默认情况下会记录验证错误(这正是我所需要的),例如

2018-10-18 12:54:25.552  WARN 22760 --- [nio-8092-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for 

我没有看到这些消息的原因是在日志聚合工具过滤器中(即我没有在 Kibana 中看到消息,但它们出现在本地机器上)。

对于那些不会在本地看到消息的人 - 检查日志记录配置并确保 Spring 日志在那里没有被静音。