Hibernate-validator校验框架

1. 前言

Validator开发者使用手册,适用后台校验功能的开发参考。

1.1. 背景

在我们日常后台的开发中,涉及到很多的字段验证,一般普通的验证框架就基本上可以满足日常的开发需求,但有一些情况,这些普通的验证框架无法达到要求,例如,我们必须对验证的属性进行分组,于是就产生了我们的Validator验证框架。当然,我们的验证框架不仅仅只提供了分组的功能。

2. 参考文档

Hibernate Validator - 5.1.0 - 英文版.pdf

3. 概览

3.1. 工作模式和配置模式

Validator提供两种工作模式:

1、普通模式

2、快速失败返回模式

默认的工作模式为快速失败返回模式,一旦发现校验失败项,立即返回。普通模式在测试时期可以使用,可以对全部的校验项进行完整的校验(校验组序列,以及基于校验组序列的其他配置无效),通过修改配置文件中的校验模式,从而实现工作模式的自由切换。开发人员无需关心其中的原理和过程。

两种配置模式:AnnotationXml文件(此处略)

推荐使用Annotation注解模式。

工作模式配置如下:

validator.fail_fast:快速失败返回模式(只要有一个验证失败,则返回异常)

validator.normal:普通模式(会校验完所有的属性,然后返回所有的验证失败信息)

3.2. 校验功能

Validator校验框架按照Bean Validation的规范,使用了Hibernate Validatior框架。当前通过测试验证的可以支持的功能有:

1、内置注解校验

2、对象图级联校验

3、校验组分组校验

4、校验组序列

5、自定义默认校验组功能

6、自定义智能默认校验组功能

7、自定义校验注解

8、类校验——类属性的关联校验

此外,框架还内嵌了一些非法校验的功能,比如输入的校验对象为null,或者指定的对象的属性值错误,都会自行抛出异常。

4. Validator的使用方法

4.1. Validatorjar

目前,Validator的版本为2.0.0,后面可能会涉及到版本的更新。原始工程为Maven工程,使用的时候,只需要导入Validator依赖的pom文件以及进行简单的配置即可。

<dependency>

<groupId>com.travelsky.common</groupId>

<artifactId>validate</artifactId>

<version>2.0.0</version>

</dependency>

4.2. Validator的配置文件

配置文件可以从jar包里面获取,使用的时候,直接加入类路径下即可。附件部分给出了Validator依赖的pom文件。配置文件如下:

<bean id="baseValidator" class="com.travelsky.common.validator.BaseValidator">

<property name="validatorMode">

        <!-- 校验器的工作模式:

validator.fail_fast:快速失败返回模式(只要有一个验证失败,则返回异常)

validator.normal:普通模式(会校验完所有的属性,然后返回所有的验证失败息)

        -->

<value>validator.normal</value>

</property>

</bean>

4.3. Validator接口

使用Validator的校验框架非常的简单,只需要注入Validator接口即可:

@Autowired

private Validator validator;

4.4. Validator中的方法

Validator提供了6个校验接口供开发人员使用:

1、<T> void validate(T object) throws Exception

用途:校验一个对象的默认校验组的属性。

2、<T> void validate(T object, Class<?>... groups) throws Exception

用途:校验一个对象的指定的一个或多个校验组的属性。

3、<T> void validateProperty(T object, String propertyName) throws Exception

用途:校验一个对象的默认校验组的一个指定的属性值。

4、<T> void validateProperty(T object, String propertyName, Class<?>... groups) throws Exception

用途:校验一个对象指定校验组中的一个指定的属性值。

5、<T> void validateValue(Class<T> beanType, String propertyName, Object value) throws Exception

用途:校验一个value是否符合指定类的默认校验组下的某一个属性值。

6、<T> void validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups) throws Exception

用途:校验一个value是否符合指定类的指定校验组下的某一个属性值。

4.5. 测试类

大家可以从工程源码的测试目录中,找到测试类,所有的测试类都可以正常运行,并加入了详细的注释说明。

