Java轻量级数据校验框架实现
方法入口常出现重复的校验逻辑:
result.setSuccess(false);
if (StringUtils.isEmpty(order.getExternalId())) {
result.setError("外部订单号不能为空");
return result;
}
if(order.getExternalId().length() > 100){
result.setError("外部订单号长度需在100以内");
return result;
}
if (StringUtils.isEmpty(order.getProductCode())) {
result.setError("商品编码不能为空");
return result;
}
现有方案如JSR 303或Spring MVC Validator虽成熟但较重。本文实现一个轻量级校验框架,核心设计如下:
设计目标
- 轻量化:无第三方依赖,代码精简
- 链式调用:支持
new Checker().require(name).maxLength(address)语法 - 注解驱动:通过注解声明校验规则
- 可扩展:支持自定义校验器
注解校验模块
定义校验注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Mandatory {
String fieldLabel();
}
实现注解处理器:
public class MandatoryHandler implements AnnotationHandler {
@Override
public CheckResult process(Field field, Object value) {
CheckResult result = new CheckResult();
if(field.isAnnotationPresent(Mandatory.class)){
Mandatory rule = field.getAnnotation(Mandatory.class);
if(value == null || value.toString().isEmpty()){
result.setError(rule.fieldLabel() + "为必填项");
}
}
return result;
}
}
注解校验执行器:
public class AnnotationChecker {
private static final List<AnnotationHandler> handlers = new ArrayList<>();
static {
handlers.add(new MandatoryHandler());
handlers.add(new LengthLimitHandler());
}
public static <T> CheckResult verify(T obj) {
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(obj);
for (AnnotationHandler handler : handlers) {
CheckResult result = handler.process(field, value);
if(!result.valid()) return result;
}
}
return new CheckResult(true);
}
}
使用示例:
class User {
@Mandatory(fieldLabel="用户名")
private String username;
}
public class Demo {
public static void main(String[] args) {
User user = new User();
CheckResult result = AnnotationChecker.verify(user);
if(!result.valid()) {
System.out.println(result.getError());
}
}
}
链式校验模块
校验规则接口:
public interface ValidationRule {
String getError();
boolean isValid();
}
链式校验器:
public class Checker {
private boolean valid = true;
private String error;
public Checker apply(ValidationRule rule) {
if(valid) {
valid = rule.isValid();
error = rule.getError();
}
return this;
}
public Checker require(Object value, String field) {
if(valid && (value == null || value.toString().isEmpty())) {
valid = false;
error = field + "不能为空";
}
return this;
}
}
使用示例:
Checker checker = new Checker()
.require(order.getId(), "订单ID")
.require(order.getAddress(), "收货地址");
if(!checker.isValid()) {
System.out.println(checker.getError());
}
扩展机制
自定义日期校验器:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DatePattern {
String format();
String fieldName();
}
public class DateValidator implements AnnotationHandler {
@Override
public CheckResult process(Field field, Object value) {
if(field.isAnnotationPresent(DatePattern.class)){
DatePattern rule = field.getAnnotation(DatePattern.class);
try {
new SimpleDateFormat(rule.format()).parse(value.toString());
} catch (Exception e) {
return new CheckResult(rule.fieldName() + "格式错误");
}
}
return new CheckResult(true);
}
}
// 注册使用
AnnotationChecker.register(new DateValidator());