【问题标题】:Error message is not displayed in freemarker template for custom FieldMatchValidator in Spring applicationSpring 应用程序中自定义 FieldMatchValidator 的 freemarker 模板中未显示错误消息
【发布时间】:2012-03-03 00:00:43
【问题描述】:

如标题中所述,我无法将 FieldMatchValidator 的错误消息显示在我的 freemarker 模板中。所有其他“常规”错误消息,例如 @NotNull 都与来自 message.properties 的准确消息一起显示。由于 result.hasErrors() 返回 true 并且结果对象包含 FieldMatch 错误,因此使用 FieldMatchValidator 进行验证。我错过了什么?

applicationContext.xml:

<!-- Invokes Spring MVC @Controller methods -->
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="webBindingInitializer">
            <!-- Configures Spring MVC DataBinder instances -->
            <bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
                <property name="validator" ref="validator"/>
            </bean>
        </property>
    </bean>


    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="messageInterpolator">
            <bean class="com.reco.web.mvc.validator.CustomMessageInterpolator">
                <property name="messageSource" ref="messageSource"/>
            </bean>
        </property>
    </bean>

控制器:

@Controller
public class RegisterController extends MyWebController{

    private static final String REGISTER_FORM_VIEW = "/action/register/register";
    private static final String REGISTER_SUCCESS_VIEW = "/action/register/success";

    private org.springframework.validation.Validator validator;

    @Autowired
    public RegisterController(MessageSource messageSource, Validator validator) {
        super(messageSource);
        this.validator = validator;
    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.setValidator((org.springframework.validation.Validator)validator);
    }

    @RequestMapping(value = "/action/register", method = RequestMethod.GET)
    public ModelAndView getRegisterForm() {
        ModelAndView mav = new ModelAndView(REGISTER_FORM_VIEW);
        mav.addObject("registerForm", new RegisterForm());
        return mav;
    }

    @RequestMapping(value = "/action/register", method = RequestMethod.POST)
    public final String register(@Valid RegisterForm registerForm, BindingResult result, ModelMap model, HttpServletRequest request) {

        if (result.hasErrors()) {
            return REGISTER_FORM_VIEW;
        }

        return "redirect:" + REGISTER_SUCCESS_VIEW;
    }


}

注释:

@Target({TYPE, ANNOTATION_TYPE})
@Retention(RUNTIME)
@Constraint(validatedBy = FieldMatchValidator.class)
@Documented
public @interface FieldMatch {

    String message() default "{constraints.fieldmatch}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    /**
     * @return The first field
     */
    String first();

    /**
     * @return The second field
     */
    String second();

    /**
     * Defines several <code>@FieldMatch</code> annotations on the same element
     *
     * @see FieldMatch
     */
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Documented
            @interface List {
        FieldMatch[] value();
    }


}

验证器:

public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object>
{
    private String firstFieldName;
    private String secondFieldName;

    @Override

public void initialize(final FieldMatch constraintAnnotation)
{
    firstFieldName = constraintAnnotation.first();
    secondFieldName = constraintAnnotation.second();        

}



   @Override
    public boolean isValid(final Object value, final ConstraintValidatorContext context)
    {
        try
        {
            final Object firstObj = BeanUtils.getProperty(value, firstFieldName);
            final Object secondObj = BeanUtils.getProperty(value, secondFieldName);

            return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
        }
        catch (final Exception ignore)
        {
            // ignore
        }
        return true;
    }
}

freemarker 模板:

<!doctype html>
<html lang="sv">
<head>
    <meta charset="utf-8"/>
    <title></title>
</head>
<body id="register">

<div id="content">
    <form id="registerForm" action="${rc.contextPath}/action/register" method="POST">
        <p>
            <label for="firstname">firstname</label>
        <@spring.formInput "registerForm.firstName" />
        <@spring.showErrors "", "error"/>
        </p>

        <p>
            <label for="lastname">lastname</label>
        <@spring.formInput "registerForm.lastName" />
        <@spring.showErrors "", "error"/>
        </p>

        <p>
            <label for="email">email</label>
        <@spring.formInput "registerForm.email" />
        <@spring.showErrors "", "error"/>
        </p>

        <p>
            <label for="email_again">email_again</label>
        <@spring.formInput "registerForm.confirmEmail" />
        <@spring.showErrors "", "error"/>
        </p>

        <p>
            <label for="password">password</label>
        <@spring.formPasswordInput "registerForm.password" />
        <@spring.showErrors "", "error"/>
        </p>

        <p>
            <label for="password_again">password_again</label>
        <@spring.formPasswordInput "registerForm.confirmPassword" />
        <@spring.showErrors "", "error"/>
        <@spring.showErrors "", "confirmPassword"/>
        </p>

        <input type="submit"/>
    </form>

</div>

</body>
</html>

FormObject:

@FieldMatch.List({
        @FieldMatch(first = "password", second = "confirmPassword", message = "validation.message.confirm.password"),
        @FieldMatch(first = "email", second = "confirmEmail", message = "validation.message.confirm.email")
})
public class RegisterForm implements Serializable {

    private static final int MAX_TEXT_FIELD_SIZE = 32;

    /**
     * Password min size.
     */
    private static final int PASSWORD_MIN_SIZE = 8;

    /**
     * Password max size.
     */
    private static final int PASSWORD_MAX_SIZE = 36;

    @NotNull(message = "validation.message.firstname.empty")
    @Size(min = 1, max = MAX_TEXT_FIELD_SIZE, message = "validation.message.firstname.length")
    @Pattern(regexp = "^[^<>]*$", message = "validation.message.invalid.characters")
    private String firstName;

    @NotNull(message = "validation.message.lastname.empty")
    @Size(min = 1, max = MAX_TEXT_FIELD_SIZE, message = "validation.message.lastname.length")
    @Pattern(regexp = "^[^<>]*$", message = "validation.message.invalid.characters")
    private String lastName;

    @NotNull(message = "validation.message.email.empty")
    @Pattern(regexp = ".+@.+\\.[a-z]+", message = "validation.message.email", flags = { Pattern.Flag.CASE_INSENSITIVE })
    private String email;

    @NotNull(message = "validation.message.email.empty")
    @Pattern(regexp = ".+@.+\\.[a-z]+", message = "validation.message.email", flags = { Pattern.Flag.CASE_INSENSITIVE })
    private String confirmEmail;

    @NotNull
    @Size(min = PASSWORD_MIN_SIZE, max = PASSWORD_MAX_SIZE)
    private String password;

    @NotNull
    @Size(min = PASSWORD_MIN_SIZE, max = PASSWORD_MAX_SIZE)
    private String confirmPassword;

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getConfirmEmail() {
        return confirmEmail;
    }

    public void setConfirmEmail(String confirmEmail) {
        this.confirmEmail = confirmEmail;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getConfirmPassword() {
        return confirmPassword;
    }

    public void setConfirmPassword(String confirmPassword) {
        this.confirmPassword = confirmPassword;
    }
}

【问题讨论】:

    标签: spring freemarker customvalidator


    【解决方案1】:

    我通过添加适当的约束验证消息解决了这个问题:

    errorMessage = constraintAnnotation.message();
    

    到自定义 FieldMatchValidator 内的正确字段。就我而言,我将错误添加到第二个字段:

    context.buildConstraintViolationWithTemplate(errorMessage).addNode(secondFieldName).addConstraintViolation();
    

    FieldMatchValidator

    public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object>
    {
        private String firstFieldName;
        private String secondFieldName;
        private String errorMessage;
    
        @Override
        public void initialize(final FieldMatch constraintAnnotation)
        {
            firstFieldName = constraintAnnotation.first();
            secondFieldName = constraintAnnotation.second();
            errorMessage = constraintAnnotation.message();
    
        }
    
        @Override
        public boolean isValid(final Object value, final ConstraintValidatorContext context)
        {
            try
            {
                final Object firstObj = BeanUtils.getProperty(value, firstFieldName);
                final Object secondObj = BeanUtils.getProperty(value, secondFieldName);
    
                boolean valid = firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
    
                if(!valid){
                    context.buildConstraintViolationWithTemplate(errorMessage).addNode(secondFieldName).addConstraintViolation();
                }
    
                return valid;
            }
            catch (final Exception ignore)
            {
                // ignore
            }
            return true;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-11-24
      • 2017-01-15
      • 2021-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 1970-01-01
      相关资源
      最近更新 更多