@NotNull注释不适用于模型对象列表

时间:2018-07-17 16:54:56

标签: java notnull

我正在尝试在Model类中的某些属性上使用@NotNull注释,当我通过单个对象执行POST调用而不是进行POST调用时,它可以工作List个对象

型号:DefaultModel.class

@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@ToString
public class DefaultModel {

@NotNull
private String name;
@NotNull
private Integer id;

}

控制器:HelloWorldController.java

@RequestMapping(value="/default", method=RequestMethod.POST)
public List<DefaultModel> m1(@RequestBody() @Valid List<DefaultModel> model) {
    System.out.println(model);
    return model;
}

List个对象的输入有效载荷

[       
{
"name":null,
"id":1
},
{
"name":null,
"id":""
},
{
"name":"",
"id":1
}
]

输出:

[DefaultModel(name=null, id=1), DefaultModel(name=null, id=null), DefaultModel(name=, id=1)]

我知道我们可以通过这种方式设置默认错误消息@NotNull(message="defaultmessage")

它还会引发MethodArgumentNotValidException异常,我们可以采用以下方式处理

@ExceptionHandler(MethodArgumentNotValidException.class)
public List<String> handleValidationExceptions(MethodArgumentNotValidException ex)

我的问题是,是否仍然存在,以便我们可以覆盖方法并设置此默认值?并且如果List中的某些对象属性为null(在我的情况下正是)该怎么办,它将终止于中间还是忽略该对象?

1 个答案:

答案 0 :(得分:0)

实际上,默认情况下,验证不适用于值得列表元素。

但是您可以为集合编写一个自定义验证器,并将其绑定到控制器的数据绑定器中。

@Controller
public class MyController {

    private final LocalValidatorFactoryBean validator;

    @Autowired
    public MyController(LocalValidatorFactoryBean validator) {
        this.validator = validator;
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(new CollectionValidator(validator));
    }
}


class CollectionValidator implements Validator {

    private final Validator validator;

    CollectionValidator(LocalValidatorFactoryBean validatorFactory) {
        this.validator = validatorFactory;
    }

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

    @Override
    public void validate(Object object, Errors errors) {
        Collection collection = (Collection) object;
        for (Object collectionValue : collection) {
            ValidationUtils.invokeValidator(validator, collectionValue, errors);
        }
    }
}

或者您可以在带注释的@ControllerAdvice类中进行相同的绑定,这将导致该绑定对所有控制器都可用。

已更新 控制器建议将是相同的逻辑,只是带有不同注释的类:

@ControllerAdvice
public class MyControllerAdvice {

    private final LocalValidatorFactoryBean validator;

    @Autowired
    public MyController(LocalValidatorFactoryBean validator) {
        this.validator = validator;
     }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.addValidators(new CollectionValidator(validator));
    }
}