我是靠谱客的博主 眯眯眼心情,最近开发中收集的这篇文章主要介绍jep在java的SpringBoot中的使用jep一、在pom文件中引jep的jar包:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

jep

JEP是Java expression parser的简称,即java表达式分析器,Jep是一个用来转换和计算数学表达式的java库。通过这个程序包,用户可以以字符串的形式输入一个、任意的公式,然后快速地计算出结果。Jep支持用户自定义变量、常量和函数。包括许多常用的数学函数和常。

一、在pom文件中引jep的jar包:

<dependency>
<groupId>jep</groupId>
<artifactId>jep-java</artifactId>
<version>3.5-trial</version>
</dependency>

二、 在yaml文件中配置公式:

logic:
signal:
target:
signalOnOff: fSignalOnOffs
curSignalLights: fCurSignalLights
signalLight: fSignalLights
softDelayTime: fSoftDelayTime
shuntingSignalLight: fD_SignalLight
reference:
fSignalOnOffs: ((signalType==1) || (signalType==2))?(KDJ==1?1:(KDJ==0?2:0)):0
fD_SignalLight: (signalType==3)?(DJ==1?(DXJ==1?(LFJ==1?"0x55":"0x99"):"0x67"):"0x84"):""
fcurSignalLights: (signalType==3)?(shuntingSignalLight):""
fSignalLights: (signalType==3)?((curSignalLights=="0x84")?(softDelayTime<=3?
lastSignalLights:curSignalLights):curSignalLights):""
fSoftDelayTime: curSignalLights=="0x84"?lastSoftDelayTime+1:0

在yaml文件中配置公式:当表达式非常长时,可以利用符号 | 分行写:

 //例如:上面的fSignalLights
fSignalLights: |
(signalType==3)?
((curSignalLights=="0x84")?
(softDelayTime<=3?
lastSignalLights:curSignalLights):
curSignalLights):""

三、入参(yaml文件配置字段的声明):

public class SignalInput {
//入参
private Integer kzMode = -1;
private Integer signalId=-1;
private Integer signalType=-1;
private String signalOrder="0x80";
private Integer DJ = -1;
private Integer DXJ = -1;
private Integer LFJ = -1;
private Integer KDJ = -1;
private Integer lastSoftDelayTime = 0;
private String lastSignalLights="0x2a";
//出参:需要逻辑处理的状态
private Integer signalOnOff;
private String signalLight;
private String curSignalLights;
private String shuntingSignalLight;
private rivate Integer softDelayTime;
}

四、给入参字段赋值,每组对象存入valueList

/**
* 载入json数据
*/
public void loadData() {
SignalInput signalInput1 = new SignalInput();
signalInput1.setKzMode(2);
signalInput1.setSignalOrder("");
signalInput1.setSignalId(1);
signalInput1.setSignalType(3);
signalInput1.setDj(1);
signalInput1.setDxj(0);
signalInput.setLastSignalLights("0x2a");
signalInput.setLastSoftDelayTime(5);
valueList.add(new ObjectValueBean(signalInput1));
this.valueList = valueList;
}

五、计算


@Service
public class SignalService {
private List<IValuable> valueList;
private ExpUtil expUtil;
public void proc(String cppMsg,Long receiveTime) throws Exception {
expUtil = new ExpUtil();
//配置入参-------上面第四步的方法
loadData();
//循环处理
for(IValuable valuable : valueList) {
//计算。。。。。
expUtil.processRes(valuable, LogicGlobal.signalTargetMap,
LogicGlobal.signalOrders, LogicGlobal.signalExpMap);
}
}
}

5.1 yaml配置中字段映射到map

