针对对象、对象成员、方法、构造函数的数据验证。

1. 一个验证的小例子

(1) 添加引用jar

<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.7.Final</version>
</dependency> <dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.1-b09</version>
</dependency>

(2) 编写工具类

public static <T> void validate(T t) throws ValidationException {
ValidatorFactory vFactory = Validation.buildDefaultValidatorFactory();
Validator validator = vFactory.getValidator(); Set<ConstraintViolation<T>> set = validator.validate(t);
if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage());
}
throw new ValidationException(validateError.toString());
}
}

(3) 编写bean

package beans;

import javax.validation.constraints.NotNull;

public class Person {
@NotNull(message="用户名不能为空")
private String username; public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
}
}

(4) 编写测试类

package init;

import javax.xml.bind.ValidationException;

import beans.Person;
import validation.ValidationUtil; public class Test {
public static void main(String [] args ){
Person person = new Person();
try {
ValidationUtil.validate(person);
} catch (ValidationException e) {
System.out.println(e.getMessage()); //输出结果是:用户名不能为空
} }
}

(5)输出结果

用户名不能为空

2. 内置bean验证约束

(1)@AsserFalse
字段的值必须是false.
(2)@AsserTrue
字段的值必须是true.
(3)@DecimalMax
字段的值必须是一个小数值,应小于或者等于value元素中的数
(4)@DecimalMin
字段的值必须是一个小数值,应该大于或者等于value元素中的数
(5)@Digits
字段必须是指定范围内的一个数,integer元素指定了这个数的最大小整数位数,ftaction元素指定这个数的最大小数
(6)@Future
字段的值必须是将来一个日期
(7)@Max
字段必须是一个整数类型,应该小于或者等于value的数
(8)@Min
字段必须一个整数类型,应该大于或者等于value的数
(9)NotNull
字段的值必须不能为空
(10)@Null
字段的值必须为空
(11)@Past
字段的值必须是过去的一个日期
(12)@Pattern
字段的值必须与正则表达式匹配

(13)@Size

字段的大小,必须指定在一个范围匹配

