春季 MVC - 在 REST 服务中的豆类列表中@Valid

2022-09-01 03:00:40

在Spring MVC REST服务(json)中,我有一个这样的控制器方法:

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public List<...> myMethod(@Valid @RequestBody List<MyBean> request, BindingResult bindingResult) {

其中 MyBean 类具有 Bean 验证批注。

在这种情况下,验证似乎没有发生,尽管它适用于其他控制器。

我不想将列表封装在dto中,这会改变json输入。

为什么没有对豆类列表进行验证?有哪些替代方案?



答案 1

@Valid是 JSR-303 注释,JSR-303 适用于 JavaBeans 上的验证。A 不是 JavaBean(根据 JavaBean 的官方描述),因此不能使用符合 JSR-303 的验证器直接对其进行验证。这得到了两个观察结果的支持。java.util.List

JSR-303 规范的第 3.1.3 节规定:

除了支持实例验证外,还支持对象图形的验证。图形验证的结果作为一组统一的约束冲突返回。考虑以下情况:Bean X 包含类型为 Y 的字段。通过使用@Valid注释对字段 Y 进行批注,验证程序将在验证 X 时验证 Y(及其属性)。在 Y 类型(子类、实现)声明的字段中包含的值的确切类型 Z 是在运行时确定的。使用 Z 的约束定义。这可确保标记为@Valid的关联具有正确的多态行为。

集合值、数组值和通常可迭代的字段和属性也可以使用@Valid注释进行修饰。这将导致验证迭代器的内容。支持任何实现java.lang.Iterable的对象。

我以粗体标记了重要的信息。本节意味着,为了验证集合类型,必须将其封装在 Bean 中(由 );此外,集合不能直接验证(由 暗示,重点是字段和属性)。Consider the situation where bean X contains a field of type YCollection-valued, array-valued and generally Iterable fields and properties may also be decorated

实际的 JSR-303 实现

我有一个示例应用程序,它使用Hibernate Validator和Apache Beans Validator测试集合验证。如果以(使用休眠验证程序)和(对于 Bean Validator)对此示例运行测试,则两者都拒绝直接验证集合,这似乎符合规范。由于 Hibernate Validator 是 JSR-303 的参考实现,因此此示例进一步证明了集合需要封装在 Bean 中才能进行验证。mvn clean test -Phibernatemvn clean test -Papache


清除了这一点后,我会说尝试以问题中所示的方式将集合直接传递给控制器方法也存在设计问题。即使验证直接在集合上工作,控制器方法也无法使用备用数据表示形式,例如自定义XML,SOAP,ATOM,EDI,Google协议缓冲区等,这些表示形式不会直接映射到集合。为了支持这些表示形式,控制器必须接受并返回对象实例。这需要以任何方式将集合封装在对象实例中。因此,非常建议像其他答案所建议的那样将另一个对象包裹在另一个对象内部。List


答案 2

我能找到的唯一方法是包装列表,这也意味着JSON输入必须更改

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public List<...> myMethod(@Valid @RequestBody List<MyBean> request, BindingResult bindingResult) {

成为:

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public List<...> myMethod(@Valid @RequestBody MyBeanList request, BindingResult bindingResult) {

我们还需要:

import javax.validation.Valid;
import java.util.List;

public class MyBeanList {

    @Valid
    List<MyBean> list;

    //getters and setters....
}

这看起来也可以通过列表的自定义验证器来实现,但我还没有走得那么远。

@Valid注释是标准 JSR-303 Bean 验证 API 的一部分,不是特定于 Spring 的构造。Spring MVC 将在绑定后验证@Valid对象,只要配置了适当的验证程序。

参考资料 : http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html