2012-02-10 89 views
0

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

的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 = "[email protected]+\\.[a-z]+", message = "validation.message.email", flags = { Pattern.Flag.CASE_INSENSITIVE }) 
    private String email; 

    @NotNull(message = "validation.message.email.empty") 
    @Pattern(regexp = "[email protected]+\\.[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; 
    } 
} 

回答

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; 
    } 
} 
相关问题