Existe uma implementação (ou implementação de terceiros para) de validação de campo cruzado no Hibernate Validator 4.x? Caso contrário, qual é a maneira mais limpa de implementar um validador de campo cruzado?
Como exemplo, como você pode usar a API para validar que duas propriedades do bean sejam iguais (por exemplo, a validação de um campo de senha corresponde ao campo de verificação de senha).
Nas anotações, eu esperaria 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
fonte
fonte
Respostas:
Cada restrição de campo deve ser tratada por uma anotação de validador distinta ou, em outras palavras, não é uma prática sugerida que a anotação de validação de um campo seja verificada em relação a outros campos; a validação de campo cruzado deve ser feita no nível da classe. Além disso, a maneira preferida da Seção 2.2 do JSR-303 de expressar várias validações do mesmo tipo é através de uma lista de anotações. Isso permite que a mensagem de erro seja especificada por correspondência.
Por exemplo, validando um formulário comum:
A anotação:
O validador:
fonte
context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()).addNode(secondFieldName).addConstraintViolation().disableDefaultConstraintViolation();
Oferece a possibilidade de destacar o campo certo (se apenas o JSF o apoiar).BeanUtils.getProperty
retorna uma string. O exemplo provavelmente deve ser usado paraPropertyUtils.getProperty
retornar um objeto.Eu sugiro outra solução possível. Talvez menos elegante, mas mais fácil!
O
isValid
método é invocado pelo validador automaticamente.fonte
@AssertTrue
métodos desse tipo ? Alguma convenção de nomenclatura é válida?Estou surpreso que isso não esteja disponível imediatamente. Enfim, aqui está uma solução possível.
Eu criei um validador no nível da classe, não no nível do campo, conforme descrito na pergunta original.
Aqui está o código da anotação:
E o próprio validador:
Observe que eu usei o MVEL para inspecionar as propriedades do objeto que está sendo validado. Isso pode ser substituído pelas APIs de reflexão padrão ou, se for uma classe específica que você está validando, pelos próprios métodos acessadores.
A anotação @Matches pode ser usada em um bean da seguinte maneira:
Como isenção de responsabilidade, escrevi isso nos últimos 5 minutos, então provavelmente ainda não resolvi todos os erros. Atualizarei a resposta se algo der errado.
fonte
Com o Hibernate Validator 4.1.0.Final, recomendo usar o @ScriptAssert . Exceto em seu JavaDoc:
Nota: a avaliação está sendo executada por um " mecanismo " de script em execução na Java VM, portanto, no Java "lado do servidor", não no "lado do cliente", conforme indicado em alguns comentários.
Exemplo:
ou com alias mais curto e sem segurança:
ou com Java 7+ seguro para nulos
Objects.equals()
:No entanto, não há nada de errado com uma solução @Matches do validador de nível de classe personalizado .
fonte
As validações entre campos podem ser feitas criando restrições personalizadas.
Exemplo: - Compare os campos de senha e confirmPassword da instância do usuário.
CompareStrings
StringComparisonMode
CompareStringsValidator
ConstraintValidatorHelper
Do utilizador
Teste
Resultado
Message:- [Password, ConfirmPassword] must be equal.
Usando a restrição de validação CompareStrings, também podemos comparar mais de duas propriedades e misturar qualquer um dos quatro métodos de comparação de string.
ColorChoice
Teste
Resultado
Message:- Please choose three different colors.
Da mesma forma, podemos ter restrições de validação de campos cruzados CompareNumbers, CompareDates etc.
PS: Eu não testei esse código no ambiente de produção (apesar de tê-lo testado no ambiente de desenvolvimento), portanto, considere esse código como Milestone Release. Se você encontrar um bug, escreva um bom comentário. :)
fonte
Tentei o exemplo de Alberthoven (hibernate-validator 4.0.2.GA) e recebo uma ValidationException: „Métodos anotados devem seguir a convenção de nomenclatura do JavaBeans. match () não. Depois que eu renomeei o método de „match“ para "isValid", ele funciona.
fonte
Se você estiver usando o Spring Framework, poderá usar o Spring Expression Language (SpEL) para isso. Eu escrevi uma pequena biblioteca que fornece o validador JSR-303 baseado em SpEL - facilita muito as validações entre campos! Dê uma olhada em https://github.com/jirutka/validator-spring .
Isso validará o comprimento e a igualdade dos campos de senha.
Você também pode modificar isso facilmente para validar os campos de senha apenas quando não estiverem ambos vazios.
fonte
Gosto da ideia de Jakub Jirutka de usar o Spring Expression Language. Se você não deseja adicionar outra biblioteca / dependência (assumindo que você já usa o Spring), aqui está uma implementação simplificada de sua ideia.
A restrição:
O validador:
Aplique assim:
fonte
Não tenho reputação de comentar a primeira resposta, mas gostaria de acrescentar que adicionei testes de unidade para a resposta vencedora e tenho as seguintes observações:
fonte
Bradhouse solução muito agradável. Existe alguma maneira de aplicar a anotação @Matches a mais de um campo?
Edição: Aqui está a solução que eu encontrei para responder a esta pergunta, eu modifiquei a restrição para aceitar uma matriz em vez de um único valor:
O código para a anotação:
E a implementação:
fonte
Você precisa chamá-lo explicitamente. No exemplo acima, o bradhouse forneceu todas as etapas para escrever uma restrição personalizada.
Adicione esse código à sua classe de chamada.
no caso acima, seria
fonte
Por que não tentar Oval: http://oval.sourceforge.net/
Parece que ele suporta OGNL, então talvez você possa fazê-lo de uma forma mais natural
fonte
Caras, vocês são incríveis. Idéias realmente incríveis. Eu gosto mais de Alberthoven e McGin , então decidi combinar as duas idéias. E desenvolva uma solução genérica para atender a todos os casos. Aqui está a minha solução proposta.
fonte
Fiz uma pequena adaptação na solução do Nicko para que não seja necessário usar a biblioteca Apache Commons BeanUtils e substituí-la pela solução já disponível na primavera, para aqueles que a utilizam, como posso ser mais simples:
fonte
Solução solucionada com a pergunta: Como acessar um campo descrito na propriedade de anotação
E como usá-lo ...? Como isso:
fonte