是否可以将@Valid与从JSON有效负载创建的@HashMap一起使用?

时间:2014-10-06 16:39:07

标签: java spring spring-mvc

我尝试在@Valid旁边使用 @RequestBody来验证我的有效负载是否具有给定参数。

我找到了使用绑定的解决方案,但这样做几乎就像在@RequestMapping方法中调用验证一样。当您有预期的有效负载时,我也找到了使用@Valid的方法。

我的有效负载是完全动态的,我只想验证字段的存在,例如id。我当前的处理程序是:

@RequestMapping(method = RequestMethod.POST, value="/path", consumes = "application/json")
    @ResponseBody
    @Valid
    public Object get(final HttpServletRequest request, @Valid @RequestBody HashMap payload ) {

由于我的有效负载是完全动态的,因此我创建了一个HashMap来保存它。如果我将@NotEmpty扩展到只是验证该属性是否存在的自定义类,我想知道是否可以使用HashMap或类似的注释。

我是否在正确的轨道上?这对动态有效载荷不可能吗?

提前致谢。

1 个答案:

答案 0 :(得分:3)

问题是肯定的,不是。

,您可以使用@Valid请求验证。

,您不能对属性使用简单的@NotEmpty,因为您需要为此目的定义DTO。

鉴于有效载荷是动态的,我能做的最好的事情是基于@EddieB tutorial link,它就是这样的。

与我在问题中的函数标题相同

    @RequestMapping(method = RequestMethod.POST, value="/path", consumes = "application/json")
    @ResponseBody
    public Object get(final HttpServletRequest request, @Valid @RequestBody HashMap payload ) {

但由于有效负载是动态的,在本例中是HashMap,因此需要进行某种自定义验证。我找到的最简洁的方法是使用@InitBinder注释将Validator附加到@Valid 请求

   // instantiated in the constructor
    private final MyValidator myValidator

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(this.myValidator);
    }

然后是我们的自定义验证器:

public class MyValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return HashMap.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
       // do your custom validation.
       // if you don't call error.reject* it is considered a valid argument
    }

如果您确实抛出了错误,则可以通过创建@ControllerAdvice来捕获它。在我的情况下,我明确地将@ResponseStatus设置为BAD_REQUEST,就像它到达这里一样,它肯定是由一个糟糕的有效载荷引起的:

@ControllerAdvice
public class MyHandler{

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public String processValidationError(MethodArgumentNotValidException exception) {
        // custom error handling
    }
}

感谢两位成员的评论让我得到了这个答案。