如何以编程方式调用在 Spring 中使用 @Valid 参数的 @RequestMethod 方法上运行的同一验证程序?

我有一个类,在某些字段(如和,等)上有hibernate的验证注释。@NotNull@Size(min = 4, max = 50)

public class MyClass {

    Long id;

    @NotEmpty
    @Size(min = 4, max = 50)
    String machineName;

    @NotEmpty
    @Size(min = 4, max = 50)
    String humanName;

    // Getters, setters, etc…
}

我还有一个充当 JSON API 的自定义控制器,以及一个在调用 API 方法时创建 MyClass 对象的 JSON 反序列化程序。在我的自定义控制器中,我有一个方法来创建该类型的新对象:

@RequestMapping(method = RequestMethod.POST)
public long createMyObject(@RequestBody @Valid MyClass newObj) {
    // Create the object in the database
    return newObj.getId();
}

和另一个更新现有对象的方法

@RequestMapping(method = RequestMethod.PUT)
public void updateMyObject(@RequestBody MyClass updatedObj) {
    MyClass existingObj = // Get existing obj from DB by updatedObj.getId();

    // Do some secondary validation, such as making sure that a specific
    // field remains unchanged compared to the existing instance
    if (existingObj.getMachineName() != null && 
            !existingObj.getMachineName().equals(updatedObj.getMachineName())) {
        throw new CannotChangeMachineNameException();
    }
    else {
        updatedObj.setMachineName(existingObj.getMachineName());
    }

    // [HERE IS WHERE I WANT THE MAGIC TO HAPPEN]

    // Save updatedObj to the database
}

虽然我可以在 中使用,但我不能在其中使用它,因为我们的 API 实现要求 machineName 保持不变 - 用户可以使用 JSON 对象调用 API,该对象要么完全排除 machineName,要么使用数据库中存在的相同值填充它。@ValidcreateMyObjectupdateMyObject

在将更新后的对象保存到数据库之前,我想调用具有@Valid注释将导致调用的同一验证程序。如何找到此验证器并使用它?


答案 1

没有什么说你只需要在控制器方法中使用@Valid。为什么不创建一个验证方法,接受您注释为@Valid的参数,然后只返回相同的参数。

喜欢这个:

public Book validateBook(@Valid Book book) {
   return book;
}

看起来另一种选择是使用Hibernate的验证包。这是文档

基本上,您从 a 中获取 a,然后像这样使用验证器:ValidatorValidationFactory

 @Test
    public void manufacturerIsNull() {
        Car car = new Car(null, "DD-AB-123", 4);

        Set<ConstraintViolation<Car>> constraintViolations =
            validator.validate(car);

        assertEquals(1, constraintViolations.size());
        assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
}

答案 2

推荐