Spring 验证:使用两个验证器时得到 "Invalid target for Validator"
Spring validation: getting "Invalid target for Validator" when using two validators
我在使用@InitBinder 注释实现两个验证器时遇到问题。
控制器代码:
@Autowired
private SessionValidator sessionValidator;
@Autowired
private ChannelValidator channelValidator;
@InitBinder
public void initBinder(WebDataBinder binder){
binder.addValidators(sessionValidator, channelValidator);
}
@RequestMapping(method = RequestMethod.GET)
public UserInfo findBySession(
@Valid @ModelAttribute Session session,
@Valid @ModelAttribute Channel channel){
//...
}
会话验证器:
@Component
public class SessionValidator implements Validator {
@Override
public boolean supports(Class<?> aClass){
return Session.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors){
//...
}
}
频道验证器:
@Component
public class ChannelValidator implements Validator {
@Override
public boolean supports(Class<?> aClass){
return Channel.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors){
//...
}
}
我在调用控制器时收到以下异常:
Caused by: java.lang.IllegalStateException: Invalid target for Validator [com.almundo.p13n.dna.validators.ChannelValidator@4e642ee1]: Session(null, null)
有人知道怎么解决吗?提前致谢!
您绑定了两个验证器,但对于每个用于验证的参数,将只支持其中一个。
SessionValidator
支持Session
参数但不支持Channel
参数反之ChannelValidator
支持Channel
参数但不支持Session
参数。
而异常。
作为第一种选择,您可以在每个 Spring 验证器子 class 中支持两种参数类型。它有点笨拙,但应该可以工作:
@Override
public boolean supports(Class<?> aClass){
return Channel.class.equals(aClass) || Session.class.equals(aClass);
}
你当然应该检查 validate()
中的类型,只有当它与验证器 class 匹配时才执行验证。
作为第二种选择,使用标准验证 API 通过为每个 class 实现 javax.validation.ConstraintValidator
来验证并在控制器中显式验证参数。
作为第三种选择,如果有意义,您可以直接在 Session
和 Channel
class 上注释约束。因此,您仍然可以在参数声明中使用 @Valid
来保持自动验证。
您只能添加受支持的验证器:
@InitBinder
protected void initBinder(WebDataBinder binder) {
if (binder.getTarget() == null) return;
final ImmutableList<Validator> validatorsList = ImmutableList.of(
new CunsomValidator1(),
new CunsomValidator2()
);
for (Validator validator : validatorsList) {
if (validator.supports(binder.getTarget().getClass())) {
binder.addValidators(validator);
}
}
}
我在使用@InitBinder 注释实现两个验证器时遇到问题。
控制器代码:
@Autowired
private SessionValidator sessionValidator;
@Autowired
private ChannelValidator channelValidator;
@InitBinder
public void initBinder(WebDataBinder binder){
binder.addValidators(sessionValidator, channelValidator);
}
@RequestMapping(method = RequestMethod.GET)
public UserInfo findBySession(
@Valid @ModelAttribute Session session,
@Valid @ModelAttribute Channel channel){
//...
}
会话验证器:
@Component
public class SessionValidator implements Validator {
@Override
public boolean supports(Class<?> aClass){
return Session.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors){
//...
}
}
频道验证器:
@Component
public class ChannelValidator implements Validator {
@Override
public boolean supports(Class<?> aClass){
return Channel.class.equals(aClass);
}
@Override
public void validate(Object o, Errors errors){
//...
}
}
我在调用控制器时收到以下异常:
Caused by: java.lang.IllegalStateException: Invalid target for Validator [com.almundo.p13n.dna.validators.ChannelValidator@4e642ee1]: Session(null, null)
有人知道怎么解决吗?提前致谢!
您绑定了两个验证器,但对于每个用于验证的参数,将只支持其中一个。
SessionValidator
支持Session
参数但不支持Channel
参数反之ChannelValidator
支持Channel
参数但不支持Session
参数。
而异常。
作为第一种选择,您可以在每个 Spring 验证器子 class 中支持两种参数类型。它有点笨拙,但应该可以工作:
@Override
public boolean supports(Class<?> aClass){
return Channel.class.equals(aClass) || Session.class.equals(aClass);
}
你当然应该检查 validate()
中的类型,只有当它与验证器 class 匹配时才执行验证。
作为第二种选择,使用标准验证 API 通过为每个 class 实现 javax.validation.ConstraintValidator
来验证并在控制器中显式验证参数。
作为第三种选择,如果有意义,您可以直接在 Session
和 Channel
class 上注释约束。因此,您仍然可以在参数声明中使用 @Valid
来保持自动验证。
您只能添加受支持的验证器:
@InitBinder
protected void initBinder(WebDataBinder binder) {
if (binder.getTarget() == null) return;
final ImmutableList<Validator> validatorsList = ImmutableList.of(
new CunsomValidator1(),
new CunsomValidator2()
);
for (Validator validator : validatorsList) {
if (validator.supports(binder.getTarget().getClass())) {
binder.addValidators(validator);
}
}
}