package beans.validation;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map; import javax.validation.constraints.AssertFalse;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Digits;
import javax.validation.constraints.Future;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Null;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size; public class BuiltInValidationBean {
    @AssertTrue(message="isActive    @AssertTrue    值应该为true")
    private boolean isActive;
    
    @AssertFalse(message="isUnsupported    @AssertFalse    值应该为false")
    private boolean isUnsupported;
    
    @Max(value=100, message="quantityMax    @Max    最大值是100")
    private int quantityMax;
    
    @Min(value=10, message="quantityMin    @Min    最小值是10")
    private int quantityMin;
    
    @DecimalMax(value="100", message="discountMax    @DecimalMax 最大值是100")
    private BigDecimal discountMax;
    
    @DecimalMin(value="10", message="discountMin    @DecimalMin 最小值是10")
    private BigDecimal discountMin;     @Digits(integer=3, fraction=1, message="price    @Digits    最大整数位数是3, 最大小数位数是1")
    private BigDecimal price;
    
    @Future(message="eventDate    @Future    字段值必须是一个将来的日期")
    private Date eventDate;
    
    @Past(message="birthday    @Past    字段值必须是一个过去的日期")
    private Date birthday;     @NotNull(message="username    @NotNull    username不能为空")
    private String username;  
    
    @Null(message="unusedString    @Null    unusedString必须为空")
    private String unusedString;  
    
    @Pattern(regexp="\\(\\d(3)\\)\\d{9}", message="phoneNumber    @Pattern    手机号码不正确")
    private String phoneNumber;
    
    @Size(min=2, max=8, message="briefMessage    @Size    字符串最短2,最长8")
    private String briefMessage;
    
    @Size(min=2, max=8, message="briefList    @Size    list最短2,最长8")
    private List<String> briefList;
    
    @Size(min=2, max=8, message="briefMap    @Size    map最短2,最长8")
    private Map<String, String> briefMap;     public boolean isActive() {
        return isActive;
    }     public void setActive(boolean isActive) {
        this.isActive = isActive;
    }     public boolean isUnsupported() {
        return isUnsupported;
    }     public void setUnsupported(boolean isUnsupported) {
        this.isUnsupported = isUnsupported;
    }     public int getQuantityMax() {
        return quantityMax;
    }     public void setQuantityMax(int quantityMax) {
        this.quantityMax = quantityMax;
    }     public int getQuantityMin() {
        return quantityMin;
    }     public void setQuantityMin(int quantityMin) {
        this.quantityMin = quantityMin;
    }     public BigDecimal getDiscountMax() {
        return discountMax;
    }     public void setDiscountMax(BigDecimal discountMax) {
        this.discountMax = discountMax;
    }     public BigDecimal getDiscountMin() {
        return discountMin;
    }     public void setDiscountMin(BigDecimal discountMin) {
        this.discountMin = discountMin;
    }     public BigDecimal getPrice() {
        return price;
    }     public void setPrice(BigDecimal price) {
        this.price = price;
    }     public Date getEventDate() {
        return eventDate;
    }     public void setEventDate(Date eventDate) {
        this.eventDate = eventDate;
    }     public Date getBirthday() {
        return birthday;
    }     public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }     public String getUsername() {
        return username;
    }     public void setUsername(String username) {
        this.username = username;
    }     public String getUnusedString() {
        return unusedString;
    }     public void setUnusedString(String unusedString) {
        this.unusedString = unusedString;
    }     public String getPhoneNumber() {
        return phoneNumber;
    }     public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }     public String getBriefMessage() {
        return briefMessage;
    }     public void setBriefMessage(String briefMessage) {
        this.briefMessage = briefMessage;
    }     public List<String> getBriefList() {
        return briefList;
    }     public void setBriefList(List<String> briefList) {
        this.briefList = briefList;
    }     public Map<String, String> getBriefMap() {
        return briefMap;
    }     public void setBriefMap(Map<String, String> briefMap) {
        this.briefMap = briefMap;
    }
}

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

Validates all constraints on object -- 验证所有字段

	static ValidatorFactory vFactory = Validation.buildDefaultValidatorFactory();
static Validator validator = vFactory.getValidator();
static ExecutableValidator executableValidator = validator.forExecutables(); public static <T> void validate(T object, Class<?>... groups) throws ValidationException {
Set<ConstraintViolation<T>> set = validator.validate(object, groups); if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
validateError.append("validate:\r\n"); for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage()).append("\r\n");
} throw new ValidationException(validateError.toString());
}
}

        BuiltInValidationBean builtInValidationBean = new BuiltInValidationBean();
        
        builtInValidationBean.setActive(false);
        builtInValidationBean.setUnsupported(true);
        
        builtInValidationBean.setQuantityMax(101);
        builtInValidationBean.setQuantityMin(9);
        
        builtInValidationBean.setDiscountMax(new BigDecimal("100.1"));
        builtInValidationBean.setDiscountMin(new BigDecimal("9.9"));
        
        builtInValidationBean.setPrice(new BigDecimal("9999"));
        
        builtInValidationBean.setEventDate(new Date(1999, 12, 31));
        builtInValidationBean.setBirthday(new Date(2999, 12, 31));
        
        builtInValidationBean.setUsername(null);
        builtInValidationBean.setUnusedString("test");
        
        builtInValidationBean.setPhoneNumber("");
        
        builtInValidationBean.setBriefMessage("");
        builtInValidationBean.setBriefList(new ArrayList<>(20));
        builtInValidationBean.setBriefMap(new HashMap<>(20));
        
        try {  
            ValidationUtil.validate(builtInValidationBean);  
        } catch (ValidationException e) {  
            System.out.println("builtInValidationTest--validate");
            System.out.println(e.getMessage());
        }

输出结果

