为什么80%的码农都做不了架构师?>>>   

背景介绍:

为什么需要这个表达式解析微引擎?

首先这个引擎是产生于调用链路跟踪系统,我们知道在调用跟踪系统里经常会根据关键字搜索日志但有时候我们搜一个关键字可能搜出N条记录这时我们就需要有表达式了需要更精准搜索,比如搜 既包含 'a' 又包含 'b' 再排除 'c'  等类似这样。

那一般的做法可能就是前端搞一个动态表单,然后用户去选择类型(and、or、not),这样就需要前端修改了。重点来了,有没有一种方式前端不修改后端服务去解析用户输出的搜索词汇重而得出我们想要的表达式呢?

请往下看

解析引擎源码:

public class Keyword {private String key;private RelationEnum relation;public Keyword(String key,RelationEnum relation) {this.key = key;this.relation = relation;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public RelationEnum getRelation() {return relation;}public void setRelation(RelationEnum relation) {this.relation = relation;}}public enum LabelEnum {AND(new Character('&'),RelationEnum.AND),OR(new Character('|'),RelationEnum.OR),BLANK(new Character(' '),RelationEnum.OR),EXCLAMATION(new Character('!'),RelationEnum.NO);private Character label;private RelationEnum relation;LabelEnum(Character label,RelationEnum relation) {this.label = label;this.relation = relation;}public Character getLabel() {return label;}public void setLabel(Character label) {this.label = label;}public RelationEnum getRelation() {return relation;}public void setRelation(RelationEnum relation) {this.relation = relation;}
}public enum RelationEnum {AND,OR,NO
}public class SquareBracket {private LinkedList<Integer> left = Lists.newLinkedList();private LinkedList<Integer> right = Lists.newLinkedList();public void addLeft(int index) {this.left.add(index);}public void addRight(int index) {this.right.add(index);}public LinkedList<Integer> getLeft() {return left;}public LinkedList<Integer> getRight() {return right;}}public enum TagStatusEnum {VALID,UNCONFIRMED,INVALID
}public class Tag {private int index;private LabelEnum label;private TagStatusEnum status;public Tag(LabelEnum label,int index,TagStatusEnum labelStatusEnum) {this.label = label;this.index = index;this.status = labelStatusEnum;}public LabelEnum getLabel() {return label;}public void setLabel(LabelEnum label) {this.label = label;}public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}public TagStatusEnum getStatus() {return status;}public void setStatus(TagStatusEnum status) {this.status = status;}}public class ExpressionProcessor {private static final char PREFIX_BRACKET = '[';private static final char SUFFIX_BRACKET = ']';/*** 分词keyword,并解析相应关系* 具体参考:{@linkplain com.huize.framework.apm.data.es.expression.LabelEnum} </br>* 如果表达式的特殊字段需要查询则需要用 ‘[]’括起则有效,且在同一组中,只有最外层的有效;</br>* * <pre>* ExpressionProcessor.split("12&34") = (12,&)、(34,&)* ExpressionProcessor.split("12!34") = (12,&)、(34,!)* ExpressionProcessor.split("12[!]34") = (12!34,&)* ExpressionProcessor.split("12[[!34]]") = (12[!34],&)* </pre>*/public static List<Keyword> split(String keyword) {return convert(keyword,mark(keyword));}private static  Pair<List<Tag>,List<SquareBracket>> mark(String keyword) {List<Tag> tags = Lists.newArrayList();TagStatusEnum status = TagStatusEnum.VALID;int unconfirmedCount = 0;Tag tag = null;List<SquareBracket>  squareBrackets = Lists.newArrayList();SquareBracket squareBracket = new SquareBracket();squareBrackets.add(squareBracket);for (int i = 0; i < keyword.length(); i++) {final char ch = keyword.charAt(i);if(ch == PREFIX_BRACKET) {if(unconfirmedCount == 0) {squareBracket = new SquareBracket();squareBrackets.add(squareBracket);}squareBracket.addLeft(i);unconfirmedCount += 1;status = TagStatusEnum.UNCONFIRMED;continue;}if(ch == SUFFIX_BRACKET) {unconfirmedCount -=1;if(status == TagStatusEnum.UNCONFIRMED) {resetTagStatus(tags);}if(unconfirmedCount == 0) {status = TagStatusEnum.VALID;}squareBracket.addRight(i);continue;}tag = getTag(ch,i,status);if(i == 0 && tag== null) {tag = new Tag(LabelEnum.AND, -1, TagStatusEnum.VALID);}if(tag != null) {tags.add(tag);}}return Pair.of(tags, squareBrackets);}private static List<Keyword> convert(String keyword,Pair<List<Tag>,List<SquareBracket>> pair) {List<Tag> tags = pair.getLeft();if(CollectionUtils.isEmpty(tags)) {Lists.newArrayList(new Keyword(keyword,RelationEnum.AND));}List<Keyword> keywords = Lists.newArrayListWithCapacity(tags.size()); List<Integer> bracketIndexs = getValidBracketIndexs(pair.getRight());final int size = tags.size();int step = 0;int next = 0;for(int i = 0; i < size; i++) {Tag tag = tags.get(i);if(tag == null) {continue;}if(TagStatusEnum.INVALID == tag.getStatus()) {continue;}next = i + 1;int index = tag.getIndex();step = index;if (next < size) {while(TagStatusEnum.INVALID == tags.get(next).getStatus() && next < (size -1)) {next += 1;}if(TagStatusEnum.INVALID == tags.get(next).getStatus()) {step = keyword.length();}else {step = tags.get(next).getIndex();}}else {step = keyword.length();}if(step - index > 1) {keywords.add(new Keyword(cut(keyword,index+1,step,bracketIndexs),tag.getLabel().getRelation()));}}return keywords;}private static String cut(String keyword,int start,int end,List<Integer> bracketIndexs) {List<Integer> list = Lists.newArrayList();for(Integer index : bracketIndexs) {if(index >=start && index <= end) {list.add(index);}}StringBuffer buffer = new StringBuffer(StringUtils.substring(keyword,start,end));if(!CollectionUtils.isEmpty(list)) {int delCount = 0;for(int index : list) {int delIndex = index - delCount- start;char ch = buffer.charAt(delIndex);if(ch == PREFIX_BRACKET || ch == SUFFIX_BRACKET) {buffer.deleteCharAt(delIndex);delCount += 1;}}}return buffer.toString();}private static void resetTagStatus(List<Tag> tags) {if(!CollectionUtils.isEmpty(tags)) {for(Tag tag : tags) {if(TagStatusEnum.UNCONFIRMED == tag.getStatus()) {tag.setStatus(TagStatusEnum.INVALID);}}}}private static Tag getTag(char charset,int index,TagStatusEnum status) {LabelEnum label = null;if(LabelEnum.AND.getLabel() == charset) {label = LabelEnum.AND;}else if(LabelEnum.OR.getLabel() == charset) {label = LabelEnum.OR;}else if(LabelEnum.BLANK.getLabel() == charset) {label = LabelEnum.BLANK;}else if(LabelEnum.EXCLAMATION.getLabel() == charset) {label = LabelEnum.EXCLAMATION;}if(label != null) {return new Tag(label,index,status);}return null;}private static List<Integer> getValidBracketIndexs(List<SquareBracket>  squareBrackets) {List<Integer> bracketIndexs = Lists.newArrayList();if(CollectionUtils.isEmpty(squareBrackets)) {return bracketIndexs;}for(SquareBracket squareBracket : squareBrackets) {if(CollectionUtils.isEmpty(squareBracket.getLeft()) || CollectionUtils.isEmpty(squareBracket.getRight())) {continue;}int first = squareBracket.getLeft().getFirst();int last = squareBracket.getRight().getLast();if(last > first) {bracketIndexs.add(first);bracketIndexs.add(last);}}return bracketIndexs;}}

