fel基本使用
fel 我猜 是 function expression language 的缩写,函数表达式语言
使用:引入maven依赖(据说有0.9支持大整数 但是 maven 仓库没有 )
<!-- fel --> <dependency> <groupId>org.eweb4j</groupId> <artifactId>fel</artifactId> <version>0.8</version> </dependency>
测试和使用说明:
package com.lomi.fel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import com.alibaba.fastjson.JSONObject;
import com.greenpineyu.fel.Expression;
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.common.ObjectUtils;
import com.greenpineyu.fel.context.AbstractContext;
import com.greenpineyu.fel.context.ContextChain;
import com.greenpineyu.fel.context.FelContext;
import com.greenpineyu.fel.context.MapContext;
import com.greenpineyu.fel.function.CommonFunction;
import com.greenpineyu.fel.function.Function;
import com.greenpineyu.fel.parser.FelNode;
import com.lomi.entity.Goods;
public class FelTest {
/**
* 使用常量
*/
@Test
public void test0() {
FelEngine felEngine = new FelEngineImpl();
Object result = felEngine.eval("2*3");
System.out.println(result);
}
/**
* 使用变量
*/
@Test
public void test2() {
FelEngine felEngine = new FelEngineImpl();
FelContext ctx = felEngine.getContext();
ctx.set("count", 10);
ctx.set("price", 100);
Object result = felEngine.eval("count*price");
System.out.println(result);
}
/**
* 使用变量的方法和属性
*/
@Test
public void test3() {
FelEngine felEngine = new FelEngineImpl();
FelContext ctx = felEngine.getContext();
Goods good = Goods.randomGoods();
ctx.set("good", good);
Map<String, String> map = new HashMap<String, String>();
map.put("key1", "value1");
ctx.set("map", map);
//取不存在的方法属性,返回null
Object result = felEngine.eval("good.size");
System.out.println("result:" + result);
//调用good的toString
result = felEngine.eval("good.toString");
System.out.println("result:" + result);
//获取name(分别调用 name() 方法 和 getName() 方法,name(优先) ,不会取直接获取私有字段)
result = felEngine.eval("good.name");
System.out.println("result:" + result);
//调用有参方法 name(int i)
result = felEngine.eval("good.name(1)");
System.out.println("result:" + result);
//获取 map 的 value
result = felEngine.eval("map.key1");
System.out.println("result:" + result);
}
/**
* 使用集合,直接用下标获取 集合元素
*/
@Test
public void test4() {
FelEngine felEngine = new FelEngineImpl();
FelContext ctx = felEngine.getContext();
// 数组
int[] intArray = { 1, 2, 3 };
ctx.set("intArray", intArray);
String exp = "intArray[0]";
System.out.println(exp + "->" + felEngine.eval(exp));
// List
List<Integer> list = Arrays.asList(1, 2, 3);
ctx.set("list", list);
exp = "list[0]";
System.out.println(exp + "->" + felEngine.eval(exp));
// 集合
Collection<String> coll = Arrays.asList("a", "b", "c");
ctx.set("coll", coll);
// 获取集合最前面的元素。执行结果为"a"
exp = "coll[0]";
System.out.println(exp + "->" + felEngine.eval(exp));
// 迭代器
Iterator<String> iterator = coll.iterator();
ctx.set("iterator", iterator);
// 获取迭代器最前面的元素。执行结果为"a"
exp = "iterator[0]";
System.out.println(exp + "->" + felEngine.eval(exp));
//Map
Map<String, String> m = new HashMap<String, String>();
m.put("name", "HashMap");
ctx.set("map", m);
exp = "map.name";
System.out.println(exp + "->" + felEngine.eval(exp));
// 多维数组
int[][] intArrays = { { 11, 12 }, { 21, 22 } };
ctx.set("intArrays", intArrays);
exp = "intArrays[0][0]";
System.out.println(exp + "->" + felEngine.eval(exp));
// 多维综合体,支持数组、集合的任意组合。
List<int[]> listArray = new ArrayList<int[]>();
listArray.add(new int[] { 1, 2, 3 });
listArray.add(new int[] { 4, 5, 6 });
ctx.set("listArray", listArray);
exp = "listArray[0][0]";
System.out.println(exp + "->" + felEngine.eval(exp));
}
/**
* 使用类的静态方法和new
*/
@Test
public void test5() {
FelEngine fel = new FelEngineImpl();
FelContext ctx = fel.getContext();
ctx.set("json", JSONObject.class);
ctx.set("goods", Goods.randomGoods());
System.out.println(fel.eval("json.toJSONString( goods )"));
// 调用Math.min(1,2),java.lang包下面的都可简写
System.out.println(FelEngine.instance.eval("$('Math').min(1,2)"));
// 调用new Goods().randomGoods();
System.out.println(FelEngine.instance.eval("$('com.lomi.entity.Goods.new').randomGoods()"));
//感觉这玩意可以用链式编程动态编程(如果不考虑效率的话)
ctx.set("name1", "张三");
System.out.println(FelEngine.instance.eval("$('com.lomi.entity.Goods.new').setName(name1)",ctx));
}
/**
* 使用上下文的参数
*/
@Test
public void test6() {
// 负责提供气象服务的上下文环境
FelContext ctx = new AbstractContext() {
public Object get(String name) {
if ("天气".equals(name)) {
return "晴";
}
if ("温度".equals(name)) {
return 25;
}
return null;
}
};
FelEngine felEngine = new FelEngineImpl(ctx);
Object eval = felEngine.eval("'天气:'+天气+';温度:'+温度");
System.out.println(eval);
}
/**
* 多层上下文(有继承关系,新的覆盖老的重复值)
*/
@Test
public void test7() {
FelEngine felEngine = new FelEngineImpl();
FelContext ctx1 = felEngine.getContext();
ctx1.set("a", 10);
ctx1.set("b", 100);
FelContext ctx2 = new ContextChain(ctx1, new MapContext());
ctx2.set("a", 20);
String exp = "b" + "-" + "a";
//使用上下文2
Object rt2 = felEngine.eval(exp, ctx2);
System.out.println("b-a=" + rt2);
//使用上下文1
Object rt = felEngine.eval(exp);
System.out.println("b-a=" + rt);
}
/**
* 编译以后在执行效率会高很多(先编译后执行,前提是公式固定)
*/
@Test
public void test8() {
FelEngine fel = new FelEngineImpl();
FelContext ctx = fel.getContext();
ctx.set("单价", 5000);
ctx.set("数量", 12);
ctx.set("运费", 7500);
Expression exp = fel.compile("单价*数量+运费", ctx);
Object result = exp.eval(ctx);
System.out.println(result);
}
/**
* 大值(不知道哪里有0.9的版本)
*/
@Test
public void test9() {
/*
* FelEngine fel = FelBuilder.bigNumberEngine(); String input =
* "111111111111111111111111111111+22222222222222222222222222222222"; Object
* value = fel.eval(input); Object compileValue = fel.compile(input,
* fel.getContext()).eval(fel.getContext()); System.out.println("大数值计算(解释执行):" +
* value); System.out.println("大数值计算(编译执行):" + compileValue);
*/
}
/**
* 子定义函数
*/
@Test
public void test11() {
Function fun = new CommonFunction() {
public String getName() {
return "hello";
}
@Override
public Object call(Object[] arguments) {
Object msg = null;
if(arguments!= null && arguments.length>0){
msg = arguments[0];
}
System.out.println( msg );
return "say:" + ObjectUtils.toString(msg);
}
};
Function addFun = new CommonFunction() {
public String getName() {
return "add";
}
@Override
public Object call(Object[] arguments) {
if(arguments== null || arguments.length != 2){
throw new RuntimeException("参数异常");
}
int a = (int)arguments[0];
int b = (int)arguments[1];
return a+b;
}
};
FelEngine felEngine = new FelEngineImpl();
//添加函数到引擎中。
felEngine.addFun(fun);
felEngine.addFun(addFun);
String exp = "hello('你好')";
//解释执行
Object eval = felEngine.eval(exp);
System.out.println("hello "+eval);
//编译执行(编译的过程会直接执行一边,如果这时候 修改了 上下文的变量,就要注意了)
Expression compile = felEngine.compile(exp, null);
eval = compile.eval(null);
System.out.println("hello "+eval);
//函数里面可以套函数( CommonFunction.call.(Object[] arguments) 方法里面拿到的都是已经吧内嵌函数计算好了,详情见父类的 CommonFunction.call(FelNode node, FelContext context) )
System.out.println( felEngine.eval("hello( add(3,2) )") );
}
/**
* 效率比较,正常简单相加20亿次,5秒
*/
@Test
public void test12() {
Long start = System.currentTimeMillis();
Integer a = 0;
Add add = new Add();
for(int i = 0;i<2000000000;i++) {
a= (Integer) add.call( new Integer[] {a,1} );
}
Long end = System.currentTimeMillis();
System.out.println( a );
System.out.println( end-start );
}
/**
* 解释执行也就差5000 倍,10W次6 秒。
*/
@Test
public void test13() {
Long start = System.currentTimeMillis();
FelEngine felEngine = new FelEngineImpl();
felEngine.addFun( new Add() );
Integer a = 0;
for(int i = 0;i<1000000;i++) {
a = (Integer) felEngine.eval("add("+ a +",1)");
}
Long end = System.currentTimeMillis();
System.out.println( a );
System.out.println( end-start );
}
/**
* 解释执行也就差10多20 倍,2亿次9 秒
*/
@Test
public void test14() {
Long start = System.currentTimeMillis();
FelEngine felEngine = new FelEngineImpl();
felEngine.addFun( new Add2() );
Object a = 0;
FelContext felContext = felEngine.getContext();
felContext.set("a", 0 );
//不知道为啥编译会把int类型改成double。
Expression expression = felEngine.compile("add(a,1)",felContext);
for(int i = 0;i<200000000;i++) {
a = expression.eval(felContext);
}
Long end = System.currentTimeMillis();
System.out.println( a );
System.out.println( end-start );
}
/**
* 覆盖 com.greenpineyu.fel.function.operator 下面的 +,-,*,/,=,等可以从定义这些符号,比如让 1==2 返回true
*/
@Test
public void testEqual() {
FelEngine felEngine = new FelEngineImpl();
Object evalRt = felEngine.eval("1==2");
System.out.println( evalRt );
}
class Add extends CommonFunction{
@Override
public String getName() {
return "add";
}
@Override
public Object call(Object[] arguments) {
return (Integer)arguments[0] + (Integer)arguments[1];
}
}
class Add2 extends CommonFunction{
FelContext context;
public Object call(FelNode node, FelContext context) {
Object[] children = evalArgs(node, context);
this.context = context;
return call(children);
}
@Override
public String getName() {
return "add";
}
@Override
public Integer call(Object[] arguments) {
Integer a = (Integer)arguments[0] + (Integer)arguments[1];
context.set("a", a);
return a;
}
}
}
附Goods类:
package com.lomi.entity;
import com.lomi.utils.CodeUtil;
import cn.hutool.core.util.IdUtil;
public class Goods {
private Long id;
private String name;
private Integer stock;
private String des;
private String data;
public Goods( String name ) {
this.name = name;
}
public Goods() {}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public String name(int i) {
return "name方法" + i;
}
public Goods setName(String name) {
this.name = name == null ? null : name.trim();
return this;
}
public Integer getStock() {
return stock;
}
public void setStock(Integer stock) {
this.stock = stock;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des == null ? null : des.trim();
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data == null ? null : data.trim();
}
@Override
public String toString() {
return "Goods [id=" + id + ", name=" + name + ", stock=" + stock + ", des=" + des + ", data=" + data + "]";
}
public static Goods randomGoods() {
Goods goods = new Goods();
goods.setId(IdUtil.getSnowflakeNextId());
goods.setData( CodeUtil.getRandomNum18() );
goods.setDes( CodeUtil.randomCode(6) );
goods.setName( CodeUtil.randomCode(3) );
goods.setStock( Integer.valueOf( CodeUtil.randomNumCode(4) ) );
return goods;
}
public static void main(String[] args) {
System.out.println( Long.MAX_VALUE );
}
}
例子地址代码:https://github.com/hualiuwuxin/TestExample.git

能耍的时候就一定要耍,不能耍的时候一定要学。
--天道酬勤,贵在坚持posted on 2022-03-30 16:22 zhangyukun 阅读(2445) 评论(0) 收藏 举报
浙公网安备 33010602011771号