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  阅读(1473)  评论(0编辑  收藏  举报

导航