代码就上面这么多,非常简洁。

下面就来测试下:

public class ExpressionProcessorTest {public static void main(String[] args) {String keyword = "a&d!c";//String keyword = "20180209002149[!]27343565";//String keyword = "20180209002149[!&!]27343565";//String keyword = "201802||09002149[!&!]27343565&&sdfas";//String keyword = "测试]][[!]测试[[[[psdf]23541345!@#$%^|)(*";//String keyword = "201802|||09002149[!&!]27343565&&sdfas";//String keyword = "201802|||!!09002149[!&!]27343565&&sdfas";//String keyword = "201802||!!09002149[!&!]27343565&&sdfas";System.out.println(JsonUtils.beanToJson(ExpressionProcessor.split(keyword)));}}

运行:

[{"key":"a","relation":"AND"},{"key":"d","relation":"AND"},{"key":"c","relation":"NO"}]

转载于:https://my.oschina.net/woter/blog/1843812

JAVA关系表达式解析微引擎相关推荐

  1. java aviator_Aviator 表达式求值引擎开源框架

    简介¶ Aviator是一个高性能.轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值.现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢? Aviato ...

  2. java 数学表达式解析插件_数学表达式解析-JAVA版

    1 .工具介绍 String exp = "v>=10&&v<=2000&&v%10==0"; 在 js 中,能够直接运行 eval 得 ...

