当前位置: 首页 > 工具软件 > Struts4RCP > 使用案例 >

RCP数据模型验证框架

姬阳曜
2023-12-01
Struts(for)RCP([url]http://struts4rcp.googlecode.com[/url])发布了0.1版本,但还缺少一个重要元素,那就是数据模型验证框架,MVC框架总是少不了它。
验证框架需要实现哪些功能?
1. 对Action执行过程中的数据进行透明化检验,Action只需声明验证规则,而不参与验证过程。
2. 可以服务器端验证,也以可客户端验证,或者数据模型自验证。
3. 验证规则捆绑方便,可以使用注解,也可以使用XML配置,以及直接编码捆绑。
4. 验证规则可自定义,并且内置规则丰富。
5. 验证出错信息国际化。
现成的验证框架已经不少,像Struts, WebWork, Hibernate, JSF等都提供了验证框架,是否可以重用?
由于B/S开发的盛行,大多数已有验证框架都向B/S结构倾斜,虽然它们也能验证C/S结构应用。
而且验证框架众多,不易选择大众口味,所以还是由框架本身提供,然后适配到其它验证框架。
如果重新定义验证框架,它应该属于哪个包?
它并不是MVC控制器框架必需的,而且它需要在服务器端和客户端同时使用,
甚至给其它第三方包复用,所以,它应该放在util包内,与序列化器相似。
最后决定放在com.googlecode.struts4rcp.util.validator包下。
首先,需要定义验证器接口,它将作为验证框架的中心接口,如:

/**
* 数据验证器
*/
public interface Validator {

/**
* 验证数据
* @param model 数据模型
* @throws ValidationException 数据验证失败时抛出
*/
void validate(Object model) throws ValidationException;

}

基本的验证器实现如:

/**
* 必需验证器
*/
public class RequiredValidator implements Validator {

public void validate(Object model) throws ValidationException {
if (model == null)
throw new ValidationException();
if (model instanceof String && ((String)model).trim().length() == 0)
throw new ValidationException();
if (model instanceof Collection && ((Collection<?>)model).size() == 0)
throw new ValidationException();
if (model instanceof Map && ((Map<?, ?>)model).size() == 0)
throw new ValidationException();
}

}


/**
* 正则表达式验证器
*/
public class PatternValidator implements Validator {

protected final String pattern;

public PatternValidator(String pattern) {
this.pattern = pattern;
}

public void validate(Object model) throws ValidationException {
if (model == null)
return;
if (! (model instanceof String))
return;
String str = (String)model;
str = str.trim();
if (str.trim().length() == 0)
return;
if (! str.matches(pattern))
throw new ValidationException();
}

}

还有Length, Range, Email, URL, Phone, ZipCode, CreditCard, IdentificationCard等等。
以上都是原子级验证器的实现,可通过组合,链,委托等方式,进行更复杂的验证规则处理,如:

/**
* 验证器链
*/
public class ValidatorChain implements Validator {

private Collection<Validator> validators;

public ValidatorChain(Validator... validators) {
this.validators = Arrays.asList(validators);
}

public void validate(Object model) throws ValidationException {
if (validators != null && validators.size() > 0) {
for (Validator validator : validators) {
validator.validate(model);
}
}
}

}


/**
* 字段验证器
*/
public class FieldValidator implements Validator {

protected final String filedName;

protected final Validator validator;

public FieldValidator(String filedName, Validator validator) {
this.filedName = filedName;
this.validator = validator;
}

public void validate(Object model) throws ValidationException {
if (model == null)
validator.validate(null);
else if (model instanceof Map)
validator.validate(((Map)model).get(filedName));
else
validator.validate(BeanUtils.getProperty(model, filedName));
}

}

等等。
不管验证规则多复杂,最终得到的都是一个Validator总接口。
这样,服务器端可通过拦载器,实现验证框架的集成:(此集成拦截器属于server包)

/**
* 验证拦截器
*/
public class ValidationInterceptor implements ActionInterceptor {

public Serializable intercept(Action<Serializable, Serializable> action,
Serializable model) throws Exception {
Action<Serializable, Serializable> srcAction = ActionContext.getContext().getAction();
Validator validator = null;
if (srcAction instanceof ValidationAction) { // Action自声明
ValidationAction<Serializable, Serializable> validationAction = (ValidationAction<Serializable, Serializable>)srcAction;
validator = validationAction.getValidator();
} else {
validator = ValidationManager.getValidator(srcAction); // 从配置读取
}
if (validator != null)
validator.validate(model); // 验证
return action.execute(model);
}

}

然后,就是绑定规则,框架应支持多种绑定方式,以适应不同应用情况:
第一种方式,使用注解:
在Action上声明,表示只对指定Action请求进行验证,如:

public class LoginAction implements Action<Account, User> {

@Required // 不带field属性,表示对整个model进行校验,这里表示传入model不能为null,如果需要对比多个字段时,也可能需要用到
@Required(field="username")
@Length(field="username", min=3, max=20)
@Required(field="password")
@Length(field="password", min=6, max=20)
public User execute(Account account) throws Exception {
// ......
}
}

在数据模型上声明,表示对所有该类型的数据模型进行验证,如:

public class Account {

@Required
@Length(min=3, max=20)
public String getUsername() {
// ......
}

@Required
@Length(min=6, max=20)
public String getPassword() {
// ......
}
}

第二种方式,使用XML配置:

<validation>
<!--定义验证器-->
<validator name="required" class="com.googlecode.struts4rcp.util.validator.RequiredValidator" />
<validator name="length" class="com.googlecode.struts4rcp.util.validator.LengthValidator" />
<!--只对指定Action请求进行验证-->
<action name="loginAction">
<required /> <!--放在field外面,表示对整个model进行校验,这里表示传入model不能为null,如果需要对比多个字段时,也可能需要用到-->
<field name="username">
<required />
<length min="3" max="20" />
</field>
<field name="password">
<required />
<length min="6" max="20" />
</field>
</action>
<!--对所有该类型的数据模型进行验证-->
<model class="com.xxx.demo.domain.Account">
<field name="username">
<required />
<length min="3" max="20" />
</field>
<field name="password">
<required />
<length min="6" max="20" />
</field>
</model>
</validation>

第三种方式,直接编码构建规则:

public class LoginAction implements ValidationAction<Account, User> {

public Validator getValidator() {
return new ValidatorChain(
new RequiredValidator(), // 传入model不能为null
new FieldValidator("username", new ValidatorChain(
new RequiredValidator(), // 用户名不能为空
new LengthValidator(3, 20))), // 用户名长度限制
new FieldValidator("password", new ValidatorChain(
new RequiredValidator(),
new LengthValidator(6, 20))));
}

public User execute(Account account) throws Exception {
// ......
}

}
 类似资料: