【问题标题】:JSR-303 errors not detected natively by using the @Valid annotation使用 @Valid 注释本机未检测到 JSR-303 错误
【发布时间】:2015-01-15 18:26:11
【问题描述】:

@Valid 注释为什么不能原生捕获我的 JSR-303 注释,但使用以下方法捕获它们:

WebConfig.java

@Bean
public ResourceBundleMessageSource messageSource() {

    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

    String[] strBaseNames = {
            "resources.messages.layout.LayoutResources",
            "resources.messages.layout.MenuResources",
            "resources.messages.global.GlobalResources"
    };

    messageSource.setUseCodeAsDefaultMessage(true);
    messageSource.setDefaultEncoding("UTF-8");
    messageSource.setBasenames(strBaseNames);

    return messageSource;
}

@Bean
public LocalValidatorFactoryBean jsr303Validator() {

    LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    localValidatorFactoryBean.setValidationMessageSource(this.messageSource());

    return localValidatorFactoryBean;
}

UserController.java

@Controller
@RequestMapping(value = "/security/user", method = RequestMethod.GET)
public class UserController {

@Autowired
private SecurityService securityService;

@Autowired
SessionObject sessionObject;

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

@RequestMapping(value = "/edit/validate", method = RequestMethod.POST)
public String validateEdit( @ModelAttribute @Valid User user,
                            BindingResult result,
                            Model model) {

    String strViewName = "common/error";

    validator.validate(user, result);

    if(result.hasErrors()) {
        strViewName = "user/userEdit";
    } else {
        ... update work ...
        strViewName = "user/success";
    }

    return strViewName;
}

资源: http://www.wenda.io/questions/2462924/convert-jsr-303-validation-errors-to-springs-bindingresult.html

如果我只使用@Valid 注释,result.hasErrors() 总是空的,所以我最终会遇到预期的 ConstraintViolationException(见下文)。但我希望它只使用 @Valid 注释来工作,而不必在我想要实现一些 JSR-303 验证的每个控制器中自动装配我的 jsr303validator bean。

约束违规日志跟踪

Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [spring4base.model.security.User] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='error.firstname.notnull', propertyPath=strFirstName, rootBeanClass=class spring4base.model.security.User, messageTemplate='error.firstname.notnull'}
ConstraintViolationImpl{interpolatedMessage='error.userid.notnull', propertyPath=strUserId, rootBeanClass=class spring4base.model.security.User, messageTemplate='error.userid.notnull'}
ConstraintViolationImpl{interpolatedMessage='error.lastname.notnull', propertyPath=strLastName, rootBeanClass=class spring4base.model.security.User, messageTemplate='error.lastname.notnull'}

]

User.java

@NotBlank(message = "error.userid.notnull")
@Size(min = 0, max = 14, message = "error.firstname.length")
private String strUserId = "";

@NotBlank(message = "error.firstname.notnull")
@Size(min = 0, max = 50, message = "error.firstname.length")
private String strFirstName = "";

@NotBlank(message = "error.lastname.notnull")
@Size(min = 0, max = 50, message = "error.lastname.length")
private String strLastName = "";

谢谢

【问题讨论】:

  • 你解决过这个问题吗?
  • 是的,马上发布解决方案。

标签: spring spring-mvc bean-validation


【解决方案1】:

为了使其适用于我的情况,需要以下内容:

首先,在我的 Java Config 类(在我的例子中是 WebAppContext.java)中定义一个 LocalValidatorFactoryBean。

@Bean
public ResourceBundleMessageSource messageSource() {

    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

    String[] baseNames = {
            "resources.messages.layout.LayoutResources",
            "resources.messages.layout.MenuResources",
            "resources.messages.option.AppConfigResources",
            "resources.messages.global.GlobalResources",
            "resources.messages.contact.ContactResources",
            "resources.messages.currentsession.CurrentSessionResources",
            "resources.messages.welcome.WelcomeResources",
            "resources.messages.user.UserResources",
            "resources.messages.role.RoleResources",
            "resources.messages.profile.ProfileResources"
    };

    messageSource.setCacheSeconds(60);
    messageSource.setFallbackToSystemLocale(false);
    messageSource.setUseCodeAsDefaultMessage(true);
    messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
    messageSource.setBasenames(baseNames);

    return messageSource;
}


@Bean
public LocalValidatorFactoryBean jsr303Validator() {

    LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
    localValidatorFactoryBean.setValidationMessageSource(this.messageSource());

    return localValidatorFactoryBean;
}

然后,在我的控制器中,我像这样自动装配该验证器:

@Autowired
private Validator jsr303Validator;

然后,我发现执行 JSR-303 的唯一方法是手动启动它们,如下所示:

@RequestMapping(value = "/update",  method = RequestMethod.POST)
public String processUpdate(@ModelAttribute UserForm userForm,
                            BindingResult result,
                            RedirectAttributes redirectAttributes,
                            SessionStatus status) throws CheckedPersistenceException {

    this.userFormValidator.validate(userForm, result);

    if (!result.hasErrors()) {
        this.jsr303Validator.validate(userForm, result);
    }

    if(result.hasErrors()) {
        return this.UPDATE_VIEW;
    }

    ...
}

【讨论】:

  • 但这不正是您的问题吗?
猜你喜欢
  • 2014-08-25
  • 1970-01-01
  • 2021-06-13
  • 1970-01-01
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 1970-01-01
  • 2016-11-22
相关资源
最近更新 更多