参数验证:http://dubbo.apache.org/en-us/docs/user/demos/parameter-validation.html
Dubbo中的参数验证基于JSR-303,它是JAVA EE 6中的一项子规范,通过注解的方式用来对 Java Bean中字段的值进行简单验证。Consumer端要调用Provider端的接口,调用接口的话就会有参数用于传递数据,这里的验证指的就是对这个参数进行验证。
javax.validation
validation-api
1.0.0.GA
org.hibernate
hibernate-validator
4.2.0.Final
如果使用的jdk比较新的话,需要另外添加如下几个依赖:
javax.xml.bind
jaxb-api
2.2.11
com.sun.xml.bind
jaxb-core
2.2.11
com.sun.xml.bind
jaxb-impl
2.2.11
javax.activation
activation
1.1.1
这几个hibernate所依赖的包原来包含在旧版本的jdk中,在新版本中被移除了,好像是从jkd 9开始的,因此需要手动添加。
创建一个用来传递数据的Bean,在成员之前添加用于验证参数的注解:
import java.io.Serializable;
import java.util.Date;
import javax.validation.constraints.Future;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
public class ValidationParameter implements Serializable {
private static final long serialVersionUID = 7158911668568000392L;
@NotNull // Required
@Size(min = 1, max = 20) // range
private String name;
@NotNull(groups = ValidationService.Save.class) // It is not allowed to be blank when saving. When it is updated, it is allowed to be blank, indicating that the field is not updated
@Pattern(regexp = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")
private String email;
@Min(18) // min value
@Max(100) // max value
private int age;
@Past // Must be a past time
private Date loginDate;
@Future // Must be a future time
private Date expiryDate;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getLoginDate() {
return loginDate;
}
public void setLoginDate(Date loginDate) {
this.loginDate = loginDate;
}
public Date getExpiryDate() {
return expiryDate;
}
public void setExpiryDate(Date expiryDate) {
this.expiryDate = expiryDate;
}
}
看一下private String email这个成员:
@NotNull(groups = ValidationService.Save.class) // It is not allowed to be blank when saving. When it is updated, it is allowed to be blank, indicating that the field is not updated
@Pattern(regexp = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")
private String email;
有两条参数验证的注解,第一条是非NULL,后边的注释写black应该是错误的。后边的groups用于区分场景,表示只有调用ValidationService.Save这个方法时才不允许为空,其它场景下允许。
第二条对成员的值进行正则匹配,当然如果email的值是NULL,则不进行匹配,这种情况是通过验证。
服务接口:
public interface ValidationService { // By default, service interfaces are used to differentiate authentication scenarios. For example:@NotNull(groups = ValidationService.class)
@interface Save{} // The same name as the method interface, the first letter capitalized, used to distinguish between authentication scene. For example:@NotNull(groups = ValidationService.Save.class),option
void save(ValidationParameter parameter);
void update(ValidationParameter parameter);
}
接下来在Provider端正常实现上边的接口,Consumer端调用save或者update方法时,会触发参数验证。
关联验证示例:
import javax.validation.GroupSequence;
public interface ValidationService {
@GroupSequence(Update.class) // 同时验证Update组规则
@interface Save{}
void save(ValidationParameter parameter);
@interface Update{}
void update(ValidationParameter parameter);
}
没明白什么是关联验证。
参数验证示例:
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public interface ValidationService {
void save(@NotNull ValidationParameter parameter); // 验证参数不为空
void delete(@Min(1) int id); // 直接对基本类型参数验证
}
验证可发生在Consumer端或者Provider端。
Consumer端:
Provider端:
捕获异常:
try {
parameter = new ValidationParameter();
validationService.save(parameter);
System.out.println("Validation ERROR");
} catch (RpcException e) { // 抛出的是RpcException
ConstraintViolationException ve = (ConstraintViolationException) e.getCause(); // 里面嵌了一个ConstraintViolationException
Set> violations = ve.getConstraintViolations(); // 可以拿到一个验证错误详细信息的集合
System.out.println(violations);
}
参考:http://dubbo.apache.org/en-us/docs/dev/impls/validation.html