61

我正在使用 Hibernate 和 Spring Annotations 进行很多验证,如下所示:

public class Account {
    @NotEmpty(groups = {Step1.class, Step2.class})
    private String name;

    @NotNull(groups = {Step2.class})
    private Long accountNumber;

    public interface Step1{}
    public interface Step2{}
}

然后在控制器中在参数中调用它:

public String saveAccount(@ModelAttribute @Validated({Account.Step1.class}) Account account, BindingResult result) {
   //some more code and stuff here
   return "";
}

但我想根据控制器方法中的一些逻辑来决定使用的组。有没有办法手动调用验证?像result = account.validate(Account.Step1.class)什么?

我知道创建自己的 Validator 类,但这是我想避免的,我宁愿只使用类变量本身的注释。

4

7 回答 7

64

Spring 提供了LocalValidatorFactoryBean,它实现了 SpringSmartValidator接口以及 Java Bean ValidationValidator接口。

// org.springframework.validation.SmartValidator - implemented by LocalValidatorFactoryBean
@Autowired
SmartValidator validator;

public String saveAccount(@ModelAttribute Account account, BindingResult result) {
    // ... custom logic
    validator.validate(account, result, Account.Step1.class);
    if (result.hasErrors()) {
        // ... on binding or validation errors
    } else {
        // ... on no errors
    }
    return "";
}
于 2013-10-04T21:38:15.190 回答
39

这是来自JSR 303 规范的代码示例

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

Driver driver = new Driver();
driver.setAge(16);
Car porsche = new Car();
driver.setCar(porsche);


Set<ConstraintViolation<Driver>> violations = validator.validate( driver );

所以是的,您可以从验证器工厂获取验证器实例并自己运行验证,然后检查是否存在违规行为。您可以在Validator 的 javadoc 中看到,它还将接受一组要验证的组。

显然,这直接使用 JSR-303 验证,而不是通过 Spring 验证,但我相信如果在类路径中找到 Spring 验证注释将使用 JSR-303

于 2013-10-04T21:10:36.473 回答
16

如果您已正确配置所有内容,则可以执行以下操作:

@Autowired
Validator validator;

然后你可以用它来验证你的对象。

于 2013-10-04T21:25:57.963 回答
7

这个链接给出了在 Spring 应用程序中使用验证的很好的例子。 https://reflectoring.io/bean-validation-with-spring-boot/

我在本文中找到了一个以编程方式运行验证的示例。

class MyValidatingService {

  void validatePerson(Person person) {
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<Person>> violations = validator.validate(person);
    if (!violations.isEmpty()) {
      throw new ConstraintViolationException(violations);
    }
  } 
}

它会抛出500状态,因此建议使用自定义异常处理程序来处理它。

@ControllerAdvice(annotations = RestController.class)
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<CustomErrorResponse> constraintViolationException(HttpServletResponse response, Exception ex) throws IOException {
        CustomErrorResponse errorResponse = new CustomErrorResponse();
        errorResponse.setTimestamp(LocalDateTime.now());
        errorResponse.setStatus(HttpStatus.BAD_REQUEST.value());
        errorResponse.setError(HttpStatus.BAD_REQUEST.getReasonPhrase());
        errorResponse.setMessage(ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
    }
}

第二个例子来自https://www.mkyong.com/spring-boot/spring-rest-error-handling-example/

更新:不推荐使用验证是持久层: https ://twitter.com/odrotbohm/status/1055015506326052865

于 2019-12-12T19:25:01.067 回答
6

除了@digitaljoel 的回答之外,一旦您获得了一组违规行为,您就可以抛出 ConstraintViolationException。

Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
        Set<ConstraintViolation<NotionalProviderPaymentDTO>> violations = validator.validate( notionalProviderPaymentDTO );

        if(!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }

您可以创建自己的异常映射器来处理 ConstraintViolationException 并将错误消息发送到客户端。

于 2019-09-25T12:12:27.880 回答
1

并且:

@Autowired
@Qualifier("mvcValidator")
Validator validator;

...
violations = validator.validate(account);
于 2016-11-21T14:29:08.613 回答
0
import javax.validation.Validator;
import javax.validation.ConstraintViolation;

public class{
    @Autowired
    private Validator validator;
       .
       .
    public void validateEmployee(Employee employee){

        Set<ConstraintViolation<Employee>> violations = validator.validate(employee);
        if(!violations.isEmpty()) {
            throw new ConstraintViolationException(violations);
        }
    }
}

在这里,'Employee' 是一个 pojo 类,'employee' 是它的对象

于 2021-02-03T22:26:50.410 回答