Java EE6核心特征:Bean Validation

Bean Validation是JavaEE6数据验证新框架,ValidationAPI并不依赖特定的应用层或是编程模型,这样同一套验证可由应用的所有层共享.它还提供了通过扩展ValidationAPI来增加客户化验证约束的机制以及查询约束元数据仓库的手段. 

  在Java EE6的BeanValidation出现之前,开发者不得不在表示层框架、业务层以及持久层中编写验证规则以保证这些规则的同步性,但这么做非常浪费时间而且极易出错.BeanValidation是通过约束实现的,这些约束以注解的形式出现,注解可以放在JavaBean(如backingbean)的属性、方法或是类上面.约束既可以是内建的注解(位于javax.validation.constraints包下面),也可以由用户定义。一些常用的内建注解列举如下: 

   ◆Min:被@Min所注解的元素必须是个数字,其值要大于或等于给定的最小值。
  ◆Max:被@Max所注解的元素必须是个数字,其值要小于或等于给定的最大值。 
  ◆Size:@Size表示被注解的元素必须位于给定的最小值和最大值之间。支持Size验证的数据类型有String、Collection(计算集合的大小)、Map以及数组。 
  ◆NotNull:@NotNull确保被注解的元素不能为null。 
  ◆Null:@Null确保被注解的元素一定为null。 
  ◆Pattern:@Pattern确保被注解的元素(String)一定会匹配给定的Java正则表达式。  

  代码中通过BeanValidation注解声明了一些约束: 
        
package org.jboss.as.quickstarts.bean_validation.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Digits;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import javax.persistence.UniqueConstraint;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;

@Entity
@Table(name="MEMBER_BEAN_VALIDATION", uniqueConstraints = @UniqueConstraint(columnNames = "email"))
public class Member implements Serializable {
    /** Default value included to remove warning. Remove or modify at will. **/
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue
    private Long id;

    @NotNull
    @Size(min = 1, max = 25)
    @Pattern(regexp = "[A-Za-z ]*", message = "must contain only letters and spaces")
    private String name;

    @NotNull
    @NotEmpty
    @Email
    private String email;

    @NotNull
    @Size(min = 10, max = 12)
    @Digits(fraction = 0, integer = 12) //限制12位int数字,小数部分为0位.
    @Column(name = "phone_number")
    private String phoneNumber;

    public Long getId() {
        return id;
    }

    public void setId(Long 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 getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

如下代码自定义了一个名为email的约束(官方源码): 


package org.hibernate.validator.constraints;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

import org.hibernate.validator.constraints.impl.EmailValidator;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * The string has to be a well-formed email address.
 *
 * @author Emmanuel Bernard
 * @author Hardy Ferentschik
 */
@Documented
@Constraint(validatedBy = EmailValidator.class)
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RUNTIME)
public @interface Email {
	String message() default "{org.hibernate.validator.constraints.Email.message}";

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

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

	/**
	 * Defines several {@code @Email} annotations on the same element.
	 */
	@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
	@Retention(RUNTIME)
	@Documented
	public @interface List {
		Email[] value();
	}
}
@Constraint(validatedBy = EmailValidator.class)的代码如下:
package org.hibernate.validator.constraints.impl;

import java.util.regex.Matcher;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.hibernate.validator.constraints.Email;

/**
 * Checks that a given string is a well-formed email address.
 * <p>
 * The specification of a valid email can be found in
 * <a href="http://www.faqs.org/rfcs/rfc2822.html">RFC 2822</a>
 * and one can come up with a regular expression matching <a href="http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html">
 * all valid email addresses</a> as per specification. However, as this
 * <a href="http://www.regular-expressions.info/email.html">article</a> discusses it is not necessarily practical to
 * implement a 100% compliant email validator. This implementation is a trade-off trying to match most email while ignoring
 * for example emails with double quotes or comments.
 * </p>
 *
 * @author Emmanuel Bernard
 * @author Hardy Ferentschik
 */
public class EmailValidator implements ConstraintValidator<Email, String> {
	private static String ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~-]";
	private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*";
	private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";

	private java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(
			"^" + ATOM + "+(\\." + ATOM + "+)*@"
					+ DOMAIN
					+ "|"
					+ IP_DOMAIN
					+ ")$",
			java.util.regex.Pattern.CASE_INSENSITIVE
	);

	public void initialize(Email annotation) {
	}

	public boolean isValid(String value, ConstraintValidatorContext context) {
		if ( value == null || value.length() == 0 ) {
			return true;
		}
		Matcher m = pattern.matcher( value );
		return m.matches();
	}
}


Validation API 

  1.   开发者可以借助于ValidationAPI以编程的方式验证JavaBean。BeanValidationAPI的默认包是javax.validation。下面对该包中的一些类进行说明: 
  2.   ConstraintValidator:这是一个接口,具体的约束验证类需要实现该接口。该接口定义了相关的逻辑以验证给定对象类型中的约束。 
  3.   Validator:Validahttp://java.sun.com/javaee/6/docs/api/index.html?javax/validation/Validator.htmltor接口持有对象验证图的契约。该接口的实现必须是线程安全的。 
  4.   ConstraintViolation:ConstraintViolation接口表示给定bean上的约束验证失败,它公开了约束违背上下文以及描述该违背情况的信息。 
  5.   ValidationException:如果在验证过程中出现了某些不可恢复的错误就会抛出ValidationException异常。某些情况下可以指定该异常,如不合法的分组(group)定义、不合法的约束定义以及不合法的约束声明等等。 
  约束元数据请求API 
  BeanValidation规范提供了查询约束仓库的手段。该API主要用于工具支持和与其他框架、库以及JSR的集成。BeanValidation规范旨在为对象约束提供一个验证引擎和元数据仓库。需要进行约束定义、验证和元数据的框架(JavaEE或JavaSE)可以利用BeanValidation规范完成这些功能,从应用或是基础设施的角度来看,这么做可以避免不必要的重复工作。 

  BeanValidation已经集成到了JSF2.0和JPA2.0中。在JSF中可以将表单输入域与域对象的属性绑定起来。JSF2和BeanValidation可以判断出绑定的是哪个属性并执行与之相关的验证,还会将约束违背的信息显示给用户。HibernateValidator4是BeanValidation规范的参考实现框架,其最新版增加了不少新特性,如分组验证、与JPA2和JSF2的自然集成以及扩展的注解集等等。

但是,所有的输入信息源头基本是用户,所以前台的验证才是最为关键的.

你可能感兴趣的:(Java EE6核心特征:Bean Validation)