5. 各个校验功能的开发指南

本章节提供了各种校验功能具体的开发方法,基本能够满足开发人员所有 的校验需求。(所有的实体类省略了getset方法)

5.1. 内置注解校验

适用场景:简单的单属性的校验。

内置的校验注解共分为三种:Bean Validation内置的校验注解和Hibernate Validator拓展的校验注解以及框架自带的校验注解。推荐大家首先考虑使用这些注解,简单易用。

使用方法:

public class RangeModel {

@Length(min=5, max=17)

private String length;

@Size(min=1, max=3)

private String age;

@Range(min=150,max=250)

private int high;

5.1.1. Bean Validator内置的注解

Annotation

支持的数据类型

作用

Hibernate metadata impact

@AssertFalse

Boolean, boolean

判断关联属性是否为布尔值false

没有

@AssertTrue

Boolean, boolean

Checks that the annotated element istrue.

没有

@DecimalMax

BigDecimal, BigInteger, String, byte, short, int,long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number.

被注解的值必须不大于约束中指定的最大值这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.

没有

@DecimalMin

BigDecimal, BigInteger, String, byte, short, int,long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number.

被注解的值必须不小于约束中指定的最小值这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.

没有

@Digits(integer=, fraction=)

BigDecimal, BigInteger, String, byte, short, int,long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number.

校验整数位数和小数位数

对应的数据库表字段会被设置精度(precision)和准度(scale).

@Future

java.util.Date, java.util.Calendar; Additionally supported by HV, if the Joda Time date/time API is on the class path: any implementations of ReadablePartial and ReadableInstant.

检查给定的日期是否比现在晚.

没有

@Max

BigDecimal, BigInteger, byte, short, int, longand the respective wrappers of the primitive types. Additionally supported by HV: String(the numeric value represented by a String is evaluated), any sub-type of Number.

检查该值是否小于或等于约束条件中指定的最大值.

会给对应的数据库表字段添加一个check的约束条件.

@Min

BigDecimal, BigInteger, byte, short, int, longand the respective wrappers of the primitive types. Additionally supported by HV: String(the numeric value represented by a String is evaluated), any sub-type of Number.

检查该值是否大于或等于约束条件中规定的最小值.

会给对应的数据库表字段添加一个check的约束条件.

@NotNull

Any type

Checks that the annotated value is notnull.

对应的表字段不允许为null.

@Null

Any type

Checks that the annotated value is null.

没有

@Past

java.util.Date, java.util.Calendar; Additionally supported by HV, if the Joda Time date/time API is on the class path: any implementations of ReadablePartial and ReadableInstant.

检查注解对象中的值表示的日期比当前早.

没有

@Pattern(regex=, flag=)

String

检查该字符串是否能够在match指定的情况下被regex定义的正则表达式匹配.

没有

@Size(min=, max=)

String, Collection, Map and arrays

校验对象的size。本文作者认为前提是该对象有size()方法,String除外。

对应的数据库表字段的长度会被设置成约束中定义的最大值.

@Valid

Any non-primitive type

递归的对关联对象进行校验如果关联对象是个集合或者数组那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.

没有

5.1.2. Hibernate Validator拓展的注解

Annotation

支持的数据类型

作用

Hibernate metadata impact

@CreditCardNumber

String

校验信用卡号码

没有

@Email

String

校验邮件地址

没有

@Length(min=, max=)

String

功能同@Size,但是只支持String类型

对应的数据库表字段的长度会被设置成约束中定义的最大值.

@NotBlank

String

不为null,不为空值,不为全空格。功能强大于@NotEmpty

没有

@NotEmpty

String,Collection,Map and arrays

校验是否为null或者为空值。功能强于@NotNull

没有

@Range(min=, max=)

BigDecimal,BigInteger,String, byte,short, int,long and the respective wrappers of the primitive types

判断数值的范围,不仅支持数值类型,还支持字符串、字节等等类型

没有

@SafeHtml(whitelistType=, additionalTags=)

CharSequence

无使用价值

没有

@ScriptAssert(lang=, script=, alias=)

Any type

无使用价值

没有

@URL(protocol=, host=, port=, regexp=, flags=)

String

Checks if the annotated string is a valid URL according to RFC2396. If any of the optional parameters protocol, host or port are specified, the corresponding URL fragments must match the specified values. The optional parametersregexp and flags allow to specify an additional regular expression (including regular expression flags) which the URL must match.

没有

5.1.3. Validator框架拓展注解

Annotation

支持的数据类型

作用

@NotEmptyPattern

String

在字符串不为空的情况下,验证是否匹配正则表达式

@ListStringPattern

List<String>

验证集合中的字符串是否满足正则表达式

@DateValidator

String

验证日期格式是否满足正则表达式,LocalENGLISH

@DateFormatCheckPattern

String

验证日期格式是否满足正则表达式,Local为自己手动指定

5.2. 对象图级联校验

Validator不仅能够校验单个实例对象,还可以校验完整的对象图。对于实例中的对象成员属性,注解上@Valid,就可以被关联校验。

public class Order {

@NotEmpty

private String orderName;

@NotNull

@Valid

private OrderItem orderItem;

}

public class OrderItem {

@NotEmpty

private String itemName;

@NotEmpty

@Pattern(regexp="\\d+")

private String itemCode;

@NotEmpty

@Email

private String email;

}

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:applicationContext-validator.xml" })

public class CaseCadeTest {

@Autowired