  3. Java关系表达式x y,java8--函数式接口,以及和Lambda表达式的关系

    一:函数式接口 函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract Method). jdk8的lambda表达式的函数式接口主要有: imag ...

  4. java jexl 工具类_jexl表达式解析、计算工具类.md

    jexl表达式解析.计算工具类.md 根据表达式可以动态反向解析出变量:适合动态表达式,参数未知场景 如 (A0.2+B0.8)/C 解析出 A\B\C,把ABC参数值代入计算 初始化引擎 priva ...

  5. 【Java工具类】学会MVEL2.0,表达式解析再不怕

    文章目录 常见的表达式引擎 一.什么是MVEL? 二.快速入门 三.语法 1.基本语法 1.1 简单属性表达式 1.2 布尔表达式 1.3 复合语句表达式 1.4 返回值 2. 操作符 2.1 一元操 ...

  6. AVIATOR——轻量级JAVA表达式求值引擎

    简介 Aviator是一个高性能.轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值.现在已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢? Aviator ...

  7. java juel表达式_activiti 自定义函数解析juel表达式

    activiti是支持juel表达式的,这个也很好用,但实际过程中需要支持类方法及变量. 原来项目中解析juel,这边有自定义一个方法的 代码如下: public String getStringBy ...

  8. Java 表达式解析(非原创)

    因项目需要,在网上找来一套表达式解析方法,由于原来的方法太过于零散,不利于移植,现在整理在同一文件内: 文件中包含5个内部类,源码如下: 1 import java.util.ArrayList; 2 ...

  9. java 自定义表达式_Java中使用Groovy实现自定义表达式解析

    Groovy作为一种JVM-Based语言,目前普及程度正在提高.本文演示一下在Java类中,通过继承GDK的groovy.lang.Script类如何支持自定义表达式解析功能. 输入: 表示一行数据 ...

最新文章

  1. TOAD FOR MYSQL 进行数据插入时乱码的解决办法---MariaDB 5.5
  2. python自动化脚本实例100条-自动化运维基础实例解析-Python批量登录到服务器执行任务...
  3. CTO:再写if-else,逮着一个罚款1000!
  4. localdatetime 默认时间_java中的时间与时区:LocalDateTime和Date
  5. python编辑配置_Python环境安装及编辑器配置(一)
  6. miui12怎么自定义开机动画_MIUI12一天的体验,像换新机一样,感知超强!
  7. 一名高校老师的观点:高考志愿该怎么填
  8. 目前Java编程语言最流行的7个框架,你了解多少?
  9. 多传感器融合理论及其应用——2
  10. orcad元件封装制作
  11. 【VHDL语言学习笔记(七)】 分频器
  12. SMC在线气动制图软件PneuDraw
  13. [面试问答] 面试常问的40个问题 附带经典答案!
  14. 正大国际琪貨纯手:期货投资中该如何看懂趋势线?
  15. 10bit视频是什么?
  16. Python爬虫实训案例之爬取豆瓣电影Top250并保存至excel
  17. 人脸识别通过什么区分人脸和照片
  18. 华为手机如何安装google play, chrome等
  19. Windows10 2021年5月更新正式推出,驱动人生详细介绍win10更新新功能
  20. Image Thresholding图像阙值化和Adaptive Thresholding

热门文章

  1. python语言表白语句简单_简短的表白语句
  2. iframe 禁止打开新窗口_教育部新政策:禁止中学生复读?
  3. linux文件一列加1,Linux命令(1)-创建文件
  4. java 飞信接口_java 飞信接口
  5. vim中直接打开ipython的方法
  6. 电脑中没有oracle服务器,用AnySQL在没有oracle客户端的服务器上发送邮件
  7. 星系超级计算机,Mira超级计算机“最后的旅程”:阿贡实验室进行了一次超大规模宇宙模拟...
  8. 【项目管理】PMO-为强大的收益实现演变
  9. 笔记-项目采购管理-规划采购管理
  10. WIN7系统共享访问方式总结