近期由于工作的需要,写了一个简易的参数校验框架,虽然市场上有common-validator 和
hibernate-validator两个开源的,但是有些情景
他们是无法满足的,比如参数字段之间的依赖关系,这在项目中是极其常见的。他们仅仅提供了对字段的简单的格式校验。另外这两种校验框架的校验器都是有状态的,这样导致校验的性能不好,对于录入还无所谓,但是批量excel 导入的这种,就非常吃力了。
出于性能和依赖关系校验的需求,改造下工作的校验框架为一个通用的参数校验框架,支持
表达式的格式校验,灵活性极好,代码完全复用,思路明了,适合复杂的参数校验场景,希望各位给予指正其中的不足~
下面我贴出来了我写的框架的代码,但是太麻烦搞格式,我也懒的搞,如果有兴趣,可以下载源码看看~
git地址为:https://github.com/wangxinchun/javaframe-validator
先看下这个框架的用法:
class="java" name="code">
/**
* 验证要求:
* 1、begin 可以为空,end 也可以为空,如果不为空,那么他们必须是yyyy-MM-dd的时间格式
* 2、如果end不为空,那么end的时间必须大于当前时间
* 3、如果begin不为空,并且end不为空,end 必须大于begin的时间
* @author wangxinchun
*
*/
public class DateVO {
@Rules(
conditionList = {
@ConditionRule(id = "A",type = RuleType.empty),
@ConditionRule(id = "B",type = RuleType.not_empty)
},
conclusionList = {
@ConclusionRule(id = "C",type =RuleType.date_format ,value = "yyyy-MM-dd",tip = "格式错误")
},
logicList = {
//如果为空,那么直接success,如果失败继续下一个规则的校验
@LogicRule(conclusion = "A",successNextStep = NextStepType.returnSuccess,failNextStep = NextStepType.goNext),
@LogicRule(condition = "B", conclusion = "C") //此次的B配置可以去掉,因A成功,已经返回,所以B条件肯定成立
},
text = "开始时间")
private Date begin;
@Rules(
conditionList = {
@ConditionRule(id = "A",type = RuleType.empty),
//@ConditionRule(id = "B",type = RuleType.not_empty),
@ConditionRule(id = "C",type = RuleType.not_empty,dependProperty = "begin")
},
conclusionList = {
@ConclusionRule(id = "D",type = RuleType.date_format,value = "yyyy-MM-dd",tip = "格式错误"),
@ConclusionRule(id = "E",type = RuleType.date_compare_now,value = ">=,yyyy-MM-dd",tip = "必须大于当前时间"),
@ConclusionRule(id = "F",type = RuleType.date_compare_refer,value = "begin,>=,yyyy-MM-dd",tip = "结束时间必须大于开始时间")
},
logicList = {
//如果为空,那么直接返回,如果不为空,那么直接进入下一个校验
@LogicRule(conclusion = "A",successNextStep = NextStepType.returnSuccess,failNextStep = NextStepType.goNext),
@LogicRule(conclusion = "D&&E"),// 此次的验证可以分开也可以合并
@LogicRule(condition= "C", conclusion = "F") //依赖验证
},
text = "结束时间")
private Date end;
public Date getBegin() {
return begin;
}
public void setBegin(Date begin) {
this.begin = begin;
}
public Date getEnd() {
return end;
}
public void setEnd(Date end) {
this.end = end;
}
}
测试用例:
@Test
public void testValidateDate() {
CommonValidateService service = new CommonValidateService();
Map<String,String> params = new HashMap<String,String>();
params.put("begin", "2013-12-09");
params.put("end", "2013-12-08");
ValidateResult result = service.validate(params, DateVO.class);
Assert.assertEquals(result.isSuccess(), false);
}
@Test
public void testValidateDate2() {
CommonValidateService service = new CommonValidateService();
Map<String,String> params = new HashMap<String,String>();
params.put("begin", "2013-12-09");
params.put("end", "2013-12-10");
ValidateResult result = service.validate(params, DateVO.class);
Assert.assertEquals(result.isSuccess(), true);
}
引用术语:
一个对象有多个属性
每个属性对应一个校验规则集合
一个校验规则集合对于多个校验规则
每个校验规则有一个或者多个校验条件和结论组成。
基于以上的分析,定义对以上角色的
注解抽象:
/**
* 验证规则集
* @author wangxinchun1988@163.com <br>
* 配置在bean的成员上,代表一组校验规则集
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Rules {
/**
* 结论规则集合 */
ConclusionRule[] conclusionList();
/**
* 条件规则集合 */
ConditionRule[] conditionList() default {};
/**
* 逻辑验证规则集合 */
LogicRule[] logicList() default {};
/** 成员字段名称*/
String text() default "";
/** 校验顺序,默认同一order值,按照在bean中出现的先后顺序校验*/
int order() default Integer.MIN_VALUE;
/** LogicRule的组合模式,默认为AND组合*/
LogicAssembleType assembleType() default LogicAssembleType.AND;
}
/**
* 逻辑项注解
* @author wangxinchun1988@163.com
* @date 2013-12-2下午1:37:47
*/
public @interface LogicRule {
/** 条件:逻辑条件表达式。<BR>
* tips:简单逻辑没有条件的,推导逻辑才有条件*/
public String condition() default "";
/** 结论:要验证的结论表达式 <br>
* eg:(A&&B)||C
* */
public String conclusion();
/** 逻辑验证成功的下一步执行逻辑 <br/>
* 1、NextStepType.goNext 默认进行下一个校验规则的验证。(如果词条为最后一个逻辑项,那么等同于NextStepType.returnSuccess)<br/>
* 2、NextStepType.returnSuccess 表示此验证完成之后,不再进行下一个校验规则的验证 ,直接返回校验成功
* */
public NextStepType successNextStep() default NextStepType.goNext;
/** 逻辑校验失败后下一步执行逻辑
* 1、NextStepType.returnFail 默认校验失败时,直接返回校验失败
* 2、NextStepType.goNext 校验继续下一个词条的校验(如果词条为最后一个逻辑项,那么等同于NextStepType.returnSuccess)
* */
public NextStepType failNextStep() default NextStepType.returnFail;
/** 条件验证失败的下一步返回类型 <br>
* 1、NextStepType.goNext 默认条件校验失败,进入下一个逻辑词条的校验(如果词条为最后一个逻辑项,那么等同于NextStepType.returnSuccess)<br>
* 2、NextStepType.returnFail 不进行下一个词条的校验,直接返回校验失败 <br>
* 3、NextStepType.returnSuccess 不进行下一个词条的校验,直接返回校验成功
* */
public NextStepType conditionFailNextStep() default NextStepType.goNext;
/**
* 验证失败后的提醒信息,此提醒信息优先级最高
*/
public String tip() default "";
/**
* 提醒类型
*/
public TipType tipType() default TipType.combine;
}
/**
* 条件项注解
* @author wangxinchun1988@163.com
* @date 2013-12-2下午9:45:20
*
* tip: 条件项的注解,不需要包括 字段验证的失败信息。
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ConditionRule {
public String id();
/**
* 验证规则名字
*/
public RuleType type() default RuleType.local_type;
/**
* 验证规则值
*/
public String value() default "";
/** 依赖参照熟悉*/
public String dependProperty() default "";
/**
* 扩展本地校验规则
* @return
*/
public String local() default "";
}
/**
* 推导结果项注解
* @author xinchun.wang
*
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ConclusionRule {
/** 规则项的位唯一id属性*/
public String id();
/**
* 验证规则名字
*/
public RuleType type() default RuleType.local_type;
/**
* 验证规则值
*/
public String value() default "";
/**
* 此验证失败后的提醒信息,如果没有配置那么从ConclusionItem 取tip信息
*/
public String tip() default "";
/**
* 提醒类型
* @return
*/
public TipType tipType() default TipType.combine;
/**
* 扩展本地校验规则
* @return
*/
public String local() default "";
}
规则定义完毕,下面就是
解析校验规则了:
/**
* 验证服务接口
* @author xinchun.wang
*
*/
public interface IValidateService {
/**
* 校验params中的参数以及对应的值是否有效
* @param params
* @return
*/
ValidateResult validate(Map<String, String> params,Class<?> cls);
}
/**
* 验证接口的抽象实现
*
* @author xinchun.wang
*
*/
public abstract class AbstractValidateService implements IValidateService {
protected static final Logger logger= LoggerFactory.getLogger(AbstractValidateService.class);
/**持有Rules到其上所有校验器的缓存。结构: Rules ->(id,ValidatorVO)的映射*/
final private static ConcurrentHashMap<Rules,Map<String,RuleVO> > rulesCacheMap = new ConcurrentHashMap<Rules, Map<String,RuleVO>>();
/** 持有Rules上逻辑校验逻辑的缓存。结构:Rules->LogicGroup 的映射*/
final private static ConcurrentHashMap<Rules,LogicGroup > rulesLogicGroupCacheMap = new ConcurrentHashMap<Rules, LogicGroup>();
/**
* 规则处理集合接口
*
* @param rule 规则
* @param value 参数值
* @param params 依赖参考对象
* @return
*/
final protected ValidateResult processRules(Rules rules, String name, Map<String, String> params) {
LogicRule[] logicArr = rules.logicList();
if(logicArr == null || logicArr.length <=0 ){
return ValidateResult.SUCCESS; //如果没有配置验证逻辑项,默认返回success
}
LogicGroup execute = rulesLogicGroupCacheMap.get(rules);
if(execute == null){
for(LogicRule item : logicArr) {
String conclusion = item.conclusion();//逻辑校验规则的结论表达式
String condition = item.condition();
if(condition == null || condition.trim().isEmpty()){ //如果是简单逻辑,只有结论没有条件
if(conclusion == null || conclusion.trim().isEmpty()){
throw new LogicConfigException("没有配置conclusion逻辑" + item);
}
LogicRuleVO logic = initLogicVO(rules,item ,name);
LogicGroup atomicLogicGroup = new AtomicLogicGroup(logic);
if(execute == null){
execute = atomicLogicGroup;
}else {
if(rules.assembleType() == LogicAssembleType.AND){
execute = new AndLogicGroupAdapter(Arrays.asList(execute, atomicLogicGroup));
} else{
execute = new OrLogicGroupAdapter(Arrays.asList(execute, atomicLogicGroup));
}
}
}else {//推导验证逻辑项
if(conclusion != null && !conclusion.trim().isEmpty() && condition != null && !condition.trim().isEmpty()){
/* 没有缓存的逻辑组*/
LogicRuleVO logic = initLogicVO(rules,item,name);
LogicGroup deduceLogic = new DeduceAtomicLogicGroup(logic);
if(execute == null) {
execute = deduceLogic;
}else{
if(rules.assembleType() == LogicAssembleType.AND){
execute = new AndLogicGroupAdapter(Arrays.asList(execute,deduceLogic));
} else{
execute = new OrLogicGroupAdapter(Arrays.asList(execute,deduceLogic));
}
}
} else{
throw new LogicConfigException(item+ " 推导逻辑配置错误 ");
}
}
}
}
LogicValidateResult result = execute.executeLogic(params);
if(result.isSuccess()){
return ValidateResult.SUCCESS;
}else{
return ValidateResult.errorInstance(result.getMessage());
}
}
/**
* 初始化逻辑VO
* @param item
* @param validatorMap
* @return
*/
private LogicRuleVO initLogicVO(Rules rules,LogicRule item,String name) {
LogicRuleVO logic = new LogicRuleVO();
Map<String, RuleVO> validatorMap = rulesCacheMap.get(rules);
if (validatorMap == null) {
validatorMap = resolveValidatorMapByRules(rules, name);
rulesCacheMap.putIfAbsent(rules, validatorMap);
}
String conclusion = item.conclusion();
if(conclusion != null && !conclusion.trim().isEmpty()){
ConditionGroup conclusionGroup = ConditionGroupResolver.resolve(conclusion,validatorMap);
logic.setConclusionGroup(conclusionGroup);
}
String condition = item.condition();
if(condition != null && !condition.trim().isEmpty()){
ConditionGroup conditionGroup = ConditionGroupResolver.resolve(condition,validatorMap);
logic.setConditionGroup(conditionGroup);
}
if(item.tipType() == TipType.just_rule){
logic.setTip(item.tip());
}else{
if(item.tip() != null && !item.tip().isEmpty()){
logic.setTip(rules.text() + item.tip());
}
}
logic.setFailNextStep(item.failNextStep());
logic.setSuccessNextStep(item.successNextStep());
logic.setConditionFailNextStep(item.conditionFailNextStep());
return logic;
}
/**
* 解析rules上所有的校验器
* @param rules
* @param name
* @return
*/
private Map<String,RuleVO> resolveValidatorMapByRules(Rules rules ,String name){
Map<String,RuleVO> ruleMap = new HashMap<String,RuleVO>();
for(ConclusionRule item : rules.conclusionList()){
RuleVO vo = new RuleVO();
IValidator validator = null;
/* 找到验证器*/
if(RuleType.local_type == item.type()){
String localRule = item.local();
validator = ValidatorFactory.getLocalValidator(localRule);
} else {
validator = ValidatorFactory.getCommonValidator(item.type());
}
if(validator == null){
throw new IllegalStateException(item + "没有注册有效的验证器");
}
vo.setProperty(name);
if(item.tipType() == TipType.combine){
vo.setTip(rules.text()+item.tip());
}else{
vo.setTip(item.tip());
}
vo.setRuleType(item.type());
vo.setRule(item.value());
ruleMap.put(item.id(), vo);
}
for(ConditionRule item : rules.conditionList()){
RuleVO vo = new RuleVO();
if(item.dependProperty()== null || item.dependProperty().isEmpty()){
vo.setProperty(name);
}else {
vo.setProperty(item.dependProperty());
}
vo.setRuleType(item.type());
vo.setRule(item.value());
ruleMap.put(item.id(), vo);
}
return ruleMap;
}
}
/**
* 通用规则验证器 <br>
*
* 根据cls 检索其字段上的注解,解析注解,然后校验params的信息。
* @author xinchun.wang
*
*/
public class CommonValidateService extends AbstractValidateService {
final private static ConcurrentHashMap<String, Map<Field, Rules>> cacheMap = new ConcurrentHashMap<String, Map<Field, Rules>>();
/*
* (non-Javadoc)m
*
* @see
* com.qunar.flight.tts.policy.client.validator.impl.AbstractValidateServiceImpl
* #validate(java.util.Map)
*/
@Override
public ValidateResult validate(Map<String, String> params,Class<?> cls) {
Map<Field, Rules> fieldRuleMap = cacheMap.get(cls.getName());
if (fieldRuleMap == null) {
fieldRuleMap = ClassHelper.getFieldsAndRules(cls);
cacheMap.putIfAbsent(cls.getName(), fieldRuleMap);
}
for (Map.Entry<Field, Rules> item : fieldRuleMap.entrySet()) {
Field itemField = item.getKey();
String name = itemField.getName();
Rules rules = item.getValue();
if(rules == null){
continue;
}
ValidateResult result = processRules(rules, name, params);
if(!result.isSuccess()){
return result;
}
}
return new ValidateResult(true,null);
}
}
public class ClassHelper {
/**
* 检索cls类的所有Field字段以及其上的验证信息
*
* @param cls
* @return
*/
@SuppressWarnings("unchecked")
public static Map<Field, Rules> getFieldsAndRules(Class<?> cls) {
if (cls == null) {
return Collections.EMPTY_MAP;
}
final Field[] fields = cls.getDeclaredFields();
if (fields == null) {
return Collections.EMPTY_MAP;
}
Map<Field, Rules> fieldRulesMap = new TreeMap<Field, Rules>(
new Comparator<Field>() {
@Override
public int compare(Field o1, Field o2) {
Rules rules1 = o1.getAnnotation(Rules.class);
Rules rules2 = o2.getAnnotation(Rules.class);
if (rules1.order() != Integer.MIN_VALUE && rules2.order() != Integer.MIN_VALUE) { //如果两个都有配置顺序
if(rules1.order() == rules2.order()) { //都配置,但是配置的order顺序相等
int index1 = ArrayUtils.indexOf(fields,o1);
int index2 = ArrayUtils.indexOf(fields,o2);
return index1 - index2;
}
return rules1.order() - rules2.order(); //都配置,order小的排在前面
} else if (rules1.order() == Integer.MIN_VALUE) { //o1 没有配置,o2配置了
return 1;
} else if (rules2.order() == Integer.MIN_VALUE) { //o1 配置了,o2没有配置了
return -1;
}else {
int index1 = ArrayUtils.indexOf(fields,o1);
int index2 = ArrayUtils.indexOf(fields,o2);
return index1 - index2;
}
}
});
for (Field item : fields) {
Rules rules = item.getAnnotation(Rules.class);
if (rules == null) {
continue;
}
fieldRulesMap.put(item,rules);
}
return fieldRulesMap;
}
}
逻辑条件 和 逻辑结论的解析和组装
/**
* 条件逻辑组校验接口
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:03:53
*/
public interface ConditionGroup {
/**
* 逻辑校验方法
* @param params
* @return
*/
public ValidateResult executeCondition(Map<String, String> params);
}
/**
* 原子校验组
* 一个原子校验组拥有一个校验器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:04:48
*/
public class AtomitConditionGroup implements ConditionGroup {
private RuleVO ruleVo;
public AtomitConditionGroup(final RuleVO ruleVo) {
this.ruleVo = ruleVo;
}
@Override
public ValidateResult executeCondition(Map<String, String> params) {
if(ruleVo == null){
throw new ValidatorConfigException();
}
IValidator validator = null;
/* 找到验证器*/
if(RuleType.local_type == ruleVo.getRuleType()){
String localRule = ruleVo.getLocal();
validator = ValidatorFactory.getLocalValidator(localRule);
} else {
validator = ValidatorFactory.getCommonValidator(ruleVo.getRuleType());
}
if(validator == null){
throw new IllegalStateException(ruleVo + "没有注册有效的验证器");
}
ValidateResult result = validator.validate(ruleVo, params);
return result;
}
}
/**
* 逻辑组校验适配器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:06:08
*/
public abstract class ConditionGroupAdapter implements ConditionGroup {
protected List<ConditionGroup> list;
}
/**
* 逻辑组校验AND类型的集成适配器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:06:55
*/
public class AndConditionGroupAdapter extends ConditionGroupAdapter {
public AndConditionGroupAdapter(List<ConditionGroup> list) {
this.list = list;
}
@Override
public ValidateResult executeCondition(Map<String, String> params) {
if(list == null || list.size() <= 0){
return ValidateResult.SUCCESS;
}else {
for(ConditionGroup item : list){
ValidateResult result = item.executeCondition(params);
if(!result.isSuccess()){
return result;
}
}
return ValidateResult.SUCCESS;
}
}
}
/**
* 逻辑组校验OR类型的集成适配器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:05:36
*/
public class OrConditionGroupAdapter extends ConditionGroupAdapter {
public OrConditionGroupAdapter(List<ConditionGroup> list) {
this.list = list;
}
@Override
public ValidateResult executeCondition(Map<String, String> params) {
if(list == null || list.size() <= 0){
return ValidateResult.SUCCESS;
}else {
StringBuilder failBuilder = new StringBuilder();
for(ConditionGroup item : list){
ValidateResult result = item.executeCondition(params);
if(result.isSuccess()){
return ValidateResult.SUCCESS;
}else {
failBuilder.append(result.getMessage()).append(item.equals(list.get(list.size()-1))? "":",或者");
}
}
return ValidateResult.errorInstance(failBuilder.toString());
}
}
}
/**
* 条件表达式解析器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午12:07:48
*/
public class ConditionGroupResolver {
private static final char AND = '&';
private static final String ANDAND = "&&";
private static final char OR = '|';
private static final String OROR = "||";
private static final char left = '(';
private static final char right = ')';
/**
* 逻辑表达是的解析
*
* @param logic ((A||B)&&(C||D))||(F&&H)
* @param ruleMap 校验器id->ValidatorVO
* @return 返回逻辑表达式对应校验封装实现
*/
public static ConditionGroup resolve(String logic, Map<String, RuleVO> validatorMap) {
logic = trimLogic(logic);
if (logic == null || logic.trim().isEmpty()) {
return null;
}
if (!logic.contains(ANDAND) && !logic.contains(OROR)) {
RuleVO logicVO = validatorMap.get(logic);
if (logicVO == null) {
if(logic.indexOf(""+AND)!=-1 || logic.indexOf(""+OR)!= -1){
throw new LogicConfigException(logic + "配置错误,与和或的逻辑请使用 && || 表达 ");
}
throw new LogicConfigException(logic + "没有对应的Rule");
}
return new AtomitConditionGroup(logicVO);
}
int leftCount = 0;
int rightCount = 0;
boolean andFlag = false;
boolean orFlag = false;
int lastSubIndex = 0;
List<String> subLogicList = new ArrayList<String>();
for (int i = 0; i < logic.length(); i++) {
char tempChar = logic.charAt(i);
if (tempChar == left) {
leftCount++;
} else if (tempChar == right) {
rightCount++;
if(i == logic.length()-1){
subLogicList.add(logic.substring(lastSubIndex));
}
} else if (tempChar == AND && logic.charAt(i + 1) == AND) {
if (leftCount == rightCount) {//保证操作的id不再括弧内
andFlag = true;
subLogicList.add(logic.substring(lastSubIndex, i));
i++;
lastSubIndex = i+1;
}
} else if (tempChar == OR && logic.charAt(i + 1) == OR) {
if (leftCount == rightCount) { //保证操作的id不再括弧内
orFlag = true;
subLogicList.add(logic.substring(lastSubIndex, i));
i++;
lastSubIndex = i+1;
}
} else{
if(i == logic.length()-1){
subLogicList.add(logic.substring(lastSubIndex));
}
}
}
if(andFlag == orFlag){
throw new LogicConfigException(logic+ "配置错误,最外层必须配置同一类型的逻辑分割符合");
}
List<ConditionGroup> listGroup = new ArrayList<ConditionGroup>();
if (subLogicList.size() > 0) {
for (String item : subLogicList) {
ConditionGroup logicGroup = resolve(item, validatorMap);
if (logicGroup != null) {
listGroup.add(logicGroup);
}
}
} else {
throw new LogicConfigException(logic+ " ()配对不全或者 缺少逻辑符号||, && ");
}
ConditionGroup returnGroup;
if (andFlag) {
returnGroup = new AndConditionGroupAdapter(listGroup);
} else {
returnGroup = new OrConditionGroupAdapter(listGroup);
}
return returnGroup;
}
/**
* 过滤外括号
* @param logic
* @return
*/
public static String trimLogic(String logic) {
if (logic == null || logic.trim().isEmpty()) {
return null;
}
if (logic.charAt(0) != left || logic.charAt(logic.length() - 1) != right) {
return logic;
} else {
int leftCount = 0;
for (int i = 0; i < logic.length(); i++) {
if (logic.charAt(i) == left) {
leftCount++;
} else if (logic.charAt(i) == right) {
leftCount--;
if (leftCount == 0 && i == logic.length() - 1) { //如果第一次和(匹配的是最后一个字符),那么去除外括号
return trimLogic(logic.substring(1, logic.length() - 1));
}else if(leftCount == 0){ //如果第一次和第一个(匹配的不是最后一个字符),那么直接返回
return logic;
}
}
}
return logic;
}
}
}
/**
* 逻辑组校验接口
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:03:53
*/
public interface LogicGroup {
/**
* 逻辑校验方法
* @param params
* @return
*/
public LogicValidateResult executeLogic(Map<String, String> params);
}
/**
* 逻辑原子校验组
* 一个原子校验组对应一个逻辑校验规则
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:04:48
*/
public class AtomicLogicGroup implements LogicGroup {
private LogicRuleVO logic;
public AtomicLogicGroup(final LogicRuleVO logic) {
this.logic = logic;
}
@Override
public LogicValidateResult executeLogic(Map<String, String> params) {
if(logic == null){
throw new ValidatorConfigException();
}
LogicValidateResult logicResult = null;
ValidateResult result = logic.getConclusionGroup().executeCondition(params);
//结论逻辑成功,那么设置成功的下一步
if(result.isSuccess()){
logicResult = LogicValidateResult.successInstance();
logicResult.setSuccessNextStep(logic.getSuccessNextStep());
}else {//如果失败,那么继续失败的下一步,并且设置失败原因
logicResult = LogicValidateResult.errorInstance(logic.getTip());
logicResult.setFailNextStep(logic.getFailNextStep());
logicResult.setConditionFailNextStep(logic.getConditionFailNextStep());
if(logic.getTip()== null || logic.getTip().isEmpty()){
logicResult.setMessage(result.getMessage());
}
}
return logicResult;
}
}
/**
* 推导原子校验组
* 一个推导原子校验组拥有一个校验器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:04:48
*/
public class DeduceAtomicLogicGroup implements LogicGroup {
private LogicRuleVO logic;
public DeduceAtomicLogicGroup(final LogicRuleVO logic) {
this.logic = logic;
}
@Override
public LogicValidateResult executeLogic(Map<String, String> params) {
if(logic == null){
throw new ValidatorConfigException();
}
LogicValidateResult logicResult = null;
ValidateResult conditionResult = logic.getConditionGroup().executeCondition(params);
//条件验证成功,那么验证结论逻辑
if(conditionResult.isSuccess()){
ValidateResult conclusionResult = logic.getConclusionGroup().executeCondition(params);
//结论逻辑成功,那么设置成功的下一步
if(conclusionResult.isSuccess()){
logicResult = LogicValidateResult.successInstance();
logicResult.setSuccessNextStep(logic.getSuccessNextStep());
}else {//如果失败,那么继续失败的下一步,并且设置失败原因
logicResult = LogicValidateResult.errorInstance(logic.getTip()); //TODO
logicResult.setFailNextStep(logic.getFailNextStep());
if(logic.getTip()== null || logic.getTip().isEmpty()){
logicResult.setMessage(conclusionResult.getMessage());
}
}
}else { //如果条件失败,那么判断条件失败的下一步
if(logic.getConditionFailNextStep() == NextStepType.goNext){
logicResult = LogicValidateResult.successInstance();
logicResult.setFailNextStep(NextStepType.goNext);
}else if(logic.getConditionFailNextStep() == NextStepType.returnFail){
//如果条件失败,那么返回此逻辑验证的失败message
logicResult = LogicValidateResult.errorInstance(logic.getTip());
logicResult.setFailNextStep(NextStepType.returnFail);
}
}
return logicResult;
}
}
/**
* 逻辑组校验AND类型的集成适配器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:06:55
*/
public class AndLogicGroupAdapter extends LogicGroupAdapter {
public AndLogicGroupAdapter(List<LogicGroup> list) {
this.list = list;
}
@Override
public LogicValidateResult executeLogic(Map<String, String> params) {
if(list == null || list.size() <= 0){
return LogicValidateResult.SUCCESS;
}else {
for(LogicGroup item : list){
LogicValidateResult result = item.executeLogic(params);
if(!result.isSuccess()){
//AND类型的逻辑的组合,如果第一个失败,并且 result.getConditionFailNextStep() == NextStepType.returnFail 直接返回
if(result.getFailNextStep() == NextStepType.returnFail){
return result;
}else if(result.getFailNextStep() == NextStepType.goNext){ //如果goNext 那么判断下一个and逻辑组
continue;
}
}else {
//如果当前研究组合成功,那么
if(result.getSuccessNextStep() == NextStepType.returnSuccess){
return result;
}
}
}
return LogicValidateResult.SUCCESS;
}
}
}
具体的校验器 接口定义(实现略):
/**
* 校验器
* @author wangxinchun1988@163.com
* @date 2013-12-1下午1:08:55
*/
public interface IValidator {
/**
* 校验器统一校验接口
* @param rule 校验规则
* @param name 参数名字
* @param params 待校验的参数集合
* @return 返回此验证结果
*/
public ValidateResult validate(RuleVO validator, Map<String, String> params);
}
/**
* 数字范围校验校验
*
* @author xinchun.wang
* eg: value = "[2,12]",
* value = "(2,12)",
* value = "[2,12)"
* value = "(2,12)"
*/
public class NumberLimitValidator extends AbstractValidator {
@Override
public ValidateResult validate(RuleVO validator, Map<String, String> params) {
//校验name对应的值不能为空
String paramValue = params.get(validator.getProperty());
try {
String ruleValue = validator.getRule();
boolean leftContains = false;
boolean rightContains = false;
if(ruleValue.startsWith("[")){
leftContains = true;
}
if(ruleValue.endsWith("]")){
rightContains = true;
}
ruleValue = removeRangeFlag(ruleValue);
String[] valueArr = ruleValue.split(",");
BigDecimal min = new BigDecimal(valueArr[0].trim());
BigDecimal max = new BigDecimal(valueArr[1].trim());
BigDecimal paramDecimal = new BigDecimal(paramValue);
if(leftContains == true && rightContains == true){
if(min.compareTo(paramDecimal) <=0 && max.compareTo(paramDecimal) >=0){
return ValidateResult.SUCCESS;
}else {
return ValidateResult.errorInstance(validator.getTip());
}
}else if(leftContains = true && rightContains == false){
if(min.compareTo(paramDecimal) <=0 && max.compareTo(paramDecimal) >0){
return ValidateResult.SUCCESS;
}else {
return ValidateResult.errorInstance(validator.getTip());
}
}else if(leftContains == false && rightContains == true){
if(min.compareTo(paramDecimal) <0 && max.compareTo(paramDecimal) >=0){
return ValidateResult.SUCCESS;
}else {
return ValidateResult.errorInstance(validator.getTip());
}
}else {
if(min.compareTo(paramDecimal) <0 && max.compareTo(paramDecimal) >0){
return ValidateResult.SUCCESS;
}else {
return ValidateResult.errorInstance(validator.getTip());
}
}
} catch (Exception e) {
logWarn(e, validator.getProperty(),params.get(validator.getProperty()),validator.getRule(),this.getClass().getName());
return ValidateResult.errorInstance(validator.getTip());
}
}
}
/**
* 验证器工厂
* @author xinchun.wang
*
*/
public class ValidatorFactory {
/**
* 保存通用验证器缓存*/
private static final Map<RuleType, IValidator> commonValidatorCacheMap = new HashMap<RuleType, IValidator>();
/**
* 本地验证器缓存*/
private static final ConcurrentHashMap<String, IValidator> localValidatorCacheMap = new ConcurrentHashMap<String, IValidator>();
/**
* 通用验证器
*/
private static StringNotEmptyValidator notEmptyValidator = new StringNotEmptyValidator();
private static StringEmptyValidator emptyValidator = new StringEmptyValidator();
private static StringRegxValidator stringRegxValidator = new StringRegxValidator();
private static StringLimitLengthValidator stringLimitLengthValidator = new StringLimitLengthValidator();
/** 格式型验证*/
private static DateFormatValidator dateFormatValidator = new DateFormatValidator();
private static NumberFormatValidator numberFormatValidator =new NumberFormatValidator();
private static NumberModValidator numberModValidator = new NumberModValidator();
private static NumberLimitValidator numberLimitValidator = new NumberLimitValidator();
/** 参考型验证*/
private static NumberReferCompareValidator numberReferCompareValidator = new NumberReferCompareValidator();
private static DateReferCompareValidator dateReferCompareValidator = new DateReferCompareValidator();
private static DateCompareNowValidator dateCompareNowValidator = new DateCompareNowValidator();
private static ValuesLimitValidator valuesLimitValidator = new ValuesLimitValidator();
static {
/** 通用验证器的注册*/
commonValidatorCacheMap.put(RuleType.empty, emptyValidator);
commonValidatorCacheMap.put(RuleType.not_empty, notEmptyValidator);
commonValidatorCacheMap.put(RuleType.string_regex, stringRegxValidator);
commonValidatorCacheMap.put(RuleType.number_format, numberFormatValidator);
commonValidatorCacheMap.put(RuleType.date_format, dateFormatValidator);
commonValidatorCacheMap.put(RuleType.string_length_limit, stringLimitLengthValidator);
commonValidatorCacheMap.put(RuleType.number_value_limit, numberLimitValidator);
commonValidatorCacheMap.put(RuleType.number_value_mod, numberModValidator);
commonValidatorCacheMap.put(RuleType.number_compare_refer, numberReferCompareValidator);
commonValidatorCacheMap.put(RuleType.date_compare_refer, dateReferCompareValidator);
commonValidatorCacheMap.put(RuleType.date_compare_now, dateCompareNowValidator);
commonValidatorCacheMap.put(RuleType.values_collection_limit, valuesLimitValidator);
}
public static IValidator getCommonValidator(RuleType ruleName) {
return commonValidatorCacheMap.get(ruleName);
}
/**
* 返回本地自定义的验证器
*/
public static IValidator getLocalValidator(String name){
return localValidatorCacheMap.get(name);
}
/** 注册自定义验证器
*/
public static void registerLocalValidator(String name,IValidator validator){
localValidatorCacheMap.putIfAbsent(name, validator);
}
}