我在 REST 服务中使用 SpringBoot (spring-boot-starter-web 1.5.16.RELEASE) 和 hibernate-validator 6.0.11.Final。
使用正确的验证约束注释的 DTO 对象(更新:我在控制器的参数上使用 @Valid 注释)并且验证按预期工作。
我希望将所有验证错误(发送到客户端)记录在日志文件中。
我认为应该有一些简单的方法来启用此类消息(例如应用程序属性中的标志),但我在任何地方都找不到它。
如有任何建议,我们将不胜感激。
事实证明,
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 日志不会在那里静音。
更新: 在这种情况下,您可以在控制器方法中使用在
BindingResult
bean 声明之后定义的 @Valid
对象,例如
@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
旧答案: 如果您正在验证像
这样的beanSet<ConstraintViolation<POJO>> violations = validator.validate(pojo);
然后您可以迭代违规行为并记录它们,例如
for (ConstraintViolation<POJO> violation : violations) {
log.error(violation.getMessage());
}
您必须使用 @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);
}
}