//读取yaml配置
public void initConfig() {
//读取logic.yaml中的信息
LogicGlobal.signalTargetMap = (Map<String,String>) YamlReader.instance.getValueByKey("logic.signal.target");
LogicGlobal.signalRefMap = (Map<String,String>) YamlReader.instance.getValueByKey("logic.signal.reference");
}
//将yaml对应的公式 和 计算结果 定义在全局 map 
public class LogicGlobal {
public static Map<String, String> signalTargetMap = new HashMap<>();
public static Map<String, String> signalRefMap = new HashMap<>();
/**存储公式和对应的Jep计算器对象*/
public static Map<String,JepExp> signalExpMap;
/**存储计算结果*/
public static Set<String> signalOrders;
}
//给yaml对应的公式 和 计算结果 定义在全局的
map 中放值
//将yaml中字段放进 map,方便获取
public void initSignal() throws Exception {
LogicGlobal.signalExpMap = new HashMap<String,JepExp>();
LogicGlobal.signalOrders = new LinkedHashSet<String>();
expUtil.initCalculatorOrder(LogicGlobal.signalTargetMap,LogicGlobal.signalRefMap,LogicGlobal.signalOrders,LogicGlobal.signalExpMap);
}
/**
* 初始化计算顺序,当存在字段的循环引用时会抛出异常
* @throws Exception
*/
public void initCalculatorOrder(Map<String, String> targetMap,Map<String, String> referenceMap,Set<String> calculationOrder,Map<String,JepExp> expMap) throws Exception {
if(targetMap==null
|| targetMap.keySet().isEmpty()
|| referenceMap==null
|| referenceMap.keySet().isEmpty())
return;
List<String> order = new ArrayList<String>();
for(String fieldName:targetMap.keySet())
{
this.addFormulaFields(targetMap,referenceMap,fieldName, order,expMap,fieldName);
}
calculationOrder.addAll(order);
}
/**
* 添加公式的字段
* @param fieldName
* @param order
* @param childFieldName
* @throws Exception
*/
public void addFormulaFields(Map<String, String> targetMap,Map<String, String> referenceMap,String fieldName, List<String> order,Map<String,JepExp> expMap,String childFieldName) throws Exception{
String formulaKey = targetMap.get(childFieldName);
if (formulaKey!=null && !"".equals(formulaKey)) {
// The current column has a formula, add it in the order
order.add(0, childFieldName);
String formula = referenceMap.get(formulaKey);
JepExp jep = new JepExp(formula);
jep.parse();
expMap.put(formulaKey, jep);
Set<String> children = jep.findChildren();
for (String child: children) {
if (child.equals(fieldName)) {
throw new Exception("Circular formula on field: " + fieldName);
}
addFormulaFields(targetMap,referenceMap,fieldName, order, expMap,child);
}
}
}

5.2 yaml配置中公式中的变量

public class JepExp {
/***/
private Jep jep = new Jep();
/***/
private String formula;
/** The root node of the formula */
protected Node node;
protected Object result;
public JepExp(String formula)
{
this.formula = formula;
}
/**
* 解析公式表达式
* @return
* @throws ParseException
*/
public boolean parse() throws ParseException
{
if (formula == null) {
return false;
}
jep.setComponents(new StandardConfigurableParser(),new JavaOperatorTable());
node = jep.parse(formula);
return true;
}
public void setComponents() throws ParseException
{
jep.setComponents(new StandardConfigurableParser(),new JavaOperatorTable());
}
}

1、jep计算:进入expUtil.processRes()方法,获取表达式

/**
valuable是从valueList获取的其中一组入参,已经赋值好了。
targetMap是yaml配置中target下变量名作为key,其名称对应的值得变量名(reference下名称)作为value。
calculationOrder就是yaml配置中target下变量名。
expMap就是yaml配置中reference下名称作为key,其对应公式作为value。
*/
public void processRes(IValuable valuable,Map<String, String>targetMap,
Set<String> calculationOrder, Map<String,JepExp> expMap) throws Exception {
for(String fieldName : calculationOrder) {
//例如:shuntingSignalLight
if(targetMap.keySet().contains(fieldName)) {
//对应fD_SignalLight
String formulaKey = targetMap.get(fieldName);
//对应公式:(signalType==3)?(DJ==1?(DXJ==1?(LFJ==1?"0x55":"0x99"):"0x67"):"0x84"):""
JepExp jep = expMap.get(formulaKey);
//给公式中变量赋值
jep.addVariables(valuable);
//计算结果

Object result = jep.evaluate();
//设置字段名和结果
valuable.setValue(fieldName, result);
}
}
}

2、jep计算:从valueList获取一组入参值valuable,赋值给公式中需要的变量

/**
* 变量赋值
* @throws Exception
*/
public void addVariables(IValuable valuable) throws Exception
{
//公式包含的所有变量children 
Set<String> children = this.findChildren();
for(String child : children)
{
//jep底层方法,jep.addVariable()
//valuable接口的方法getValue,通过其中的变量child获取其值。
jep.addVariable(child, valuable.getValue(child));
}
}

3、jep计算:接口IValuable

public interface IValuable{
/**
* 通过字段名称获取字段值
* @param fieldName
* @return
* @throws Exception
*/
public Object getValue(String fieldName)throws Exception;
/**
* 设置字段名称和计算结果
* @param fieldName
* @param result
* @throws Exception
*/
public void setValue(String fieldName, Object result)throws Exception;
}

4、jep计算:jep底层方法addVariable()。还有进一步底层方法varTab.addVariable()。

public Variable addVariable(String var1, Object var2) throws JepException {
return this.varTab.addVariable(var1, var2);
}

5、jep计算:计算结果

/**
* 计算结果
* @throws EvaluationException
*/
public Object evaluate() throws EvaluationException
{
result = jep.evaluate();
return result;
}

最后

以上就是眯眯眼心情为你收集整理的jep在java的SpringBoot中的使用jep一、在pom文件中引jep的jar包:的全部内容,希望文章能够帮你解决jep在java的SpringBoot中的使用jep一、在pom文件中引jep的jar包:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(28)

评论列表共有 0 条评论

立即
投稿
返回
顶部