- 浏览: 341016 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (212)
- spring (21)
- design pattern(java) (12)
- linux-shell (28)
- java-thread (20)
- java-collection (6)
- java-reflect (9)
- mysql (11)
- java-io (7)
- java-util&lang&io (3)
- algorithm (3)
- interview (2)
- tools-eclipse (2)
- tools-maven (1)
- web-script (1)
- java组建 (13)
- 博客收藏 (1)
- 架构设计与实践 (10)
- active-mq (6)
- java-jvm&性能&原理 (27)
- tomcat (2)
- flume (1)
- serialization (2)
- git (1)
- cache&redis (8)
- guava (1)
- zookeeper (3)
- socket&tcp&udp&http (6)
- test (1)
最新评论
-
bbls:
有用有用有用
java-jvm-jstack-(监视器和锁的概念) -
王新春:
小侠有点帅哦 写道此流怎么关闭新春这个实现 可以不关闭的,哈哈 ...
源码剖析之java.io.ByteArrayOutputStream -
小侠有点帅哦:
此流怎么关闭新春
源码剖析之java.io.ByteArrayOutputStream -
cumt168:
写的很好为什么初始化参数,年轻代-Xmn10M def new ...
jvm之内存申请过程分析 -
ronin47:
应该是跟共享域名思路差不多,根据cookie的key作判断
跨域:一种通过服务端解决跨域的实现
近期由于工作的需要,写了一个简易的参数校验框架,虽然市场上有common-validator 和hibernate-validator两个开源的,但是有些情景他们是无法满足的,比如参数字段之间的依赖关系,这在项目中是极其常见的。他们仅仅提供了对字段的简单的格式校验。另外这两种校验框架的校验器都是有状态的,这样导致校验的性能不好,对于录入还无所谓,但是批量excel 导入的这种,就非常吃力了。
出于性能和依赖关系校验的需求,改造下工作的校验框架为一个通用的参数校验框架,支持表达式的格式校验,灵活性极好,代码完全复用,思路明了,适合复杂的参数校验场景,希望各位给予指正其中的不足~
下面我贴出来了我写的框架的代码,但是太麻烦搞格式,我也懒的搞,如果有兴趣,可以下载源码看看~
git地址为:https://github.com/wangxinchun/javaframe-validator
先看下这个框架的用法:
测试用例:
引用术语:
一个对象有多个属性
每个属性对应一个校验规则集合
一个校验规则集合对于多个校验规则
每个校验规则有一个或者多个校验条件和结论组成。
基于以上的分析,定义对以上角色的注解抽象:
规则定义完毕,下面就是解析校验规则了:
逻辑条件 和 逻辑结论的解析和组装
具体的校验器 接口定义(实现略):
出于性能和依赖关系校验的需求,改造下工作的校验框架为一个通用的参数校验框架,支持表达式的格式校验,灵活性极好,代码完全复用,思路明了,适合复杂的参数校验场景,希望各位给予指正其中的不足~
下面我贴出来了我写的框架的代码,但是太麻烦搞格式,我也懒的搞,如果有兴趣,可以下载源码看看~
git地址为:https://github.com/wangxinchun/javaframe-validator
先看下这个框架的用法:
/** * 验证要求: * 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); } }
发表评论
-
guava-cache-本地缓存(收藏)
2017-05-22 20:00 2853范例 -
jackson-filter特性
2016-07-12 17:20 3949jackson提供动态序列化的输出json static ... -
json-jackson多子类继承的反序列化
2015-03-24 20:31 11040相关文章: http://wangxinchun.iteye. ... -
HttpAsyncClient
2014-12-16 18:31 3398参考: http://wangxinchun.iteye.co ... -
Httpclient再续
2014-11-16 12:55 2413参考: http://wangxinchun.iteye.co ... -
hibernate-validator
2014-11-13 18:08 2678在web工程中,对于用户 ... -
HttpClient
2014-10-13 18:16 2047参考: http://wangxinchun.iteye.co ... -
slf4j-logback-filter-MDC进阶
2014-08-13 11:44 6394Have lots of ideas and throw ... -
slf4j-logback-Appender进阶
2014-08-08 11:17 7207logback 进阶 基础篇请参考http://wangxin ... -
slf4j-logback
2014-07-22 00:33 3092上一篇文章讲了log4j的 ... -
slf4j-log4j
2014-07-19 21:09 2566在几乎所有的业务系统中,日志是必不可少的组建,尤其是复杂的业务 ... -
java-json
2014-04-26 17:45 2320相关文章: http://dreamhead.blogbus. ...
相关推荐
综上所述,自定义校验注解框架"monkey-validator"可能包括了上述步骤的实现,提供了方便快捷的方式来创建和管理项目特定的参数校验规则。通过学习和使用这个框架,开发者可以更好地理解Java的注解机制以及如何构建...
在工作中,我看到JavaEE6中提供了一个基于注解的Bean校验框架,另外Hibernate也提供了类似功能的基于java注解的校验,我们产品也需要这种功能,无奈用的是JavaEE5,因此我自己写了一个简单的基于注解的校验框架,...
基于Spring boot + maven,以注解+AOP方式实现的java后端项目接口参数校验框架。迄今为止使用最简单、最容易理解的参数校验方案。博客地址:https://blog.csdn.net/weixin_42686388/article/details/104009771
在“ssm基于注解的项目搭建”中,我们主要会涉及到以下几个关键知识点: 1. **Spring框架**:Spring是Java企业级应用的核心框架,它提供了依赖注入(DI)和面向切面编程(AOP)等功能,通过管理对象的生命周期和...
在这个基于注解的简单案例中,我们将深入探讨如何使用MyBatis进行基本的数据操作:增加、删除、修改和查询。 首先,我们需要在项目中引入MyBatis的依赖库。通常,这可以通过Maven或Gradle的配置来完成。在Maven的...
本项目“mybatis-demo12-动态SQL语句2-基于注解配置”是针对MyBatis动态SQL功能的一个示例,主要探讨如何通过注解方式来实现动态SQL。 1. **动态SQL**: 动态SQL是MyBatis的核心特性之一,它允许我们在运行时根据...
**基于注解的Spring JdbcTemplate** 在Java世界中,Spring框架是企业级应用开发的首选。Spring JDBC模絫提供了一种简洁的方式来处理数据库操作,而`Spring JdbcTemplate`是这个模絫的核心组件。本教程将深入探讨...
本项目基于注解的实现方式,使得配置更为简洁,同时也展现了现代Java开发的便利性。以下将详细讲解这三个框架及其注解的使用。 **Spring 3.x** Spring是一个全面的后端开发框架,它提供了依赖注入(DI)、面向切面...
在Java编程中,基于注解(Annotation)的加签验是一种常见的代码管理和验证技术,它允许程序员通过在源代码中添加元数据来实现特定的功能或逻辑。这些注解可以用于各种目的,包括但不限于数据验证、依赖注入、编译时...
在Spring MVC框架中,基于注解的编程方式极大地简化了Web应用的开发,尤其是在处理HTTP请求,如form表单提交时。本篇文章将深入探讨如何使用注解来实现在Spring MVC中处理form表单的数据,以及如何将这些数据保存到...
Hybris的验证框架是基于JSR 303(Java Bean Validation)标准,允许开发者直接在模型的字段上添加注解来进行数据校验。这使得数据校验的实现更加简洁且易于理解。 2.1. Hybris验证框架特性 - 自动校验:在Hybris中...
该框架能够根据用户参数和应用场景的模板自动生成加解密代码,同时对开发者代码进行校验,在编译阶段发现并报出错误。这样可以确保开发者正确地使用密码学 API,减少安全漏洞的出现。 除了 SecureCrypto 框架外,...
基于注解的SpringMVC是Spring框架中的一个关键模块,用于构建Web应用程序。SpringMVC以其松耦合、模块化和高度可配置性而受到广大开发者的欢迎。在这个框架中,注解扮演着核心角色,使得开发者无需编写大量的XML配置...
本资料将详细解析这三个框架的整合,并重点探讨基于注解的配置方式。 一、Spring框架 Spring的核心特性是依赖注入(DI),它通过控制反转(IoC)实现了对象之间的解耦。在基于注解的配置中,我们可以使用`@...
### hibernate验证框架学习 #### 一、简介与入门 **Hibernate Validator** 是一个流行的 Java 验证框架,它实现了 **JSR 349**(即 Java Bean Validation API)规范,提供了强大的验证功能,帮助开发者确保应用...
本文将详细介绍一种基于Java的后台验证框架设计思路及其应用场景,旨在为开发者提供一种高效、可扩展且易于使用的验证方案。 #### 二、应用场景 在实际开发过程中,特别是在action或facade层,我们需要实现统一的...
同时,通过`<cache:annotation-driven>`标签启用基于注解的缓存处理。 7. **MyBatis与Memcached结合**: 虽然MyBatis本身不支持缓存,但可以通过Spring的缓存抽象层与Memcached进行整合。在MyBatis的Mapper接口...
在本文中,我们将深入探讨基于注解的Spring MVC在实现增删改操作中的应用。Spring MVC是Spring框架的一部分,主要用于构建Web应用程序。它利用注解简化了开发过程,使得开发者无需编写大量的XML配置文件,就能实现...
在实际开发中,OVal常用于表单验证、API参数校验、业务对象验证等场景,帮助提升代码质量和用户体验。 总结,Java对象验证框架OVal以其便捷的注解使用、强大的自定义能力、灵活的验证策略和良好的扩展性,成为Java...
本小DEMO将演示如何在Spring MVC环境中集成并使用基于注解的AOP。 首先,我们来理解AOP的核心概念。AOP的目标是将那些影响多个类的代码(如日志、事务管理、性能监控等)抽取出来,形成独立的模块,称为切面。切点...