    private Validator validator;

@Test

public void test(){

Order order = new Order();

OrderItem item = new OrderItem();

order.setOrderName("chuanhongliu");

item.setEmail("12345");

item.setItemCode("123456");

item.setItemName("love");

order.setOrderItem(item);

try {

validator.validate(order);

catch (ValidException e) {

System.out.println(e.getAllMessage());

}

}

}

5.3. 校验组分组校验

校验组能够在验证的时候选择应用哪些约束条件。校验组是否通过可变参数传递给validate()validateProperty()validateValue()方法的,校验的过程中,只有被指定的校验组起作用。

设置校验组共分为三个步骤:

1、创建校验组接口:

public interface AvailableFlightGroup {

}

public interface DestinationFlightGroup {

}

2、指定校验组:

public class SegmentVo {

@NotNull

@NotEmpty(groups={AvailableFlightGroup.class})

private String deptCity;

@Pattern(regexp="[A-Z]{3}", groups={DestinationFlightGroup.class})

@NotEmpty(groups={DestinationFlightGroup.class})

private String arrCity;

@DateValidator(regexp="yyyyMMdd", message="日期格式不正确,正确的格式类似于19980413")

@NotEmpty

private String deptDate;

@NotEmpty

private String arrDate;

@NotEmpty

@Email

private String email;

}

3、使用校验组:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:applicationContext-validator.xml" })

public class GroupTest {

    @Autowired

    private Validator validator;

    

    @Test

