2016-07-28 31 views
1

我有一个Rest服务器与春季启动开发,我需要返回错误报告的属性格式错误(无效日期,无效整数的,无效的串,对象,而不是一个阵列,..)如何返回验证的错误bean与rest服务的无效属性列表与弹簧

的问题是,在所发送的JSON对象无效参数的情况下,我们必须用{字段,ERRORMSG}的列表返回一个对象

示例

{ 
    "message": "Invalid request parameters", 
    "properties_errors": [ 
    { 
     "property": "mail", 
     "cause": "Email format invalid" 
    }, 
    { 
     "property": "startDate", 
     "cause": "Date format invalid" 
    } 
    ] 
} 

在控制米勒,我标注的验证,给出参数的对象,与@Valid @RequestBody MyObj中的obj 之后,我foud两种解决方案:

  1. 自定义解串器

定义自定义解串器(com.fasterxml .jackson.databind.JsonDeserializer)将json对象的String或Object值转换为实体属性的所需类型 ,并使用@JsonDeserialize(使用= MyCustomDeserializer.class)对这些属性进行注释。

此解决方案的问题是,它在第​​一个错误时失败(只返回一个属性错误)。 Spring使用HttpMessageConverter HTTP请求体转换为实体对象,在我们的情况下,弹簧实现MappingJackson2HttpMessageConverter使用一个杰克逊Objectmapper,它采用了com.fasterxml.jackson.databind.deser .BeanDeserializer是与反序列化IOException异常的第一个错误之后失败将由中的MessageConverter HttpMessageNotReadableException

这种方法似乎更清洁的笼罩,但我不知道我们能不能redefi NE的ObjectMapper或BeanDeserializer失败,并包含所有的属性与问题

  1. DTO为实体

的第二解决方案是定义DTO对象在控制器中使用的根异常报告(而不是),其中所有属性都是Object类型的,在创建这个对象(让spring和jackson创建这个dto)之后,我们对这些属性进行验证(使用特定的javax.validation.ConstraintValidator来检查DTO Object类型的属性是instanceOf我们期望的类型)

该第二种解决方案提供了期望的最终结果,因为它使用了弹簧的API验证,该验证已经给出了MethodArgumentNotValidException。但是,将DTO的属性类型为Object进行验证并将其转换为业务层的正确模型非常难看,它不是通用的,...

是否有更好的解决方案或者我错过的方法对于这样的结果

回答

2

我还没有测试与您的情况下面,但我相信可以使用类似的解决方案。

使用@ControllerAdvice通过@ExceptionHandler处理异常(MethodArgumentNotValidException.class)。获取所有错误结果,然后返回包含验证错误的对象列表。下面的例子。

@ControllerAdvice 
public class ControllerValidationHandler { 
    @Autowired 
    private MessageSource msgSource; 

    @ExceptionHandler(MethodArgumentNotValidException.class) 
    @ResponseStatus(HttpStatus.BAD_REQUEST) 
    @ResponseBody 
    public ValidationMessages processValidationError(MethodArgumentNotValidException ex) { 
     BindingResult result = ex.getBindingResult(); 
     List<FieldError> fieldErrors = result.getFieldErrors(); 
     return new ValidationMessages(fieldErrors.stream() 
       .map(fieldError -> processFieldError(fieldError)) 
       .collect(Collectors.toList())); 
    } 

    private ValidationMessage processFieldError(FieldError error) { 
     ValidationMessage message = null; 
     if (error != null) { 
      Locale currentLocale = LocaleContextHolder.getLocale(); 
      String msg; 
      try { 
       msg = msgSource.getMessage(error.getDefaultMessage(), null, currentLocale); 
      } catch (Exception e) { 
       msg = error.getDefaultMessage(); 
      } 

      message = new ValidationMessage(error.getField(), msg, MessageType.ERROR); 
     } 
     return message; 
    } 
} 
+1

是的,当然,如果我们可以有所有无效字段的异常MethodArgumentNotValidException,这是清楚如何做出响应,但我的问题是如何得到这个异常 – Jugu