public interface CheckRule {
/**
* 是否校验通过
* @param r
* @param dataClump
* @return
*/
boolean isValid(User r, DataClump dataClump);
/**
* 当此条校验不通过的时候,对应的错误码是什么.
*
* @return
*/
FailReasonEnum errorCode();
/**
* 失败时是否继续其它校验
* @return
*/
boolean isContinueWhenFail();
}
public enum FailReasonEnum {
USER_NOT_EXIST("USER_NOT_EXIST", "用户不存在",1L<<1),
ITEM_NOT_EXIST("ITEM_NOT_EXIST", "商品不存在",1L<<2),
;
/** 业务类型代码 */
private String code;
/** 描述 */
private String desc;
/** 唯一标识.唯一标识必须是2的N次方.是用于在批量处理过程中一个批量开通会有多个错误的场景 **/
private long id;
/**
* 枚举类型
*
* @param code
* @param desc
*/
private FailReasonEnum(String code, String desc, long id) {
this.code = code;
this.desc = desc;
this.id = id;
}
/**
* Getter method for property <tt>code</tt>.
*
* @return property value of code
*/
public String getCode() {
return code;
}
/**
* Getter method for property <tt>desc</tt>.
*
* @return property value of desc
*/
public String getDesc() {
return desc;
}
/**
* 获取唯一标识
* @return
*/
public long getId() {
return id;
}
/**
* 获取枚举静态方法
*
* @param code
* @return
*/
public static FailReasonEnum getByCode(String code) {
for (FailReasonEnum type : values()) {
if (StringUtil.equalsIgnoreCase(code, type.getCode())) {
return type;
}
}
return null;
}
/**
* 获取枚举静态方法
*
* @param id
* @return
*/
public static FailReasonEnum getById(long id) {
for (FailReasonEnum type : values()) {
if (id == type.getId()) {
return type;
}
}
return null;
}
}
public enum UserRule implements CheckRule {
/**
* 用户是否存在
*/
USER_EXIST((r, d) -> d.getUserId().containsKey(r.getUserId()), USER_NOT_EXIST,false),
/**
* 业务规则
*/
private final BiPredicate<User, DataClump> predicate;
/**
* 校验失败时对应的错误码.
*/
private final FailReasonEnum errorCode;
/**
* 当校验失败时是否继续
*/
private boolean continueWhenFail;
SourceShopRule(BiPredicate<User, DataClump> predicate, FailReasonEnum errorCode,boolean continueWhenFail) {
this.predicate = predicate;
this.errorCode = errorCode;
this.continueWhenFail = continueWhenFail;
}
@Override
public boolean isValid(User r, DataClump dataClump) {
return predicate.test(r, dataClump);
}
@Override
public FailReasonEnum errorCode() {
return errorCode;
}
public boolean isContinueWhenFail() {
return continueWhenFail;
}
/**
* 错误的上下文信息
*/
public class ErrorContext extends ToString {
/**
* 错误码的唯一标识. FailReasonEnum getId
*/
private long errorId;
public ErrorContext(long errorId) {
this.errorId = errorId;
}
public ErrorContext() {
}
public long getErrorId() {
return errorId;
}
public void setErrorId(long errorId) {
this.errorId = errorId;
}
@Override
public String toString() {
FailReasonEnum failReasonEnum = FailReasonEnum.getById(errorId);
if (failReasonEnum != null){
return "failReasonCode:" + failReasonEnum.getCode()+",desc:"+failReasonEnum.getDesc()+",id:"+failReasonEnum.getId();
} else {
return "null";
}
}
}
//规则引擎,循环遍历所有的枚举,实现所有的规则,把所有的错误信息统一放到上下文中
public List<ErrorContext> applyUserRule(User c, DataClump d) {
List<ErrorContext> errors = Lists.newArrayList();
for (UserRule rule : UserRule.values()) {
if (-1 == 开关推送规则.indexOf(rule.name())) {
LoggerUtil.info(LOGGER,"规则:{0}配置为不执行,跳过",rule.name());
continue;
}
if (!rule.isValid(c, d)) {
errors.add(new CopyErrorContext(rule.errorCode().getId()));
if (!rule.isContinueWhenFail()){
break;
}
}
}
return errors;
}
本文使用的是枚举的方式以及巧妙的是BiPredict方式进行
//判断是否满足条件
boolean test(T t, U u)