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

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. 用zcat查看压缩日志中百度抓取的量

    比如查看124.251.44.85这一台服务器的07-13,07-14,07-15的日志中百度抓取http://www.baidu.com/search/spider.html 的量 wc命令参考博客 ...

  2. jquery 1.9里面已经删除了toggle(fn1, fn2)函数:

    jquery 1.9里面已经删除了toggle(fn1, fn2)函数:引用Note: This method signature was deprecated in jQuery 1.8 and r ...

  3. POJ3013 Big Christmas Tree

    题目:http://poj.org/problem?id=3013 求每个点到1的最短路.不是最小生成树. 总是WA.看讨论里说INF至少2e10,于是真的A了! 算一下,dis最大可能3276800 ...

  4. CC2530中串口波特率改为9600时单个数据包来不及接收的解决方案

    在调试CC2530过程中发现波特率改为9600时,单个包仅有3个Byte时,接收DMA就会启动 因而数据包被强迫拆分成多个,显然只要将接收DMA启动延时做到足够大即可. 具体修改内容如下图所示: 经过 ...

  5. Thinkphp自动验证规则

    其实说白了,这篇文章就是转给自己看的,省的下次用的时候满网络找了.有需要的同学也可以看看.自动验证是非常有用的一个技术.平常的验证基本就是,用户名是否为空,用户名是否重复,密码,重复密码是否一致.官方 ...

  6. 【shell】grep命令

    1.作用Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全局 ...

  7. innotop监控mysql

    InnoTop 是一个系统活动报告,类似于Linux性能工具,它与Linux的top命令相仿,并参考mytop工具而设计. 它专门用后监控InnoDB性能和MySQL服务器.主要用于监控事务,死锁,外 ...

  8. Oracle 10g下emctl start dbconsole 报错:OC4J Configuration issue 问题解决

    http://blog.sina.com.cn/s/blog_95b5eb8c0100x4a7.html http://blog.csdn.net/sz_bdqn/article/details/17 ...

  9. ComboBox智能搜索功能

    cmbList.AutoCompleteSource = AutoCompleteSource.ListItems; cmbList.AutoCompleteMode = AutoCompleteMo ...

  10. 【C#】datetimepicker里面如何设置日期为当天日期,而时间设为0:00或23:59?

    今天无意中发现要根据日期查询时间,datatimepicker控件会把时间默认成当前时间(当你的控件只显示日期时),这样查询出来的出来的数据会有误差,用来下面的办法成功设置日期为当天日期,而时间设为0 ...