【问题标题】:spring mvc process object before @valid is applied应用@valid之前的spring mvc进程对象
【发布时间】:2013-01-21 20:37:38
【问题描述】:

我有一个如下所示的 spring mvc 控制器

@RequestMapping(value="/new", method=RequestMethod.POST)
public String createBooking(@Valid Booking booking, BindingResult bindingResult, Model model, Principal principal)
{
    if(bindingResult.hasErrors()) {
        return "booking/edit";
    }
    //Store Booking in db...
    ...

问题是我从 POST 获得的 Booking 对象是由 Spring 构造的,但无法填充验证器所需的属性之一,因为该属性不存在于表单中。所以我的问题是我有没有办法在预订被@Valid 标签处理程序处理以添加这个必需的属性之前拦截它?

干杯! NFV

【问题讨论】:

标签: spring bean-validation hibernate-validator


【解决方案1】:

@Valid触发前修改模型属性对象有两种方式:

  1. 删除@Valid并自动连接验证器并手动触发验证器:
class MyController {

  private final Validator validator;

  class MyController(Validator validator) {
    this.validator = validator;
  }

  @PostMapping("/new")
  public String createBooking(Booking booking, BindingResult bindingResult, Model model, Principal principal) {
    // edit booking here

    validator.validate(booking, result)

    // original method body here
  }
}

  1. 装饰默认验证器并在装饰验证器内预处理booking 对象。
class MyController {

  @InitBinder
  public void initBinder(WebDataBinder binder) {
      binder.setValidator(new PreProcessBookingValidator(binder.getValidator()));
  }

  @PostMapping("/new")
  public String createBooking(@Valid Booking booking, BindingResult bindingResult, Model model, Principal principal) {
    ...
  }

  private static class PreProcessBookingValidator implements Validator {
        private final Validator validator;

        public PreProcessBookingValidator(Validator validator) {
            this.validator = validator;
        }

        @Override
        public boolean supports(@Nonnull Class<?> clazz) {
            return validator.supports(clazz);
        }

        @Override
        public void validate(@Nonnull Object target, @Nonnull Errors errors) {
            if (target instanceof Booking) {
                Booking booking = (Booking) target;
                // manipulate booking here

            }

            validator.validate(target, errors);
        }
    }

}

(第二个提示是我从https://github.com/spring-projects/spring-framework/issues/11103 那里得到的)

【讨论】:

    【解决方案2】:

    我不确定我是否理解这个问题,但听起来你想在你的命令被表单提交绑定之前将命令对象中的一个字段设置为一个值。如果是这样,您可以在控制器中添加一个方法,如下所示...

    @ModelAttribute
    public Booking getBooking() {
        Booking booking = new Booking();
        booking.setMyRequiredProperty("some value");
        return booking;
    }
    

    希望有帮助

    【讨论】:

    • 这是正确的,但我认为 nfvindaloo 想在应用标准验证之前预处理从表单提交的 bean (@Valid)。应用自定义验证器很容易,但不是标准验证器。也许这是一个答案 - stackoverflow.com/questions/18049204/… .
    • 不,这不是一个答案——首先执行方法上的@ModelAttribute,然后执行参数@ModelAttribute,从表单填充bean,我们被困住了——阅读这个stackoverflow.com/questions/25011568/…。所以我不知道如何在@Valid之前预处理类。
    猜你喜欢
    • 2014-05-06
    • 1970-01-01
    • 2020-10-30
    • 1970-01-01
    • 1970-01-01
    • 2021-03-02
    • 2011-11-19
    • 2011-06-29
    • 1970-01-01
    相关资源
    最近更新 更多