添加使用initBinder多重校验(Adding multiple validators usin

2019-07-18 18:13发布

我添加使用用户验证initBinder方法:

@InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator(new UserValidator());
    }

这里是UserValidator

public class UserValidator implements Validator {

    public boolean supports(Class clazz) {
        return User.class.equals(clazz);
    }

    public void validate(Object target, Errors errors) {
        User u = (User) target;

        // more code here
    }
}

validate方法控制器方法调用中得到正确调用。

@RequestMapping(value = "/makePayment", method = RequestMethod.POST)
public String saveUserInformation(@Valid User user, BindingResult result, Model model){

    // saving User here

    // Preparing CustomerPayment object for the payment page.
    CustomerPayment customerPayment = new CustomerPayment();
    customerPayment.setPackageTb(packageTb);
    model.addAttribute(customerPayment);
    logger.debug("Redirecting to Payment page.");

    return "registration/payment";
}

但是,当返回支付界面我得到这个错误:

java.lang.IllegalStateException:com.domain.CustomerPayment [customerPaymentId =空] org.springframework.validation.DataBinder.setValidator(DataBinder.java:476)com.web:用于验证[com.validator.UserValidator@710db357]无效目标。 UserRegistrationController.initBinder(UserRegistrationController.java:43)sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)的java .lang.reflect.Method.invoke(Method.java:597)org.springframework.web.bind.annotation.support.HandlerMethodInvoker.initBinder(HandlerMethodInvoker.java:393)org.springframework.web.bind.annotation.support.HandlerMethodInvoker .updateModelAttributes(HandlerMethodInvoker.java:222)org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:429)org.springframework.web.servlet.mvc.annota tion.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)

这可能是因为我返回CustomerPayment并没有为定义的验证。

我也无法在添加多个验证initBinder方法。

我怎样才能解决这个问题?

Answer 1:

您需要将值设置@InitBinder注释你想它来验证命令的名称。 这告诉Spring如何应用粘结剂; 没有它,Spring会尽量把它应用到一切。 这就是为什么你看到这个异常:春天尝试应用粘合剂-与您的UserValidator -以类型的参数CustomerPayment

在特定情况下,它看起来像你需要的东西,如:

@InitBinder("user")
protected void initBinder(WebDataBinder binder) {
    binder.setValidator(new UserValidator());
}

你的第二个问题,作为Rigg802解释说,春节不支持多重验证连接到一个单一的命令。 你可以,但是,定义多个@InitBinder为不同的命令的方法。 因此,举例来说,你可以把下面的一个控制器和验证用户和支付参数:

@InitBinder("user")
protected void initUserBinder(WebDataBinder binder) {
    binder.setValidator(new UserValidator());
}

@InitBinder("payment")
protected void initPaymentBinder(WebDataBinder binder) {
    binder.setValidator(new CustomerPaymentValidator());
}


Answer 2:

这是一个有点棘手的事,1个控制器对1个的命令对象只有1个验证。 你需要创建一个“综合验证”,将得到的所有验证和seperately运行它们。

下面是说明如何做一个教程: 使用多个验证



Answer 3:

我不明白了一个道理,为什么春节不过滤掉不适用默认当前实体,它强制使用由@ Rigg802描述像CompoundValidator东西全部验证。

InitBinder允许您指定的名称仅给你一些控制,但没有对如何以及何时应用您的自定义验证完全控制。 从我的角度来看是不够的。

你可以做的另一件事是执行检查自己,并添加验证与粘结剂,只有当它实际上是必要的,因为粘合剂本身结合上下文信息。

例如,如果你想添加一个新的验证器将与除了内置的验证你可以写这样的用户对象的工作:

@InitBinder
protected void initBinder(WebDataBinder binder) {
  Optional.ofNullable(binder.getTarget())
      .filter((notNullBinder) -> User.class.equals(notNullBinder.getClass()))
      .ifPresent(o -> binder.addValidators(new UserValidator()));

}



Answer 4:

您可以通过遍历所有org.springframework.validation.Validator在一个ApplicationContext并建立适合那些在@InitBinder为每个请求添加多个验证。

@InitBinder
public void setUpValidators(WebDataBinder webDataBinder) {
    for (Validator validator : validators) {
        if (validator.supports(webDataBinder.getTarget().getClass())
                && !validator.getClass().getName().contains("org.springframework"))
            webDataBinder.addValidators(validator);
    }
}

看我为例子,简单的基准测试项目。 https://github.com/LyashenkoGS/spring-mvc-and-jms-validation-POC/tree/benchamark



Answer 5:

有一个简单的黑客,总是返回truesupports方法,并委托类检查,以validate 。 然后基本上你可以在添加多个验证initBinder没有问题。

@Component
public class MerchantRegisterValidator implements Validator {

    @Autowired
    private MerchantUserService merchantUserService;

    @Autowired
    private MerchantCompanyService merchantCompanyService;

    @Override
    public boolean supports(Class<?> clazz) {
        return true; // always true
    }

    @Override
    public void validate(Object target, Errors errors) {

        if (!XxxForm.getClass().equals(target.getClass()))
            return; // do checking here.

        RegisterForm registerForm = (RegisterForm) target;

        MerchantUser merchantUser = merchantUserService.getUserByEmail(registerForm.getUserEmail());

        if (merchantUser != null) {
            errors.reject("xxx");
        }

        MerchantCompany merchantCompany = merchantCompanyService.getByRegno(registerForm.getRegno());

        if (merchantCompany != null) {
            errors.reject("xxx");
        }

    }

}


Answer 6:

在一个命令多重验证现在与Spring MVC的4.x的支持。 您可以使用此代码片段:

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.addValidators(new UserValidator(), new CustomerPaymentValidator());
}


Answer 7:

声明要求为

(... , Model model,HttpServletRequest request)

与变化

model.addAttribute(customerPayment);

request.setAttribute("customerPayment",customerPayment);


文章来源: Adding multiple validators using initBinder