(JAVA)String类型的逻辑语句编译
项目中遇到了动态配置条件触发相应事件的需求,需要根据String类型的逻辑语句,以及动态获取的数据,计算数据对应的结果,java实现。解决思路及代码实现如下,有需要的同学请自取。
一、需求提取
根据需求,抛开业务部分,我们可以将需求简化成以下核心逻辑。输入String类型的逻辑字符串,支持的逻辑符号包括 > , < , <= ,>= ,== ,() 。 例如: "(a>1&&b<2)||(c>=3&&d==4)" ,动态解析该字符串,并对输入的任意json类数据做出正确的逻辑判断。如{“b” : 10 , "a" : 9 , "c":"error" }。
二、设计思路
因为每一个最小的逻辑点。如 “a>1” 都只有两个结果:成功或者失败,并且成功或者失败后,往往需要执行下一个逻辑,所以该逻辑模型可以转换成一个二叉树的结构。据此我们先画出 "(a>1&&b<2)||(c>=3&&d==4)" 的逻辑图
每一个逻辑根据成功或者失败,指向了另外的逻辑,或者指向了最终结果,这里我们可以把指向的这个操作等价成指针,该指针指向了另外一个逻辑实体,或者指向了最终结果,又因为java中的指针,或者说引用都是需要事先指定数据类型的,如果我们使用逻辑实体和布尔类型的两种数据对象,那我们就只能将引用声明为两种数据对象的统一父类Object。但是因为Object在使用过程中涉及到了类型的判断及转化,很不方便,所以我们直接使用逻辑实体表示 逻辑,用 null表示可以直接返回最终结果。
除了两个引用以外,该逻辑实体应该还包括三个关键字,三个关键字有数据对应的key值"a" , 数据对应的逻辑符号 “>”,数据对应的阈值"1"。
据此,我们可以确定该逻辑实体的五个字段 ,建出以下实体
1 public class Logic { 2 //值对应的key值 3 private String key; 4 //逻辑符号 包括 > < >= <= == 5 private double symbol; 6 //阈值 7 private double value; 8 //成功是返回,为null时表示最终结果为true 9 private Logic sucLogic; 10 //失败是返回,为null时表示最终结果为false 11 private Logic failLogic; 12 13 //后面会用到的两个方法 14 //在logic树的每一层失败分支子树上都加一个成功时调用的对象 15 public void setSucLogicEveryFail(Logic logic){ 16 Logic logic1 = this; 17 while (true){ 18 logic1.setSucLogic( logic ); 19 if ( logic1.getFailLogic != null ){ 20 logic1 = logic1.getFailLogic(); 21 }else { 22 return; 23 } 24 } 25 } 26 //在logic树的每一层成功分支上子树上都加一个失败时调用的对象 27 public void setFailLogicEverySuc(Logic logic){ 28 Logic logic1 = this; 29 while (true){ 30 logic1.setFailLogic( logic ); 31 if ( logic1.getSucLogic != null ){ 32 logic1 = logic1.getSucLogic (); 33 }else { 34 return; 35 } 36 } 37 } 38 }
使用该实体的原因如下:
1) 可以很清楚的表明逻辑关系
2) 增加了处理时的开销,减少了使用时的开销,更好的支持大批量的数据判断
三、编码实现
1. 根据string生成Logic对象的代码
1 public class CreateLogic { 2 3 private static String[] symbol = {">=","<=",">","<","=="}; 4 private static String[] backSymbol = {"<=",">=","<",">","=="}; 5 6 public static void main(String[] args) { 7 CreateLogic createLogic = new CreateLogic(); 8 Logic logic = createLogic.handleContentLogic("(a>1&&b<2)||(c>=3&&d==4)"); 9 System.out.println( logic); 10 } 11 12 private Logic handleContentLogic(String content) { 13 //1.去除掉首位的无效括号 14 content = this.removeNoUseContent( content ); 15 //2.将content拆成小的逻辑块。 16 List<String> blockContents = new ArrayList<>(); 17 int point = 0; 18 int flag = 0; 19 for (int i = 0; i < content.length(); i++) { 20 char c = content.charAt(i); 21 if( '(' == c){ 22 flag++; 23 continue; 24 }else if( ')' == c){ 25 flag--; 26 if( flag == 0 ){ 27 blockContents.add( content.substring( point , i + 1) ); 28 point = i + 1; 29 } 30 }else if( flag == 0 && ('|' == content.charAt(i) || '&' == content.charAt(i)) ){ 31 if( i - point > 1){ 32 blockContents.add( content.substring( point , i ) ); 33 point = i; 34 } 35 }else if( i == content.length() - 1){ 36 blockContents.add( content.substring( point , i + 1 ) ); 37 } 38 } 39 //3.遍历获取最终逻辑 40 Logic logic = null; 41 for (int i = 0; i < blockContents.size(); i++) { 42 String blockContent = blockContents.get(i); 43 if( blockContent.startsWith("||(") ){ 44 Logic logic1 = this.handleContentLogic(blockContent.substring(2)); 45 logic.setFailLogicEverySuc(logic1); 46 }else if( blockContent.startsWith("&&(") ){ 47 Logic logic1 = this.handleContentLogic(blockContent.substring(2)); 48 logic.setSucLogicEveryFail(logic1); 49 }else if( blockContent.startsWith("&&") ) { 50 Logic logic1 = this.getLogicBySimpleContent(blockContent.substring(2)); 51 logic1.setSucLogicEveryFail(logic); 52 logic = logic1; 53 }else if( blockContent.startsWith("||") ) { 54 Logic logic1 = this.getLogicBySimpleContent(blockContent.substring(2)); 55 logic1.setFailLogicEverySuc(logic); 56 logic = logic1; 57 }else { 58 logic = this.getLogicBySimpleContent(blockContent); 59 } 60 } 61 return logic; 62 } 63 64 /** 65 * 去除掉首位的无效括号 66 * @param content 67 * @return 68 */ 69 public String removeNoUseContent( String content ){ 70 List<String> list = new ArrayList<>(Arrays.asList(content.split(""))) ; 71 //1.首位的小括号为无效的小括号,先去除掉 72 int flag1 = 0; 73 int flag2 = 0; 74 while (true){ 75 if( "(".equals(list.get(0) )){ 76 flag1++; 77 list.remove(0); 78 }else { 79 break; 80 } 81 } 82 if( flag1 > 0 ){ 83 for (int i = 0; i < list.size(); i++) { 84 if( flag1 == 0 ){ 85 break; 86 } 87 if( "(".equals(list.get(i) ) ){ 88 flag2++; 89 }else if( ")".equals( list.get(i) ) ){ 90 if(flag2 > 0){ 91 flag2--; 92 continue; 93 }else { 94 flag1--; 95 list.remove(i); 96 i--; 97 } 98 } 99 } 100 } 101 return StringUtils.join(list.toArray()); 102 } 103 104 /** 105 * 简单的逻辑文本直接转换成一个逻辑实体 106 * @param blockContent 107 * @return 108 */ 109 private Logic getLogicBySimpleContent(String blockContent) { 110 Logic logic = new Logic(); 111 for (int i = 0; i < symbol.length; i++) { 112 if( blockContent.indexOf( symbol[i] ) != -1 ){ 113 String value1 = blockContent.substring(0 , blockContent.indexOf( symbol[i] )); 114 String value2 = blockContent.substring( blockContent.indexOf( symbol[i] ) + symbol[i].length()); 115 try { 116 double b = Double.valueOf(value2); 117 logic.setKey(value1); 118 logic.setValue(b); 119 logic.setSymbol(symbol[i]); 120 }catch (Exception e){ 121 double b = Double.valueOf(value1); 122 logic.setKey(value2); 123 logic.setValue(b); 124 logic.setSymbol(backSymbol[i]); 125 } 126 return logic; 127 } 128 } 129 return logic; 130 } 131 }
2. 根据Logic和json判断最终结果
1 public class HandleLogic { 2 /** 3 * 根据逻辑树,递归获取最终的逻辑结果s 4 */ 5 public boolean handleMessageByLogicCore(Logic logic , JSONObject object ) { 6 boolean bool = false; 7 String key = logic.getKey(); 8 if( object.get(key) == null ){ 9 return this.getLogicByResult(logic , bool , object); 10 } 11 double value = logic.getValue(); 12 double realValue = object.getDoubleValue( key ); 13 switch ( logic.getSymbol() ){ 14 case ">=": 15 bool = realValue >= value; 16 break; 17 case "<=": 18 bool = realValue <= value; 19 break; 20 case "==": 21 bool = realValue == value; 22 break; 23 case "<": 24 bool = realValue < value; 25 break; 26 case ">": 27 bool = realValue > value; 28 break; 29 } 30 return this.getLogicByResult(logic , bool , object); 31 } 32 33 /** 34 * 根据逻辑的结果,获取逻辑的成功/失败的子逻辑树,不存在则直接返回成功/失败 35 * @param logic 当前逻辑树 36 * @param b 当前逻辑树的执行结果 37 * @param object 当前逻辑树的处理对象 38 * @return 39 */ 40 private boolean getLogicByResult(Logic logic, boolean b, JSONObject object) { 41 if( b ){ 42 if( logic.getSucLogic() == null ){ 43 return true; 44 }else { 45 return handleMessageByLogicCore( logic.getSucLogic() , object ); 46 } 47 }else { 48 if( logic.getFailLogic() == null ){ 49 return false; 50 }else { 51 return handleMessageByLogicCore( logic.getFailLogic() , object ); 52 } 53 } 54 } 55 }
以上就是逻辑语句编译的总结,原创不易,转载请注明出处。