    public void test(){

     SegmentVo vo = new SegmentVo();

     vo.setDeptCity("PEK");

     vo.setArrCity("SH");

     vo.setDeptDate("20141026");

     vo.setArrDate("");

     try {

validator.validate(vo,DestinationFlightGroup.class);

validator.validate(vo,AvailableFlightGroup.class);

catch (ValidException e) {

System.out.println(e.getMessage());

System.out.println(e.getAllMessage());

}

    }

    

    @Test

    public void test1(){

     SegmentVo vo = new SegmentVo();

     vo.setDeptCity("PEK");

     vo.setArrCity("SH");

     vo.setDeptDate("20141026");

     vo.setArrDate("");

     try {

     validator.validate(vo, DestinationFlightGroup.class, AvailableFlightGroup.class);

catch (ValidException e) {

System.out.println(e.getMessage());

System.out.println(e.getAllMessage());

}

    }

}

注意:如果指定了校验组,则该属性将不再属于默认的校验组Default.class,则在省略校验组参数的情况下,将不会校验自定义校验组的属性。推荐大家重新自定义校验组。可以参考自定义默认校验组的功能。

再注意:其实校验组的接口可以不用专门定义,针对特定业务接口的校验分组,可以直接指定特定的业务接口即可,这样校验分组就同业务接口做到了完整的统一。

5.4. 校验组序列

可以按照指定的顺序来逐个校验各个校验组。如果这个校验组中有一个约束条件没有通过的话,那么此约束条件后面的都不会再继续被校验。

1、定义校验组序列

@GroupSequence({Default.class, AvailableFlightGroup.class, DestinationFlightGroup.class})

public interface OrderChecks {

}

2、使用校验组序列

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:applicationContext-validator.xml" })

public class OrderCheckTest {

@Autowired

    private Validator validator;

@Test

public void test(){

Flight flight = new Flight();

flight.setDeptCity("PE");

flight.setArrCity("");

try {

validator.validate(flight, OrderChecks.class);

catch (ValidException e) {

System.out.println(e.getMessage());

}

}

}

5.5. 自定义默认校验组功能

由于一个对象的属性指定了一个校验组后,将不再属于默认校验组。如此一来,如果想要校验全部的属性值,那么将要注入默认校验组和所有的自定义校验组,使用起来非常的不方便。所以这里提供了自定义默认校验组的功能。

注意:自定义默认校验组的时候,需要将类加入到@GroupSequence注解中。见红色标注

@GroupSequence({DefaultGroup.class,AvailableFlightGroup.class, DestinationFlightGroup.class})

public class DefaultGroup {

@NotEmpty(groups={DestinationFlightGroup.class})

private String name;

@Email(groups={AvailableFlightGroup.class})

private String email;

@AssertTrue

private boolean man;

}

同校验组序列相比,仅仅是将@GroupSequence注解直接打在了类上面。

注意:因为不能在校验组和校验序列中有循环依赖的关系,所以,如果你想重定义一个类的默认组,并且还想把Default.class组加入到这个重定义的序列当中的话,则不能简单的加入Default.class,而是需要把被重定义的类加入到其中

5.6. 自定义智能默认校验组功能

Hibernate Validator提供了非标准的@GroupSequenceProvider注解。本功能提供根据当前对象实例的状态,来决定加载那些校验组进入默认校验组。

1.定义GroupSequenceProvider

public class BMWGroupSequenceProvider implements DefaultGroupSequenceProvider<BMW> {

    @Override

    public List<Class<?>> getValidationGroups(BMW car) {

        List<Class<?>> defaultGroupSequence = new ArrayList<Class<?>>();

        defaultGroupSequence.add(BMW.class);

//        defaultGroupSequence.add(Group2.class);

        if (car != null) {

            defaultGroupSequence.add(Group2.class);

        }

        return defaultGroupSequence;

    }

}

2.注解自定义的GroupSequenceProvider

@GroupSequenceProvider(BMWGroupSequenceProvider.class)

public class BMW extends Car{

    @NotNull

    @Valid

    private Driver driver;

    @Min(0)

    private int passager;

    @AssertFalse(groups = BMW.class)

    private boolean flag;

}

其中必须实现DefaultGroupSequenceProvider接口,同时可以根据被注入的对象的状态或者当前属性值来决定加载哪些校验组。

5.7. 自定义校验注解

先学习定义一个简单的注解,而后定义一个支持多个属性值和校验组功能的注解。

5.7.1. 定义一个简单的注解

开发人员可以自定义校验注解,一方面可以实现逻辑比较复杂的校验,另一方面也可以整合多个校验注解。下面给出了一个自定义的校验字符串大小写的校验规则,我们命名为CheckCase

1、定义枚举类型

public enum CaseMode {

    UPPER

    LOWER;

}

2、定义一个CheckCase的约束注解

@Target({ METHODFIELDANNOTATION_TYPE })

@Retention(RUNTIME)

@Constraint(validatedBy = CheckCaseValidator.class)

@Documented

public @interface CheckCase {

    String message() default "自定义标注校验失败";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    CaseMode value();

}

3、定义一个CheckCase的约束的验证器

public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> {

    private CaseMode caseMode;

    public void initialize(CheckCase constraintAnnotation) {

        this.caseMode = constraintAnnotation.value();

    }

    public boolean isValid(String object, ConstraintValidatorContext constraintContext) {

     boolean isUpper = false;

        if (object == null)

            return true;

        

        boolean isValid;

        if (caseMode == CaseMode.UPPER) {

            isValid = object.equals(object.toUpperCase());

            isUpper = true;

        }

        else {

            isValid = object.equals(object.toLowerCase());

        }

        

        if(!isValid) {

            constraintContext.disableDefaultConstraintViolation();

            if (isUpper){

             constraintContext.buildConstraintViolationWithTemplate("字符串必须为全大写").addConstraintViolation();

            }else{

             constraintContext.buildConstraintViolationWithTemplate("字符串必须为全小写").addConstraintViolation();

            }

        }

        return isValid;

    }

}

4、使用自定义的CheckCase注解

public class ConstraintbyselfModel {

@CheckCase(value=CaseMode.UPPER)

private String name;

/**

 * @return the name

 */

public String getName() {

return name;

}

/**

 * @param name the name to set

 */

public void setName(String name) {

this.name = name;

}

}

自定义Check Constraint的实质就是获取注解的对象, 并对对象做一些逻辑上的解析,判断是否符合校验逻辑,并返回自定义的校验信息。

5.7.2. 定义一个高级的注解

上面定义的CheckCase的标签是一个比较简单的标签,下面定义一个可以设置多个属性,并且支持分组功能的标签。定义一个检测List<String>中各个String是否满足指定正则表达式的标签ListStringPattern

1、定义一个约束注解ListStringPattern

@Target({ METHODFIELDANNOTATION_TYPE })

@Retention(RUNTIME)

@Constraint(validatedBy = ListStringPatternValidator.class)

@Documented

public @interface ListStringPattern {

    String message() default "List<String>中的String不符合指定的正则表达式";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String regexp();

    /**

     * Defines several {@link ListStringPattern} annotations on the same element.

     * 

     * @see ListStringPattern

     */

    @Target({ METHODFIELDANNOTATION_TYPECONSTRUCTORPARAMETER })

    @Retention(RUNTIME)

    @Documented

    @interface List {

        ListStringPattern[] value();

    }

}

其中里面所定义的属性值,如groupsregex等等,都是可以在标签中直接指定的,而@interface List内置标签的作用是可以通知支持多个Annotation修饰同一个字段,例如:

@ListStringPattern.List({@ListStringPattern(regexp="^liu"),@ListStringPattern(regexp="hong$")})

2、定义约束ListStringPattern的约束校验器

public class ListStringPatternValidator implements ConstraintValidator<ListStringPattern, List<String>> {

    private String pattern;

    public void initialize(ListStringPattern constraintAnnotation) {

        this.pattern = constraintAnnotation.regexp();

    }

    public boolean isValid(List<String> list, ConstraintValidatorContext constraintContext) {

        if (list == null) {

            return true;

        }

        String errorString = null;

        boolean isValid = true;

        if (pattern == null || "".equals(pattern.trim())) {

            isValid = false;

            if (!isValid) {

                constraintContext.disableDefaultConstraintViolation();

                constraintContext.buildConstraintViolationWithTemplate("指定的正则表达式为空").addConstraintViolation();

            }

            return isValid;

        } else {

            Iterator<String> iter = list.iterator();

            while(iter.hasNext()){

                String string = iter.next();

                if(!string.matches(pattern)){

                    isValid = false;

                    errorString = string;

                    break;

                }

            }

        }

        if (!isValid) {

            constraintContext.disableDefaultConstraintViolation();

            constraintContext.buildConstraintViolationWithTemplate("List<String>为空,或者其中的"+errorString+"不符合正则表达式:"+pattern).addConstraintViolation();

        }

        return isValid;

    }

}

3、ListStringPattern约束的使用方法

@ListStringPattern(regex="[a-zA-Z]{1}")

private List<String> list;

5.8. 类校验——类属性的关联校验

类级别的约束,本质上就是自定义校验的约束注解。当一个约束被注解在类上的时候,这个类的实例对象被传递给ConstraintValidator。当需要同时校验多个属性或者一个属性的校验依赖于其他属性虚信息的时候,类级别的校验十分有用。下面提供一个校验乘客数不能大约座位数的校验用例,方法和过程同自定义约束注解。

1、定义一个检验旅客数目合法性的注解

@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Constraint(validatedBy={ValidPersonNumberValidator.class})

@Documented

public @interface ValidPersonNumber {

String message()default "Person中的人数不合法!";

Class<?>[] groups()default{};

Class<? extends Payload>[] payload()default{};

}

2、定义一个验证器

public class ValidPersonNumberValidator implements ConstraintValidator<ValidPersonNumber, Person>{

@Override

public void initialize(ValidPersonNumber constraintAnnotation) {

}

@Override

public boolean isValid(Person value, ConstraintValidatorContext context) {

if(null == value){

return true;

}

boolean isValid = value.getNumber()<=100;

if(!isValid){

context.disableDefaultConstraintViolation();

context.buildConstraintViolationWithTemplate("Person类的总人不不能大于100").addConstraintViolation();

}

return isValid;

}

}

3、使用方法

@ValidPersonNumber

public class Person {

private int number;

/**

 * @return the number

 */

public int getNumber() {

return number;

}

/**

 * @param number the number to set

 */

public void setNumber(int number) {

this.number = number;

}

}

4、测试类

@ValidPersonNumber

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:applicationContext-validator.xml" })

public class PersonTest {

@Autowired

    private Validator validator;

@Test

public void test(){

Person person = new Person();

person.setNumber(110);

try {

validator.validate(person);

catch (ValidException e) {

System.out.println(e.getMessage());

}

}

}

5.9. 约束条件组合校验

在某些复杂的场景中可能还会有更多的约束条件被定义到同一个元素上面这可能会让代码看起来有些复杂另外如果在另外的类里面还有一个相同的属性我们可能还要把这些约束条件再拷贝到这个属性上但是这样做又违反了 DRY 原则.这个问题可以通过使用组合约束条件来解决.

1、定义一个约束条件组合的注解

@NotNull

@NotBlank

@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })

@Retention(RetentionPolicy.RUNTIME)

@Constraint(validatedBy = {})

@Documented

public @interface NotNullAndValidCheck {

String message() default "必须不为null且属性格式符合要求";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

2、约束条件组合注解的使用

public class Order1 {

@NotEmpty

private String orderName;

@NotNullAndValidCheck

private OrderItem orderItem;

3、测试类

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = { "classpath:applicationContext-validator.xml" })

public class NotNullAndValidCheckTest {

@Autowired

    private Validator validator;

@Test

public void test(){

Order1 order = new Order1();

order.setOrderName("chuanhongliu");

try {

validator.validate(order);

catch (ValidException e) {

System.out.println(e.getMessage());

}

}

}

6. 各个功能的使用场景

本章主要供大家认识各个校验功能的适用场景,大家根据这些适用场景并结合自己的具体需求,来整合多种校验功能,确定自己的开发策略。

6.1. 内置注解校验

本框架主要是通过打注解(注解)的方式去校验Bean中的属性,现成可用的注解有Bean Validator内置的注解和Hibernate Validator拓展的注解以及Validator自带的注解三种,可以直接使用。父类的校验配置会自动被子类继承。

适用场景:简单的单属性校验。

6.2. 对象图级联校验

对于一个对象中的成员对象属性,打上@Valid注解后,会自动实现对成员对象的级联校验。

本功能适用于复杂的对象,其成员属性为一个对象。

6.3. 校验组分组校验

可以对不同的属性进行分组,以便在特定场景下,仅仅校验一个或几个校验组。一个属性可以归属为多个校验组。

适用场景:将需要校验的属性分类,并单独按组校验。

6.4. 校验组序列

对于已经分成多个校验组的对象,可以配置校验组序列,让各个校验组按照一定的顺序来进行校验。

适用场景:校验组的顺序校验。

6.5. 自定义默认校验组

一个对象会有一个默认的校验组,包含了所有的未分组的校验项。校验默认组的时候不需要在校验方法中指明校验组。如果想让默认校验组包含所有的分组的校验项,可以使用自定义的默认校验组。这样如果想校验整个的对象,就不需要再方法中指定校验组了。大大提高了使用的便利性。推荐所有划分校验组的对象都重新自定义默认校验组。

适用场景:有校验组的情况下,重新定义默认校验组,以包含所有的校验项。

6.6. 自定义智能默认校验组

对于自定义的默认校验组,会有很多的校验组组成。如果想根据当前对象的不同状态来确定默认校验组的组成,决定到底去校验哪些校验组,可以自定义智能默认校验组。

适用场景:根据对象的不同状态,来决定校验哪些校验组。

6.7. 自定义校验注解

对于某一个属性有多重校验约束,或者一些逻辑上的校验约束,可以自定义校验注解,以便整合多重校验约束,或者提供复杂逻辑的校验约束。

适用场景:针对某一个属性值的复杂的校验逻辑,需要自定义。

6.8. 类校验-类属性关联校验

对类校验,注解打在类名上。并可以判断对象中多个属性值之间是否满足某种业务逻辑,来判断是否通过校验。

适用场景:对象多个属性值的关联校验。

7. 附件

7.1. 依赖的pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.travelsky.common</groupId>

  <artifactId>validate</artifactId>

  <version>2.0.0</version>

  <packaging>jar</packaging>

  <name>validate</name>

  <url>http://maven.apache.org</url>

  <properties>

    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <spring-version>3.2.5.RELEASE</spring-version>

    <junit.version>4.10</junit.version>

  </properties>

  <dependencies>

   <dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-test</artifactId>

<version>${spring-version}</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-beans</artifactId>

<version>${spring-version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-core</artifactId>

<version>${spring-version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${spring-version}</version>

</dependency>

     <dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>${junit.version}</version>

<scope>test</scope>

</dependency>

<dependency>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

<version>1.1.1</version>

</dependency>

<dependency>

<groupId>org.apache.commons</groupId>

<artifactId>commons-lang3</artifactId>

<version>3.1</version>

</dependency>

<dependency>

      <groupId>org.hibernate</groupId>

      <artifactId>hibernate-validator</artifactId>

      <version>5.1.0.Final</version>

    </dependency>

    <dependency>

      <groupId>javax.el</groupId>

      <artifactId>el-api</artifactId>

      <version>2.2.1-b04</version>

    </dependency>

    <dependency>

      <groupId>com.sun.el</groupId>

      <artifactId>el-ri</artifactId>

      <version>1.0</version>

    </dependency>

    <dependency>

      <groupId>javax.validation</groupId>

      <artifactId>validation-api</artifactId>

      <version>1.1.0.Final</version>

    </dependency>

    <dependency>

<groupId>com.fasterxml</groupId>

<artifactId>classmate</artifactId>

<version>0.5.4</version>

</dependency>

  </dependencies>

</project>

注意:具体的jar包视工程类型而定,例如,如果你只是一个普通的java项目,则需要加入el包,如果是在容器中运行的项目,例如JBOSS AS,则不需要引入此包,因为该容器已经提供了这个jar

7.2. Validator校验错误码

错误码

错误信息

20141031

validate功能校验对象不可为空!

20141032

校验的对象没有该属性

20141033

校验失败!

20141034

校验的对象不合法!

20141035

校验的属性值不合法!

20141036

校验的输入值不合法!

说明:开发人员可以根据返回的错误码,进行进一步的处理。

猜你喜欢

转载自blog.csdn.net/xp_lx1/article/details/80056138