builtInValidationTest--validate
username    @NotNull    username不能为空
briefMessage    @Size    字符串最短2,最长8
quantityMin    @Min    最小值是10
isUnsupported    @AssertFalse    值应该为false
unusedString    @Null    unusedString必须为空
discountMax    @DecimalMax 最大值是100
price    @Digits    最大整数位数是3, 最大小数位数是1
discountMin    @DecimalMin 最小值是10
isActive    @AssertTrue    值应该为true
quantityMax    @Max    最大值是100
birthday    @Past    字段值必须是一个过去的日期
briefList    @Size    list最短2,最长8
phoneNumber    @Pattern    手机号码不正确
briefMap    @Size    map最短2,最长8

Validates all constraints placed on the property of object named propertyName -- 验证指定字段

	public static <T> void validateProperty(T object, String propertyName, Class<?>... groups) throws ValidationException {
ValidatorFactory vFactory = Validation.buildDefaultValidatorFactory();
Validator validator = vFactory.getValidator(); Set<ConstraintViolation<T>> set = validator.validateProperty(object, propertyName, groups);
if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
validateError.append("validateProperty:\r\n"); for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage()).append("\r\n");
} throw new ValidationException(validateError.toString());
}
}

        builtInValidationBean = new BuiltInValidationBean();
        builtInValidationBean.setBriefMessage("");
        
        try {  
            ValidationUtil.validateProperty(builtInValidationBean, "briefMessage");  
        } catch (ValidationException e) {  
            System.out.println("builtInValidationTest--validateProperty");
            System.out.println(e.getMessage());
        }

输出结果

builtInValidationTest--validateProperty
briefMessage    @Size    字符串最短2,最长8

正则表达式全部符号解释

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符。序列 '\\' 匹配 "\" 而 "\(" 则匹配 "("。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
* 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n} n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,} n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
(pattern) 匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '\(' 或 '\)'。
(?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y 匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz] 字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\cx 匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。.
\num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n 标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

3. 验证Null和空串

允许JSF将空串当作null处理

<context-param>
<param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
<param-value>true</param-value>
</context-param>

如果某个元素有@NotNull约束, 且以上为true,则会传入null到bean验证, 会使@NotNull约束失败。

4. 验证构造函数

针对构造函数的参数设置bean约束;

package beans.validation;

import java.math.BigDecimal;

import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull; public class ConstructorValidationBean {
private String name; private BigDecimal salary; private String currency; public ConstructorValidationBean(
@NotNull(message="name不能为空") String name,
@NotNull(message="salary不能为空")
@Digits(integer=6, fraction=2, message="工资最大整数位数是6, 最大小数位数是2") BigDecimal salary,
@NotNull(message="currency不能为空") String currency) {
this.name = name;
this.salary = salary;
this.currency = currency;
} @NotNull(message="name/salary 不能为空") //跨参数约束, 应用于构造函数中所有参数
public ConstructorValidationBean(String name, BigDecimal salary) {
this.name = name;
this.salary = salary;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public BigDecimal getSalary() {
return salary;
} public void setSalary(BigDecimal salary) {
this.salary = salary;
} public String getCurrency() {
return currency;
} public void setCurrency(String currency) {
this.currency = currency;
} }

	public static <T> void validateConstructorParameters(Constructor<? extends T> constructor, Object[] parameterValues, Class<?>... groups) throws ValidationException {
Set<ConstraintViolation<T>> set = executableValidator.validateConstructorParameters(constructor, parameterValues, groups);
if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
validateError.append("validateConstructorParameters:\r\n"); for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage()).append("\r\n");
} throw new ValidationException(validateError.toString());
}
} public static <T> void validateConstructorReturnValue(Constructor<? extends T> constructor, T createdObject, Class<?>... groups) throws ValidationException {
Set<ConstraintViolation<T>> set = executableValidator.validateConstructorReturnValue(constructor, createdObject, groups);
if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
validateError.append("validateConstructorReturnValue:\r\n"); for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage()).append("\r\n");
} throw new ValidationException(validateError.toString());
}
}

	@Test
