¿Existe una implementación de (o implementación de terceros para) validación de campo cruzado en Hibernate Validator 4.x? Si no, ¿cuál es la forma más limpia de implementar un validador de campo cruzado?
Como ejemplo, ¿cómo puede usar la API para validar dos propiedades de bean? (Como validar un campo de contraseña coincide con el campo de verificación de contraseña).
En anotaciones, esperaría algo como:
public class MyBean {
@Size(min=6, max=50)
private String pass;
@Equals(property="pass")
private String passVerify;
}
validation
hibernate-validator
bean-validation
Bradhouse
fuente
fuente
Respuestas:
Cada restricción de campo debe ser manejada por una anotación de validador distinta, o en otras palabras, no es una práctica sugerida que la anotación de validación de un campo verifique contra otros campos; La validación de campo cruzado debe hacerse a nivel de clase. Además, la forma preferida de JSR-303 Sección 2.2 para expresar múltiples validaciones del mismo tipo es a través de una lista de anotaciones. Esto permite que el mensaje de error se especifique por partido.
Por ejemplo, validando una forma común:
La anotación:
El validador:
fuente
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addNode(secondFieldName).addConstraintViolation().disableDefaultConstraintViolation();
Da la posibilidad de resaltar el campo correcto (si solo JSF lo admitiera).BeanUtils.getProperty
devuelve una cadena El ejemplo probablemente significaba usarPropertyUtils.getProperty
que devuelve un objeto.Te sugiero otra posible solución. ¡Quizás menos elegante, pero más fácil!
El
isValid
validador invoca el método automáticamente.fuente
@AssertTrue
métodos similares ? ¿Se cumple alguna convención de nomenclatura?Me sorprende que esto no esté disponible de fábrica. De todos modos, aquí hay una posible solución.
He creado un validador de nivel de clase, no el nivel de campo como se describe en la pregunta original.
Aquí está el código de anotación:
Y el validador en sí mismo:
Tenga en cuenta que he usado MVEL para inspeccionar las propiedades del objeto que se valida. Esto podría reemplazarse con las API de reflexión estándar o, si está validando una clase específica, los métodos de acceso en sí.
La anotación @Matches se puede usar en un bean de la siguiente manera:
Como descargo de responsabilidad, escribí esto en los últimos 5 minutos, por lo que probablemente todavía no haya solucionado todos los errores. Actualizaré la respuesta si algo sale mal.
fuente
Con Hibernate Validator 4.1.0.Final recomiendo usar @ScriptAssert . Excepto de su JavaDoc:
Nota: la evaluación se realiza mediante un script " motor " de que se ejecuta en la máquina virtual Java, por lo tanto, en el "lado del servidor" de Java, no en el "lado del cliente" como se indica en algunos comentarios.
Ejemplo:
o con alias más corto y nulo-seguro:
o con Java 7+ null-safe
Objects.equals()
:Sin embargo, no hay nada de malo con una solución de validación de nivel de clase personalizada @Matches .
fuente
Las validaciones de campos cruzados se pueden realizar creando restricciones personalizadas.
Ejemplo: - Compare la contraseña y confirme los campos Contraseña de la instancia de Usuario.
CompareStrings
StringComparisonMode
CompareStringsValidator
Restricción Validador Ayudante
Usuario
Prueba
Salida
Message:- [Password, ConfirmPassword] must be equal.
Al usar la restricción de validación CompareStrings, también podemos comparar más de dos propiedades y podemos mezclar cualquiera de los cuatro métodos de comparación de cadenas.
ColorChoice
Prueba
Salida
Message:- Please choose three different colors.
Del mismo modo, podemos tener restricciones de validación de campos cruzados CompareNumbers, CompareDates, etc.
PD: No he probado este código en un entorno de producción (aunque lo probé en un entorno de desarrollo), así que considere este código como lanzamiento de Milestone. Si encuentra un error, por favor escriba un buen comentario. :)
fuente
He probado el ejemplo de Alberthoven (hibernate-validator 4.0.2.GA) y obtengo una ValidationException: „Los métodos anotados deben seguir la convención de nomenclatura JavaBeans. match () no. "también. Después de cambiar el nombre del método de "partido" a "isValid", funciona.
fuente
Si está utilizando Spring Framework, puede usar Spring Expression Language (SpEL) para eso. He escrito una pequeña biblioteca que proporciona el validador JSR-303 basado en SpEL, ¡hace que las validaciones de campo cruzado sean muy fáciles! Echa un vistazo a https://github.com/jirutka/validator-spring .
Esto validará la longitud y la igualdad de los campos de contraseña.
También puede modificar esto fácilmente para validar los campos de contraseña solo cuando ambos no estén vacíos.
fuente
Me gusta la idea de Jakub Jirutka. de usar Spring Expression Language. Si no desea agregar otra biblioteca / dependencia (suponiendo que ya usa Spring), aquí hay una implementación simplificada de su idea.
La restricción:
El validador:
Aplicar de esta manera:
fuente
No tengo la reputación de comentar sobre la primera respuesta, pero quería agregar que he agregado pruebas unitarias para la respuesta ganadora y tengo las siguientes observaciones:
fuente
Muy buena solución Bradhouse. ¿Hay alguna forma de aplicar la anotación @Matches a más de un campo?
EDITAR: Aquí está la solución que se me ocurrió para responder a esta pregunta, modifiqué la restricción para aceptar una matriz en lugar de un solo valor:
El código para la anotación:
Y la implementación:
fuente
Necesitas llamarlo explícitamente. En el ejemplo anterior, bradhouse le ha dado todos los pasos para escribir una restricción personalizada.
Agregue este código en su clase de llamante.
en el caso anterior sería
fuente
¿Por qué no probar Oval: http://oval.sourceforge.net/
Parece que es compatible con OGNL, así que tal vez podrías hacerlo de una manera más natural
fuente
Ustedes chicos son geniales Ideas realmente asombrosas. Me gustan más Alberthoven y McGin , así que decidí combinar ambas ideas. Y desarrolle alguna solución genérica para atender todos los casos. Aquí está mi solución propuesta.
fuente
Hice una pequeña adaptación en la solución de Nicko para que no sea necesario usar la biblioteca Apache Commons BeanUtils y reemplazarla con la solución ya disponible en primavera, para aquellos que la usan, ya que puedo ser más simple:
fuente
Solución relacionada con la pregunta: Cómo acceder a un campo que se describe en la propiedad de anotación
Y cómo usarlo...? Me gusta esto:
fuente