【问题标题】:form not validating using hibernate validator表单未使用休眠验证器进行验证
【发布时间】:2023-03-21 13:30:01
【问题描述】:

我正在使用 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>              
....

我为休眠验证器创建了一些自定义约束

@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).....

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

我检查了几个在谷歌上找到的例子,似乎我都做对了……那么,问题出在哪里?

谢谢

安德烈亚

【问题讨论】:

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


    【解决方案1】:

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

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

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

    【讨论】:

    • 没关系...我只报告了jsp的一个简单部分....jsp中的所有字段都有自己的表单:错误...我只填写第一个并留下其他空的.. 我希望收到留空字段的错误,而不是收到异常
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-20
    • 2012-09-18
    • 1970-01-01
    相关资源
    最近更新 更多