public void constructorValidationBeanTest() throws Exception {
Constructor<? extends ConstructorValidationBean> constructor = ConstructorValidationBean.class.getConstructor(String.class, BigDecimal.class, String.class);
Object[] parameterValues = { null, new BigDecimal("8888888.88"),null }; try {
ValidationUtil.validateConstructorParameters(constructor, parameterValues);
} catch (ValidationException e) {
System.out.println("constructorValidationBean--validateConstructorParameters");
System.out.println(e.getMessage());
} constructor = ConstructorValidationBean.class.getConstructor(String.class, BigDecimal.class);
parameterValues = new Object[]{null, new BigDecimal("8888888.88")};
try {
ValidationUtil.validateConstructorReturnValue(constructor, parameterValues);
} catch (ValidationException e) {
System.out.println("constructorValidationBean--validateConstructorParameters--跨参数约束");
System.out.println(e.getMessage());
} constructor = ConstructorValidationBean.class.getConstructor(String.class, BigDecimal.class);
try {
ValidationUtil.validateConstructorReturnValue(constructor, new ConstructorValidationBean(null, new BigDecimal("8888888.88")));
} catch (ValidationException e) {
System.out.println("constructorValidationBean--validateConstructorReturnValue");
System.out.println(e.getMessage());
}

输出结果

constructorValidationBean--validateConstructorParameters
validateConstructorParameters:
name不能为空
currency不能为空
工资最大整数位数是6, 最大小数位数是2

5. 验证方法

针对非静态方法的参数以及非静态方法的返回值设置bean约束;

package beans.validation;

import java.util.ArrayList;
import java.util.List; import javax.validation.constraints.Max;
import javax.validation.constraints.Size; public class MethodValidationBean {
public void drive(@Max(80) int speedInMph) {
// ...
} @Size(min = 3, max = 8)
public List<String> getPassengers() {
return new ArrayList<>();
}
}
	public static <T> void validateParameters(T object, Method method, Object[] parameterValues, Class<?>... groups) throws ValidationException {
Set<ConstraintViolation<T>> set = executableValidator.validateParameters(object, method, parameterValues, groups); if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
validateError.append("validateParameters:\r\n"); for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage()).append("\r\n");
} throw new ValidationException(validateError.toString());
}
} public static <T> void validateReturnValue(T object, Method method, Object returnValue, Class<?>... groups) throws ValidationException {
Set<ConstraintViolation<T>> set = executableValidator.validateReturnValue(object, method, returnValue, groups); if (set.size() > 0) {
StringBuilder validateError = new StringBuilder();
validateError.append("validateReturnValue:\r\n"); for (ConstraintViolation<T> val : set) {
validateError.append(val.getMessage()).append("\r\n");
} throw new ValidationException(validateError.toString());
}
}
	@Test
public void methodValidationBeanTest() throws Exception {
MethodValidationBean methodValidationBean = new MethodValidationBean();
Method method = MethodValidationBean.class.getMethod("drive", int.class);
Object[] parameterValues = { 81 }; try {
ValidationUtil.validateParameters(methodValidationBean, method, parameterValues);
} catch (ValidationException e) {
System.out.println("methodValidationBeanTest--validateParameters");
System.out.println(e.getMessage());
} method = MethodValidationBean.class.getMethod("getPassengers");
Object returnValue = Collections.emptyList(); try {
ValidationUtil.validateReturnValue(methodValidationBean, method, returnValue);
} catch (ValidationException e) {
System.out.println("methodValidationBeanTest--validateReturnValue");
System.out.println(e.getMessage());
}
}

执行结果

methodValidationBeanTest--validateParameters
validateParameters:
最大不能超过80

methodValidationBeanTest--validateReturnValue
validateReturnValue:
个数必须在3和8之间

6. 自定义约束

