1. 责任链- 使用校验的责任链 完成校验逻辑
责任链模式 其核心在将逻辑抽象成一条链条 (可维护的)核心思想是 每个节点都能干预主流程的执行 建立统一的上下文管理不同字段的校验链 主流程能汇聚每个节点的结果。
1.1 首先定义好注解,并在实体类中添加注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Length {
int value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Max {
int value();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Min {
int value();
}
public class User {
public String getName() {
return name;
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Length(5)
private String name;
@Max(15)
@Min(17)
private Integer age;
}
设计出整个校验链,使用 hanlders 做为校验处理器的List
private final List<ValidatorHandler> handlers = new ArrayList<>();
封装出 addHandler的方法 用来向外暴露添加校验处理器,并以顺序作为优先级
public void addLastHandler(ValidatorHandler handler) {
this.handlers.add(handler);
}
1.2 首先抽象出校验的类和方法
在 validate 方法中添加校验的对象,通过反射的方式对字段中需要做的校验抽象出来 ,并构建出校验的链条
public class Validator {
public void validate(Object bean) throws ValidatorException, IllegalAccessException {
// 责任链模式
Class<?> aClass = bean.getClass();
for (Field declaredField : aClass.getDeclaredFields()) {
// 私有属性添加
declaredField.setAccessible(true);
buildValidateChain(declaredField).validate(declaredField.get(bean));
}
}
private ValidatorChain buildValidateChain(Field declaredField) {
ValidatorChain chain = new ValidatorChain();
Max max = declaredField.getAnnotation(Max.class);
if ( max != null) {
chain.addLastHandler(new MaxValidatorHandler(max.value()));
}
Min min = declaredField.getAnnotation(Min.class);
if (min != null) {
chain.addLastHandler( new MinValidatorHandler(min.value()));
}
Length length = declaredField.getAnnotation(Length.class);
if (length != null) {
chain.addLastHandler(new LengthValidatorHandler(length.value()));
}
return chain;
}
}
1.3 ValidatorHandler 作为校验处理器 对各种校验逻辑的封装
public interface ValidatorHandler {
void validate(Object bean,ValidatorContext context) ;
}
// 各种不同的校验器实现
public class MaxValidatorHandler implements ValidatorHandler {
//
private final Integer max;
public MaxValidatorHandler (Integer max ) {
this.max = max;
}
// 校验器的告警机制停止校验 每个校验器都可以通过上下文对流程进行干预
@Override
public void validate(Object bean, ValidatorContext context) {
if(bean instanceof Integer) {
if(max < (Integer) bean) {
context.appendError("Max number is greater than " + max);
}
}
}
// 最小值的校验
public class MinValidatorHandler implements ValidatorHandler {
private final Integer min;
public MinValidatorHandler (Integer min ) {
this.min = min;
}
@Override
public void validate(Object bean, ValidatorContext context) {
if(bean instanceof Integer) {
if(min > (Integer) bean) {
context.appendError("Max number is min than " + min);
}
}
}
}
// 长度的校验
public class LengthValidatorHandler implements ValidatorHandler {
private final Integer length;
public LengthValidatorHandler(Integer length ) {
this.length = length;
}
@Override
public void validate(Object bean,ValidatorContext context) throws ValidatorException {
if(bean instanceof String) {
if(length < ((String) bean).length()) {
context.appendError("Max length is greater than " + length);
}
}
}
}
1.4 在具体的校验方法中的处理
在 validatorContext对象中封装一些公用的方法(如当前校验到的节点的下表,当前错误的信息的List的封装)和当前校验节点的下标。使用 ValidatorHandler的实现各种校验逻辑的封装,进行校验。
// 组装链条
public void validate(Object object) throws ValidatorException {
// for (ValidatorHandler handler : handlers) {
// handler.validate(object,context);
// if(context.shouldStopChain()){
// break;
// }
// }
ValidatorContext context = new ValidatorContext(object);
while(true) {
Integer currentIndex = context.getCurrentIndex();
if(currentIndex == handlers.size() ) {
break;
}
ValidatorHandler validatorHandler = handlers.get(currentIndex);
validatorHandler.validate(context.getValue(),context);
// 没有调用 doNext函数的情况
if(currentIndex.equals(context.getCurrentIndex())){
break;
}
}
context.throwExceptionIfNecessary();
}