jsr validator
Welcome to Hibernate Validator Example Tutorial. Data validation is integral part of any application. You will find data validation at presentation layer with the use of Javascript. Then at the server side code before processing the client data. Also data validation occurs before persisting it, to make sure it follows the correct format.
欢迎使用Hibernate Validator示例教程。 数据验证是任何应用程序不可或缺的一部分。 您将在使用Javascript的表示层进行数据验证。 然后在服务器端代码之前处理客户端数据。 数据验证也将在持久化之前进行,以确保其遵循正确的格式。
Hibernate验证器 (Hibernate Validator)
Validation is a cross cutting task, so we should try to keep it apart from our business logic. That’s why JSR303 and JSR349 provides specification for validating a bean by using annotations. Hibernate Validator provides the reference implementation of both these bean validation specs.
验证是一项跨领域的任务,因此我们应尝试将其与业务逻辑分开。 这就是JSR303和JSR349提供使用注释来验证bean的规范的原因。 Hibernate Validator提供了这两个bean验证规范的参考实现。
It’s very easy to use Hibernate Validator and best part is that we can easily extend it and create our own custom validation annotations. Today we will look into the hibernate validator in detail with examples. Finally we will have a test program to check out the validations.
使用Hibernate Validator非常容易,最好的部分是我们可以轻松扩展它并创建自己的自定义验证批注。 今天,我们将通过示例详细研究Hibernate验证器。 最后,我们将有一个测试程序来检查验证。
I have created a sample project for all the hibernate validation example, below image shows the final project structure.
我为所有Hibernate验证示例创建了一个示例项目,下图显示了最终的项目结构。
Hibernate Validator Maven依赖关系 (Hibernate Validator Maven Dependencies)
We need to add JSR303 and Hibernate Validator dependencies to use them.
我们需要添加JSR303和Hibernate Validator依赖项才能使用它们。
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.1.Final</version>
</dependency>
Hibernate Validator also requires an implementation of the Unified Expression Language (JSR 341) for evaluating dynamic expressions in constraint violation messages.
Hibernate Validator还需要实现统一表达式语言(JSR 341)来评估约束违例消息中的动态表达式。
If your application is running in a servlet container such as JBoss, it’s already provided. But if you are using it in a standalone application like my example project, you need to add them manually. Required dependencies are;
如果您的应用程序在JBoss之类的servlet容器中运行,则已经提供了它。 但是,如果要在像我的示例项目这样的独立应用程序中使用它,则需要手动添加它们。 所需的依赖关系是;
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
Check the image for all the maven dependencies in the project. Now we are ready to get started with hibernate validation examples.
检查映像中项目中所有的Maven依赖项。 现在,我们准备开始使用Hibernate验证示例。
Hibernate验证示例 (Hibernate Validation Example)
Let’s create a simple class and add some validations to it.
让我们创建一个简单的类,并向其中添加一些验证。
Employee.java
Employee.java
package com.journaldev.validator.hibernate.model;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.CreditCardNumber;
import org.hibernate.validator.constraints.Email;
public class Employee {
@Min(value=1, groups=EmpIdCheck.class)
private int id;
@NotNull(message="Name cannot be null")
@Size(min=5, max=30)
private String name;
@Email
private String email;
@CreditCardNumber
private String creditCardNumber;
//default no-args constructor
public Employee(){}
public Employee(int id, String name, String email, String ccNum){
this.id=id;
this.name=name;
this.email=email;
this.creditCardNumber=ccNum;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCreditCardNumber() {
return creditCardNumber;
}
public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}
}
We should avoid using implementation specific annotations for loose coupling. But hibernate validator provides some very good validation annotations such as @Email
and @CreditCardNumber
.
我们应该避免使用特定于实现的注释进行松散耦合。 但是Hibernate验证器提供了一些非常好的验证注释,例如@Email
和@CreditCardNumber
。
We can also provide custom error message to use with any validation. If there are no message defined then hibernate built-in error message will be used.
我们还可以提供自定义错误消息以用于任何验证。 如果未定义任何消息,则将使用Hibernate内置错误消息。
We can assign groups to any validation, this can be useful to validate a set of fields only. For example, if I just need to validate the Employee id field, I can use EmpIdCheck
group. For this we need to define a class/interface.
我们可以将组分配给任何验证,这仅对验证一组字段有用。 例如,如果我只需要验证Employee id字段,则可以使用EmpIdCheck
组。 为此,我们需要定义一个类/接口。
EmpIdCheck.java
EmpIdCheck.java
package com.journaldev.validator.hibernate.model;
public interface EmpIdCheck {
}
We will look it’s usage in the test program later on.
稍后我们将在测试程序中查看它的用法。
Hibernate Validator自定义错误消息 (Hibernate Validator Custom Error Messages)
We can define our custom error messages too, all we need is to have ValidationMessages.properties
file in the classpath.
我们也可以定义自定义错误消息,我们所需要的只是在类路径中包含ValidationMessages.properties
文件。
ValidationMessages.properties
ValidationMessages.properties
#Hibernate Bug for @CreditCardNumber Workaround - https://hibernate.atlassian.net/browse/HV-881
org.hibernate.validator.constraints.LuhnCheck.message=The check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed.
org.hibernate.validator.constraints.Email.message=Invalid email address
These property files also support localization, in that case we need to keep file names like ValidationMessages_tr_TR.properties
这些属性文件还支持本地化,在这种情况下,我们需要保留诸如ValidationMessages_tr_TR.properties之类的文件名。
The property name for message is fully classified annotation name with message at the end, you can easily figure out from above examples.
消息的属性名称是完全分类的批注名称,末尾是message,您可以轻松地从以上示例中找出来。
基于XML的约束验证 (XML Based Constraints Validation)
Sometimes we want validation on third party classes, then we can’t use annotations with them. In this situation, xml configuration based validation comes handy. For example, let’s say we have a class without any validation annotations like below.
有时我们想对第三方类进行验证,然后就不能在它们上使用注释。 在这种情况下,基于xml配置的验证非常方便。 例如,假设我们有一个没有任何验证注释的类,如下所示。
EmployeeXMLValidation.java
EmployeeXMLValidation.java
package com.journaldev.validator.hibernate.model;
public class EmployeeXMLValidation {
private int id;
private String name;
private String email;
private String creditCardNumber;
//default no-args constructor
public EmployeeXMLValidation(){}
public EmployeeXMLValidation(int id, String name, String email, String ccNum){
this.id=id;
this.name=name;
this.email=email;
this.creditCardNumber=ccNum;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCreditCardNumber() {
return creditCardNumber;
}
public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}
}
A simple example for above bean hibernate validation could be like below.
上面的beanHibernate验证的一个简单示例如下所示。
employeeXMLValidation.xml
employeeXMLValidation.xml
<constraint-mappings xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.1.xsd"
xmlns="https://jboss.org/xml/ns/javax/validation/mapping" version="1.1">
<default-package>com.journaldev.validator.hibernate.model</default-package>
<bean class="EmployeeXMLValidation" ignore-annotations="true">
<field name="id">
<constraint annotation="javax.validation.constraints.Min">
<element name="value">1</element>
</constraint>
</field>
<field name="name">
<constraint annotation="javax.validation.constraints.NotNull" />
<constraint annotation="javax.validation.constraints.Size">
<element name="min">5</element>
<element name="max">30</element>
</constraint>
</field>
<field name="email">
<constraint annotation="org.hibernate.validator.constraints.Email" />
</field>
<field name="creditCardNumber">
<constraint annotation="org.hibernate.validator.constraints.CreditCardNumber" />
</field>
</bean>
</constraint-mappings>
default-package is used to define the base package, so that we can skip long package names.
default-package用于定义基本软件包,因此我们可以跳过长软件包名称。
ignore-annotations is used to tell Hibernate validator to ignore any annotations present in the class for validation purpose, only perform validations as configured in the xml file.
ignore-annotations用于告诉Hibernate验证程序忽略类中存在的用于验证目的的所有注释,仅执行xml文件中配置的验证。
We can have multiple bean validations in a single file, we need to load this file to validator factory configuration, an example of this will be given later on.
我们可以在一个文件中进行多个bean验证,我们需要将此文件加载到验证器的工厂配置,稍后将给出一个示例。
属性级别约束 (Property level constraints)
We can apply constraints on the getter methods too, we should not apply it on setter method. Also we should avoid applying constraints on both fields and getter method because then it will be validated twice.
我们也可以在getter方法上应用约束,我们不应该在setter方法上应用约束。 另外,我们应该避免在字段和getter方法上都应用约束,因为这样它将被两次验证。
MyBean.java
MyBean.java
package com.journaldev.validator.hibernate.model;
import javax.validation.constraints.NotNull;
public class MyBean {
private String name;
@NotNull
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
具有继承的Hibernate验证 (Hibernate Validation with Inheritance)
Bean validations are inherited, so if we are validating object of child class then any validations in parent class will also be executed.
Bean验证是继承的,因此,如果我们要验证子类的对象,则还将执行父类中的任何验证。
MyChildBean.java
MyChildBean.java
package com.journaldev.validator.hibernate.model;
import javax.validation.constraints.NotNull;
public class MyChildBean extends MyBean {
private String data;
@NotNull
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
If we will validate instance of MyChildBean
, MyBean name field will also be validated.
如果我们将验证MyChildBean
实例,则MyBean名称字段也将得到验证。
使用@Valid批注进行组合验证 (Validation with Composition using @Valid annotation)
We can use @Valid
annotation incase of composition, so that it’s validations are executed.
我们可以在组合的情况下使用@Valid
批注,以便执行其验证。
AnotherBean.java
AnotherBean.java
package com.journaldev.validator.hibernate.model;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
public class AnotherBean {
@NotNull
@Valid
private MyChildBean childBean;
public MyChildBean getChildBean() {
return childBean;
}
public void setChildBean(MyChildBean childBean) {
this.childBean = childBean;
}
}
Now if we validate AnotherBean
instance, MyChildBean
object will also be validated.
现在,如果我们验证AnotherBean
实例, MyChildBean
验证MyChildBean
对象。
方法参数Hibernate验证 (Method Parameter Hibernate Validation)
We can define constraints for method parameters too, a simple example is given below.
我们也可以定义方法参数的约束,下面给出一个简单的例子。
ParamValidationBean.java
ParamValidationBean.java
package com.journaldev.validator.hibernate.model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public class ParamValidationBean {
private String name;
//using @NotNull at constructor rather than at field
public ParamValidationBean(@NotNull String name){
this.name = name;
}
public void printData(@NotNull @Size(min=5) String data){
System.out.println("Data is::"+data);
}
public String getName() {
return name;
}
}
Hibernate Validator示例测试程序 (Hibernate Validator Example Test Program)
We have seen a lot of validation scenarios, here is the test program to show the process to validate them.
我们已经看到了很多验证方案,这里是测试程序,以显示验证它们的过程。
ValidatorTest.java
ValidatorTest.java
package com.journaldev.validator.hibernate.main;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.lang.reflect.Method;
import java.util.Set;
import javax.validation.Configuration;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import javax.validation.executable.ExecutableValidator;
import org.hibernate.validator.HibernateValidator;
import com.journaldev.validator.hibernate.model.AnotherBean;
import com.journaldev.validator.hibernate.model.EmpIdCheck;
import com.journaldev.validator.hibernate.model.Employee;
import com.journaldev.validator.hibernate.model.EmployeeXMLValidation;
import com.journaldev.validator.hibernate.model.MyChildBean;
import com.journaldev.validator.hibernate.model.ParamValidationBean;
public class ValidatorTest {
public static void main(String[] args) throws FileNotFoundException, NoSuchMethodException, SecurityException {
//Getting Validator instance with Annotations
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
//If there are multiple JSR303 implementations in classpath
//we can get HibernateValidator specifically too
ValidatorFactory hibernateVF = Validation.byProvider(HibernateValidator.class)
.configure().buildValidatorFactory();
System.out.println("\nSimple field level validation example");
Employee emp = new Employee(-1, "Name","email","123");
Set<ConstraintViolation<Employee>> validationErrors = validator.validate(emp);
if(!validationErrors.isEmpty()){
for(ConstraintViolation<Employee> error : validationErrors){
System.out.println(error.getMessageTemplate()+"::"+error.getPropertyPath()+"::"+error.getMessage());
}
}
System.out.println("\nXML Based validation example");
//XML Based validation
Configuration<?> config = Validation.byDefaultProvider().configure();
config.addMapping(new FileInputStream("employeeXMLValidation.xml"));
ValidatorFactory validatorFactory1 = config.buildValidatorFactory();
Validator validator1 = validatorFactory1.getValidator();
EmployeeXMLValidation emp1 = new EmployeeXMLValidation(10, "Name","email","123");
Set<ConstraintViolation<EmployeeXMLValidation>> validationErrors1 = validator1.validate(emp1);
if(!validationErrors1.isEmpty()){
for(ConstraintViolation<EmployeeXMLValidation> error : validationErrors1){
System.out.println(error.getMessageTemplate()+"::"+error.getInvalidValue()+"::"+ error.getPropertyPath()+"::"+error.getMessage());
}
}
System.out.println("\nValidation Group example");
validationErrors = validator.validate(emp, EmpIdCheck.class);
if(!validationErrors.isEmpty()){
for(ConstraintViolation<Employee> error : validationErrors){
System.out.println(error.getMessageTemplate()+"::"+error.getPropertyPath()+"::"+error.getMessage());
}
}
System.out.println("\nValidation with inheritance example");
//Validation inheritance and Property-level constraints example
MyChildBean childBean = new MyChildBean();
Set<ConstraintViolation<MyChildBean>> validationInheritanceErrors = validator.validate(childBean);
if(!validationInheritanceErrors.isEmpty()){
for(ConstraintViolation<MyChildBean> error : validationInheritanceErrors){
System.out.println(error.getMessageTemplate()+"::"+error.getPropertyPath()+"::"+error.getMessage());
}
}
System.out.println("\nValidation in composition using @Valid annotation");
//@Valid annotation - validation in composition example
AnotherBean compositionBean = new AnotherBean();
compositionBean.setChildBean(new MyChildBean());
Set<ConstraintViolation<AnotherBean>> validationCompositionErrors = validator.validate(compositionBean);
if(!validationCompositionErrors.isEmpty()){
for(ConstraintViolation<AnotherBean> error : validationCompositionErrors){
System.out.println(error.getMessageTemplate()+"::"+error.getPropertyPath()+"::"+error.getMessage());
}
}
System.out.println("\nParameter validation example");
ParamValidationBean paramValidationBean = new ParamValidationBean("Pankaj");
Method method = ParamValidationBean.class.getMethod("printData", String.class);
Object[] params = {"1234"};
ExecutableValidator executableValidator = validator.forExecutables();
Set<ConstraintViolation<ParamValidationBean>> violations =
executableValidator.validateParameters(paramValidationBean, method, params);
if(!violations.isEmpty()){
for(ConstraintViolation<ParamValidationBean> error : violations){
System.out.println(error.getMessageTemplate()+"::"+error.getPropertyPath()+"::"+error.getMessage());
}
}
}
}
When we run above hibernate validator example program, we get following output.
当我们在Hibernate验证器示例程序之上运行时,我们得到以下输出。
Jul 25, 2014 3:51:56 AM org.hibernate.validator.internal.util.Version <clinit>
INFO: HV000001: Hibernate Validator 5.1.1.Final
Simple field level validation example
{javax.validation.constraints.Size.message}::name::size must be between 5 and 30
{org.hibernate.validator.constraints.CreditCardNumber.message}::creditCardNumber::invalid credit card number
{org.hibernate.validator.constraints.Email.message}::email::Invalid email address
XML Based validation example
{org.hibernate.validator.constraints.Email.message}::email::email::Invalid email address
{javax.validation.constraints.Size.message}::Name::name::size must be between 5 and 30
{org.hibernate.validator.constraints.CreditCardNumber.message}::123::creditCardNumber::invalid credit card number
Validation Group example
{javax.validation.constraints.Min.message}::id::must be greater than or equal to 1
Validation with inheritance example
{javax.validation.constraints.NotNull.message}::data::may not be null
{javax.validation.constraints.NotNull.message}::name::may not be null
Validation in composition using @Valid annotation
{javax.validation.constraints.NotNull.message}::childBean.data::may not be null
{javax.validation.constraints.NotNull.message}::childBean.name::may not be null
Parameter validation example
{javax.validation.constraints.Size.message}::printData.arg0::size must be between 5 and 2147483647
Important points from above hibernate validator test program are:
来自Hibernate验证器测试程序的重要要点是:
- Validator instance is thread safe, so we can cache it and reuse it. Validator实例是线程安全的,因此我们可以对其进行缓存并重新使用。
- If there are multiple JSR303 implementation present, then we can get the Hibernate Validator instance using
Validation.byProvider()
method. 如果存在多个JSR303实现,则可以使用Validation.byProvider()
方法获取Hibernate Validator实例。 - Notice the use of validation of a group, it’s validating only the fields that are part of the group. 请注意,使用了组验证,它只验证组中的字段。
- ExecutableValidator is used to validate the parameters of a method. ExecutableValidator用于验证方法的参数。
ExecutableValidator
provide methods to validate constructor parameters and return values too, these methods arevalidateReturnValue()
,validateConstructorParameters()
andvalidateConstructorReturnValue()
ExecutableValidator
提供验证构造函数参数和返回值的方法,这些方法是validateReturnValue()
,validateConstructorParameters()
和validateConstructorReturnValue()
Hibernate Validator自定义验证和Spring Framework集成 (Hibernate Validator Custom Validation and Spring Framework integration)
We can create our own custom validator too, please read Spring Hibernate Validator Example for better understanding of this feature.
我们也可以创建自己的自定义验证器,请阅读Spring Hibernate Validator Example以更好地了解此功能。
Hibernate验证器摘要 (Hibernate Validator Summary)
Hibernate Validator and JSR303 together provides base of cross cutting bean validation implementation, if used properly with Aspect Oriented Programming, we can separate all our bean validations from business logic. You can download the final project from below link and explore more.
Hibernate Validator和JSR303一起提供了跨领域bean验证实现的基础,如果与面向方面的编程正确使用,我们可以将所有bean验证与业务逻辑分开。 您可以从下面的链接下载最终项目并进行更多探索。
References:
Hibernate Validator
JSR 303
参考文献 :
Hibernate验证器
JSR 303
翻译自: https://www.journaldev.com/3626/hibernate-validator-jsr303-example-tutorial
jsr validator