package beans.validation.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import javax.validation.Constraint;
import javax.validation.ConstraintTarget;
import javax.validation.Payload;
import javax.validation.constraints.Pattern; import validation.EmailValidator; @Pattern.List({
    @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+"+"(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*"+"@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
})
@Constraint(validatedBy={EmailValidator.class})
@Documented
@Target({
    ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Email {
    String message() default "invalid email";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
    String[] value() default {};
    
    //设置约束
//    ConstraintTarget validationAppliesTo() default ConstraintTarget.PARAMETERS;
    
    
    @Target({
        ElementType.METHOD,ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.CONSTRUCTOR,ElementType.PARAMETER
    })
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @interface List{
        Email[] value();
    }
}
package validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext; import beans.validation.annotation.Email; public class EmailValidator implements ConstraintValidator<Email, String> { @Override
public boolean isValid(String value, ConstraintValidatorContext context) {
System.out.println(value); return true;
} }
package beans.validation;

import beans.validation.annotation.Email;

public class EmailBean {
@Email
private String email; public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
}
}
    @Test
    public void selfDefineValidationBeanTest() {
        EmailBean emailBean = new EmailBean();
        emailBean.setEmail("email");
        
        try {
            ValidationUtil.validate(emailBean);
        } catch (ValidationException e) {  
            System.out.println("selfDefineValidationBeanTest--validate");
            System.out.println(e.getMessage());
        }
    }

执行结果
email
selfDefineValidationBeanTest--validate
validate:
需要匹配正则表达式"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"

去除约束目标的二义性

ConstraintTarget validationAppliesTo() default ConstraintTarget.PARAMETERS;

???

http://blog.csdn.net/java_1111/article/details/22603731

https://www.ibm.com/support/knowledgecenter/zh/SSEQTP_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/cdat_beanvaljpa.html

7. 组合约束

(1) 验证组

约束组由接口表示,约束组也可由其它组继承(到时候也会验证超类中的所有约束)

interface Employee{}

interface Manager extends Employee{}

interface Contractor{}

指定约束组

package beans.validation;

import javax.validation.constraints.NotNull;

public class ConstraintGroupBean {
    @NotNull(groups={Employee.class, Contractor.class})
    private String workPhone;     @NotNull(groups=Contractor.class)
    private String homePhone;     public String getWorkPhone() {
        return workPhone;
    }     public void setWorkPhone(String workPhone) {
        this.workPhone = workPhone;
    }     public String getHomePhone() {
        return homePhone;
    }     public void setHomePhone(String homePhone) {
        this.homePhone = homePhone;
    }
}

缺省情况下,如果在单个约束上没有指定验证组或多个组,那么使用 javax.validation.groups.Default 组来予以验证

(2) 指定验证顺序 GroupSequence

GroupSequence中第一个验证过了,才会验证第二个

https://www.jianshu.com/p/cf51061de60c?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes

https://stackoverflow.com/questions/30359124/java-groupsequenceprovider-for-validation-object-is-null-in-getvalidationgroup#

8. 使用 META-INF/validation.xml

https://docs.oracle.com/javaee/6/api/javax/validation/Configuration.html

java ee7 -- Java Bean验证的更多相关文章

  1. 开涛spring3(12.4) - 零配置 之 12.4 基于Java类定义Bean配置元数据

    12.4  基于Java类定义Bean配置元数据 12.4.1  概述 基于Java类定义Bean配置元数据,其实就是通过Java类定义Spring配置元数据,且直接消除XML配置文件. 基于Java ...

  2. java ee7 配置文件

    java ee7 配置文件 1. 项目目录 # ee pom.xml      Maven构建文件 /src/main/java      Java源文件 /src/main/resource     ...

  3. Java中的数据验证

    原文链接:https://www.cuba-platform.com/blog/2018-10-09/945 翻译:CUBA China CUBA-Platform 官网 : https://www. ...

  4. Java中的参数验证(非Spring版)

    1. Java中的参数验证(非Spring版) 1.1. 前言 为什么我总遇到这种非正常问题,我们知道很多时候我们的参数校验都是放在controller层的传入参数进行校验,我们常用的校验方式就是引入 ...

  5. Spring学习系列(三) 通过Java代码装配Bean

    上面梳理了通过注解来隐式的完成了组件的扫描和自动装配,下面来学习下如何通过显式的配置的装配bean 二.通过Java类装配bean 在前面定义了HelloWorldConfig类,并使用@Compon ...

  6. xml配置和基于java类的bean配置搭配使用

    如果同时使用了xml配置,和java类的bean配置(当然估计项目中一般不会这样), 在初始化容器指定资源文件的时候可能会比较麻烦 此时我们可以把基于java类的bean配置整合到xml中,或xml的 ...

  7. 使用java连接AD域,验证账号password是否正确

    web项目中有时候客户要求我们使用ad域进行身份确认,不再另外做一套用户管理系统.事实上客户就是仅仅要一套账号能够訪问全部的OA.CRM等办公系统. 这就是第三方验证.一般有AD域,Ldap,Radi ...

  8. java工具类(二)之java正则表达式表单验证

    java正则表达式表单验证类工具类(验证邮箱.手机号码.qq号码等) 这篇文章主要介绍了java使用正则表达式进行表单验证工具类,可以验证邮箱.手机号码.qq号码等方法,需要的朋友可以参考下. jav ...

  9. Spring Boot 使用Java代码创建Bean并注册到Spring中

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/catoop/article/details/50558333 声明同一个类下的多个实例: packa ...

随机推荐

  1. Hadoop操作前准备工作

    摘要:本文介绍Hadoop操作前的准备工作. 关键词:Hadoop  Linux   JDK  WinSCP 俗语说,“磨刀不误砍柴工”.Hadoop操作前的准备工作可以加快Hadoop的操作与应用. ...

  2. leetcode:Pascal's Triangle【Python版】

    1.这道题一次提交就AC了: 2.以前用C语言实现的话,初始化二维数组全部为0,然后每行第一个元素为1,只需要用a[i][j] = a[i-1][j]+a[i-1][j-1]就可以了: 3.在Pyth ...

  3. TensorFlow笔记-08-过拟合,正则化,matplotlib 区分红蓝点

    TensorFlow笔记-08-过拟合,正则化,matplotlib 区分红蓝点 首先提醒一下,第7讲的最后滑动平均的代码已经更新了,代码要比理论重要 今天是过拟合,和正则化,本篇后面可能或更有兴趣, ...

  4. 罗技 M558 鼠标维修记录

    罗技 M558 鼠标维修记录 故障现象 按键不灵敏 拆机内部图 前进键 后退键 左键 右键 中键 自定义功能键 使用的是 OMRON 按键,好东西,质量可以. 但毕竟是机械的东西,还是有老化,用万用表 ...

  5. Microsoft Dynamics CRM 2011 配置好的IFD环境 怎么制作证书?

    一.CRM2011 IFD怎么制作证书? 配置好的IFD环境里面:打开开始—运行 1.输入: mmc(微软管理控制台) 出现: 2. 出现: 3.添加/删除管理单元,如图: 4.添加证书 5. 6. ...

  6. js jquery 设置cookie

    转自http://yaoqianglilan.blog.163.com/blog/static/70978316201091810435251/ 本人亲测setcookie() getcookie() ...

  7. Java中对话框的弹出

    最近在做学校的课程设计,java编程需要用到对话框弹出,第一反应是js中的alert和confirm,java的话瞬间懵,查阅学习总结如下,用以以后的学习 1.显示一个错误对话框,该对话框显示的 me ...

  8. sigar在Centos和Windows下使用java系统软硬件配置信息

    背景 本来这个网上一大堆实在没什么想写的,但是好像大多数都是互相抄袭的,在centos根本上用不了,因此我整理下自己具体实现的步骤. 使用环境 sigar版本:hyperic-sigar-1.6.4  ...

  9. spring SOA architecture

    在谈这个之前,还得再说下SOA和平台.SOA做两件事情,一个是解耦并识别可重用的服务,一个是对服务进行灵活组装和编排满足业务需求,SOA核心是业务和技术的解耦,服务和能力的复用.而在IT领域的平台平台 ...

  10. class^=是什么意思啊,在css中 5

    这是css属性选择器的一种:[attribute^=value] ,用来匹配属性值以指定值开头的每个元素.例如: [class^="test"] { background:#fff ...