表单未使用hibernate验证器进行验证

时间:2015-12-30 15:11:52

标签: spring-mvc bean-validation hibernate-validator

我正在使用spring mvc + jpa 2.1 + hibernate验证器在liferay 6.2上开发一个portlet

在我的pom中我有

....
 <dependency> 
            <groupId>org.hibernate</groupId> 
            <artifactId>hibernate-entitymanager</artifactId> 
            <version>5.0.6.Final</version> 
        </dependency>   
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>jta</artifactId>
            <version>1.1</version>
        </dependency>        
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>5.0.6.Final</version> 
        </dependency>                
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.1-api</artifactId>
            <version>1.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.2.Final</version>
        </dependency>        
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator-annotation-processor</artifactId>
            <version>5.2.2.Final</version>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-log4j12</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>  
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>              
....

我为hibernate验证器

创建了一些自定义约束
@Target({FIELD, METHOD})
@Retention(RUNTIME)
@Constraint(validatedBy = CheckCodiceFiscaleValidator.class)
@Documented
public @interface CheckCF {
    String message() default "{validator.assertFalse}";

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

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

并且实现的验证器是

public class CheckCodiceFiscaleValidator implements ConstraintValidator<CheckCF, String> {

    @Override
    public void initialize(CheckCF constraintAnnotation) {
        //throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
        //constraintContext.disableDefaultConstraintViolation();
        constraintContext.buildConstraintViolationWithTemplate(
                "{it.realt.validator.constraint.custom.cf.genericError.message}").addConstraintViolation();
        if (Strings.isNullOrEmpty(object)) {
            return false;
        }

        return validaCF(object, constraintContext);
    }

    private boolean validaCF(String cf, ConstraintValidatorContext constraintContext) {
        int i, s, c;
        String cf2;
        int setdisp[]
                = {
                    1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20,
                    11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23
                };
        if (cf.length() == 0) {
            constraintContext.buildConstraintViolationWithTemplate(
                    "{it.realt.validator.constraint.custom.cf.notEmpty.message}").addConstraintViolation();
            return false;
        }
        if (cf.length() != 16) {
            constraintContext.buildConstraintViolationWithTemplate(
                    "{it.realt.validator.constraint.custom.cf.tooShort.message}").addConstraintViolation();
            return false;
        }
        cf2 = cf.toUpperCase();
        for (i = 0; i < 16; i++) {
            c = cf2.charAt(i);
            if (!(c >= '0' && c <= '9' || c >= 'A' && c <= 'Z')) {
                constraintContext.buildConstraintViolationWithTemplate(
                        "{it.realt.validator.constraint.custom.cf.invalidChars.message}").addConstraintViolation();
                return false;
            }
        }
        s = 0;
        for (i = 1; i <= 13; i += 2) {
            c = cf2.charAt(i);
            if (c >= '0' && c <= '9') {
                s = s + c - '0';
            } else {
                s = s + c - 'A';
            }
        }
        for (i = 0; i <= 14; i += 2) {
            c = cf2.charAt(i);
            if (c >= '0' && c <= '9') {
                c = c - '0' + 'A';
            }
            s = s + setdisp[c - 'A'];
        }
        if (s % 26 + 'A' != cf2.charAt(15)) {
            constraintContext.buildConstraintViolationWithTemplate(
                    "{it.realt.validator.constraint.custom.cf.controlCode.message}").addConstraintViolation();
            return false;
        }
        return true;
    }
}

在实体类中我有

...
    @Column(name = "cognome")
    @NotEmpty
    private String cognome;

    @Column(name = "nome")
    @NotEmpty
    private String nome;

    @Column(name = "indirizzo")
    @NotEmpty
    private String indirizzo;

    @Column(name = "cap")
    @NotEmpty
    @Length(min=5, max=5)
    private String cap;

    @Column(name = "citta")
    @NotEmpty
    private String citta;

    @Column(name = "provincia")
    @NotEmpty
    private String provincia;

    @Column(name = "partita_iva")
    @CheckPIVA
    private String partitaIva;

    @Column(name = "codice_fiscale")
    @CheckCF
    private String codiceFiscale;
...

在我的控制器中我放了@Valid注释

...
@ActionMapping(params = "action=register")
public void richiestaRegistrazione(ActionRequest actionRequest, ActionResponse actionResponse, 
        @ModelAttribute("anagrafica") @Valid Anagrafica anagrafica, BindingResult result, Model model) throws IOException,
                 PortletException {
        boolean succeded = this.anagraficaManager.richiediRegistrazione(anagrafica);
        model.addAttribute("succeded", succeded);
}
...

最后jsp是

    ...
    <form:form name="<portlet:namespace/>anagrafica" modelAttribute="anagrafica" action="${registraRichiestaURL}" method="post">
<center>
    <table>

        <tr align="left">
            <th align="right">Partita IVA: </th>
            <td align="left" class="generale"><span><form:input path="partitaIva" maxlength="11"/><form:errors path="partitaIva" cssClass="error"/></span></td>
        </tr>
    ...

当我提交表单时,验证失败,我得到了异常

javax.validation.ConstraintViolationException: Validation failed for classes [it.realt.mypos.domain.Anagrafica] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=cap, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=natoA, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=citta, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=provincia, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=indirizzo, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=cognome, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be empty', propertyPath=nome, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.NotEmpty.message}'}
    ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=natoIl, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{javax.validation.constraints.NotNull.message}'}
    ConstraintViolationImpl{interpolatedMessage='Si è verificato un errore nel controllo del Codice Fiscale', propertyPath=codiceFiscale, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{it.realt.validator.constraint.custom.cf.genericError.message}'}
    ConstraintViolationImpl{interpolatedMessage='{validator.assertFalse}', propertyPath=codiceFiscale, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{validator.assertFalse}'}
    ConstraintViolationImpl{interpolatedMessage='length must be between 5 and 5', propertyPath=cap, rootBeanClass=class it.realt.mypos.domain.Anagrafica, messageTemplate='{org.hibernate.validator.constraints.Length.message}'}
]
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:78)
    at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:205)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:82)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:560)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:434)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39).....

并且页面中没有绑定任何错误...

我查看了google中发现的几个示例,看起来我做的都是正确的...所以问题出在哪里?

由于

安德烈

1 个答案:

答案 0 :(得分:0)

您的示例是正确的,为什么没有错误在您的页面中绑定,原因很简单,您在“partitaIva”字段中有任何错误,您可以在ConstraintViolationException跟踪中看到。

如果您想要显示所有错误,则必须从

中删除路径属性
<form:errors path="partitaIva" cssClass="error"/>