Google AviatorEvaluator 轻量级Java表达式引擎 (小写字符转大写) 内置函数

897 阅读14分钟

Aviator 一个高性能、轻量级的java语言实现的表达式求值引擎,主要用于各种表达式的动态求值

问题 :已经有很多开源可用的java表达式求值引擎,为什么还需要Avaitor呢?

答案: Aviator:高性能、轻量级、相比其他表达式引擎,Actor 非常小,总共含依赖500k以下。

Aviator则是直接将表达式编译成Java字节码,Aviator的定位是介于Groovy这样的重量级脚本语言和IKExpression这样的轻量级表达式引擎之间。

示例: 小写字符转大写



//注册规则引擎中Aviator的自定义函数
AviatorEvaluator.addFunction(new UpperCaseFunction());



public class UpperCaseFunction extends AbstractFunction {

    @Override
    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
        String right = FunctionUtils.getStringValue(arg1, env);
        right = right.toUpperCase();
        return new AviatorString(right);
    }

    public String getName() {
        return "upperCase";
    }
}



public static void main(String[] args) {

AviatorEvaluator.addFunction(new UpperCaseFunction());
System.out.println(AviatorEvaluator.execute("upperCase("abcd")"));     

}
 

自定义 函数,继承抽象类AbstractFunction

实现方法:即可落地

  • getName() 返回 函数对应的调用名称,必须实现方法 :->函数名

  • call() 方法可以重载,尾部参数可选,对应函数入参多个参数分别调用使用->重载函数实现

源码分析

定义抽象类 AbstractFunction



package com.googlecode.aviator.runtime.function;

import com.googlecode.aviator.runtime.type.AviatorFunction;
import com.googlecode.aviator.runtime.type.AviatorObject;
import java.util.Map;

public abstract class AbstractFunction implements AviatorFunction {
    public AbstractFunction() {
    }

    public AviatorObject throwArity(int n) {
        String name = this.getName();
        throw new IllegalArgumentException("Wrong number of args (" + n + ") passed to: " + name);
    }

    public AviatorObject call(Map<String, Object> env) {
        return this.throwArity(0);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1) {
        return this.throwArity(1);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2) {
        return this.throwArity(2);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3) {
        return this.throwArity(3);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4) {
        return this.throwArity(4);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5) {
        return this.throwArity(5);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6) {
        return this.throwArity(6);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7) {
        return this.throwArity(7);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8) {
        return this.throwArity(8);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9) {
        return this.throwArity(9);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10) {
        return this.throwArity(10);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11) {
        return this.throwArity(11);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12) {
        return this.throwArity(12);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13) {
        return this.throwArity(13);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14) {
        return this.throwArity(14);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15) {
        return this.throwArity(15);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16) {
        return this.throwArity(16);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17) {
        return this.throwArity(17);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18) {
        return this.throwArity(18);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18, AviatorObject arg19) {
        return this.throwArity(19);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18, AviatorObject arg19, AviatorObject arg20) {
        return this.throwArity(20);
    }

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3, AviatorObject arg4, AviatorObject arg5, AviatorObject arg6, AviatorObject arg7, AviatorObject arg8, AviatorObject arg9, AviatorObject arg10, AviatorObject arg11, AviatorObject arg12, AviatorObject arg13, AviatorObject arg14, AviatorObject arg15, AviatorObject arg16, AviatorObject arg17, AviatorObject arg18, AviatorObject arg19, AviatorObject arg20, AviatorObject... args) {
        return this.throwArity(21);
    }
}



定义接口 AviatorFunction


public interface AviatorFunction {
    String getName();

    AviatorObject call(Map<String, Object> var1);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16, AviatorObject var17);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16, AviatorObject var17, AviatorObject var18);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16, AviatorObject var17, AviatorObject var18, AviatorObject var19);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16, AviatorObject var17, AviatorObject var18, AviatorObject var19, AviatorObject var20);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16, AviatorObject var17, AviatorObject var18, AviatorObject var19, AviatorObject var20, AviatorObject var21);

    AviatorObject call(Map<String, Object> var1, AviatorObject var2, AviatorObject var3, AviatorObject var4, AviatorObject var5, AviatorObject var6, AviatorObject var7, AviatorObject var8, AviatorObject var9, AviatorObject var10, AviatorObject var11, AviatorObject var12, AviatorObject var13, AviatorObject var14, AviatorObject var15, AviatorObject var16, AviatorObject var17, AviatorObject var18, AviatorObject var19, AviatorObject var20, AviatorObject var21, AviatorObject... var22);
}

image.png

注册函数 AviatorEvaluator:AviatorEvaluator.addFunction(new UpperCaseFunction());

public class AviatorClassLoader extends ClassLoader {

    public AviatorClassLoader(ClassLoader parent) {
        super(parent);
    }
    public Class<?> defineClass(String name, byte[] b) {
        return defineClass(name, b, 0, b.length);
    }
}





/**
 * Avaitor Expression evaluator
 * 
 * @author dennis
 * 
 */
public final class AviatorEvaluator {

    // The classloader to define generated class 定义生成类的类加载器

    @Deprecated
    private static AviatorClassLoader aviatorClassLoader;

    /**
     * Optimized for compile speed  优化编译速度
     */
    public static final int COMPILE = 0;

    /**
     * Optimized for execute speed,this is the default option 
     针对 执行器执行速度做了优化,这个是默认选型
     */
    public static final int EVAL = 1;



    private static OutputStream traceOutputStream = System.out;

    private static final ConcurrentHashMap<Options, Object> options = new ConcurrentHashMap<Options, Object>();


    /**
     * Add a aviator function,it's not thread-safe.
     添加一个函数,它不是线程安全的
     * 
     * @param function
     */
    public static void addFunction(AviatorFunction function) {
        final String name = function.getName();
        if (FUNC_MAP.containsKey(name)) {
            System.out.println("[Aviator WARN] The function '" + name + "' is already exists, but you replace it.");
        }
        FUNC_MAP.put(name, function);
    }


    /**
     * Remove a aviator function by name,it's not thread-safe.
     * 跟进函数名称移除一个函数,非线程安全
     * @param name
     * @return
     */
    public static AviatorFunction removeFunction(String name) {
        return (AviatorFunction) FUNC_MAP.remove(name);
    }



    public final static Map<String, Object> FUNC_MAP = new HashMap<String, Object>();

    static {
        // Load internal functions
        // load sys lib
        addFunction(new SysDateFunction());
        addFunction(new PrintlnFunction());
        addFunction(new PrintFunction());
        addFunction(new RandomFunction());
        addFunction(new NowFunction());
        addFunction(new LongFunction());
        addFunction(new DoubleFunction());
        addFunction(new StrFunction());
        addFunction(new Date2StringFunction());
        addFunction(new String2DateFunction());
        addFunction(new BinaryFunction(OperatorType.ADD));
        addFunction(new BinaryFunction(OperatorType.SUB));
        addFunction(new BinaryFunction(OperatorType.MULT));
        addFunction(new BinaryFunction(OperatorType.DIV));
        addFunction(new BinaryFunction(OperatorType.MOD));
        addFunction(new BinaryFunction(OperatorType.NEG));
        addFunction(new BinaryFunction(OperatorType.NOT));

        // load string lib
        addFunction(new StringContainsFunction());
        addFunction(new StringIndexOfFunction());
        addFunction(new StringStartsWithFunction());
        addFunction(new StringEndsWithFunction());
        addFunction(new StringSubStringFunction());
        addFunction(new StringLengthFunction());
        addFunction(new StringSplitFunction());
        addFunction(new StringJoinFunction());
        addFunction(new StringReplaceFirstFunction());
        addFunction(new StringReplaceAllFunction());

        // load math lib
        addFunction(new MathAbsFunction());
        addFunction(new MathRoundFunction());
        addFunction(new MathPowFunction());
        addFunction(new MathSqrtFunction());
        addFunction(new MathLog10Function());
        addFunction(new MathLogFunction());
        addFunction(new MathSinFunction());
        addFunction(new MathCosFunction());
        addFunction(new MathTanFunction());

        // seq lib
        addFunction(new SeqMapFunction());
        addFunction(new SeqReduceFunction());
        addFunction(new SeqFilterFunction());
        addFunction(new SeqSortFunction());
        addFunction(new SeqIncludeFunction());
        addFunction(new SeqCountFunction());
        addFunction(new SeqMakePredicateFunFunction("seq.eq", OperatorType.EQ));
        addFunction(new SeqMakePredicateFunFunction("seq.neq", OperatorType.NEQ));
        addFunction(new SeqMakePredicateFunFunction("seq.lt", OperatorType.LT));
        addFunction(new SeqMakePredicateFunFunction("seq.le", OperatorType.LE));
        addFunction(new SeqMakePredicateFunFunction("seq.gt", OperatorType.GT));
        addFunction(new SeqMakePredicateFunFunction("seq.ge", OperatorType.GE));
        addFunction(new SeqMakePredicateFunFunction("seq.true", OperatorType.EQ, AviatorBoolean.TRUE));
        addFunction(new SeqMakePredicateFunFunction("seq.false", OperatorType.EQ, AviatorBoolean.FALSE));
        addFunction(new SeqMakePredicateFunFunction("seq.nil", OperatorType.EQ, AviatorNil.NIL));
        addFunction(new SeqMakePredicateFunFunction("seq.exists", OperatorType.NEQ, AviatorNil.NIL));
        // load custom functions.
        CustomFunctionLoader.load();
    }


    /**
     * Adds a evaluator option
     * 
     */
    public static void setOption(Options opt, Object val) {
        if (opt == null || val == null) {
            throw new IllegalArgumentException("Option and value should not be null.");
        }
        if (!opt.isValidValue(val)) {
            throw new IllegalArgumentException("Invalid value for option:" + opt.name());
        }
        options.put(opt, val);
    }


    /**
     * Returns the current evaluator option value, returns null if missing.
     * 
     * @param opt
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T getOption(Options opt) {
        Object val = options.get(opt);
        if (val == null) {
            val = opt.getDefaultValue();
        }
        return (T) val;
    }


    /**
     * Get current trace output stream,default is System.out
     * 
     * @return
     */
    public static OutputStream getTraceOutputStream() {
        return traceOutputStream;
    }


    /**
     * Returns current math context for decimal.
     * 
     * @since 2.3.0
     * @deprecated Please use {@link #getOption(Options)}
     * @return
     */
    public static MathContext getMathContext() {
        return getOption(Options.MATH_CONTEXT);
    }


    /**
     * Set math context for decimal.
     * 
     * @param mathContext
     * @deprecated please use {@link #setOption(Options, Object)}
     * @since 2.3.0
     */
    public static void setMathContext(MathContext mathContext) {
        if (mathContext == null) {
            throw new IllegalArgumentException("null mathContext");
        }
        setOption(Options.MATH_CONTEXT, mathContext);
    }


    /**
     * Set trace output stream
     * 
     * @param traceOutputStream
     */
    public static void setTraceOutputStream(OutputStream traceOutputStream) {
        AviatorEvaluator.traceOutputStream = traceOutputStream;
    }

    static {
        aviatorClassLoader = AccessController.doPrivileged(new PrivilegedAction<AviatorClassLoader>() {

            @Override
            public AviatorClassLoader run() {
                return new AviatorClassLoader(AviatorEvaluator.class.getClassLoader());
            }

        });
    }


  

    private AviatorEvaluator() {

    }


    /**
     * Clear all cached compiled expression
     */
    public static void clearExpressionCache() {
        cacheExpressions.clear();
    }


    /**
     * Returns classloader
     * 
     * @return
     */
    public static AviatorClassLoader getAviatorClassLoader() {
        return getAviatorClassLoader(false);
    }


    /**
     * Returns classloader
     * 
     * @return
     */
    public static AviatorClassLoader getAviatorClassLoader(boolean cached) {
        if (cached)
            return aviatorClassLoader;
        else
            return new AviatorClassLoader(Thread.currentThread().getContextClassLoader());
    }




    /**
     * get a aviator function by name,throw exception if null
     * 
     * @param name
     * @return
     */
    public static AviatorFunction getFunction(String name) {
        final AviatorFunction function = (AviatorFunction) FUNC_MAP.get(name);
        if (function == null) {
            throw new ExpressionRuntimeException("Could not find function named '" + name + "'");
        }
        return function;
    }


    /**
     * Check if the function is existed in aviator
     * 
     * @param name
     * @return
     */
    public static boolean containsFunction(String name) {
        return FUNC_MAP.containsKey(name);
    }


    /**
     * Remove a aviator function
     * 
     * @param function
     * @return
     */
    public static AviatorFunction removeFunction(AviatorFunction function) {
        return removeFunction(function.getName());
    }


    /**
     * Configure user defined classloader
     * 
     * @deprecated
     * @param aviatorClassLoader
     */
    public static void setAviatorClassLoader(AviatorClassLoader aviatorClassLoader) {
        // AviatorEvaluator.aviatorClassLoader = aviatorClassLoader;
    }


    /**
     * Returns a compiled expression in cache
     * 
     * @param expression
     * @return
     */
    public static Expression getCachedExpression(String expression) {
        FutureTask<Expression> task = cacheExpressions.get(expression);
        if (task != null) {
            return getCompiledExpression(expression, task);
        }
        else {
            return null;
        }
    }


    /**
     * Compile a text expression to Expression object
     将文本表达式编译为表达式对象
     * 
     * @param expression
     *            text expression
     * @param cached
     *            Whether to cache the compiled result,make true to cache it.
     是否缓存编译结果, true 则缓存编译对象
     * @return
     */
    public static Expression compile(final String expression, final boolean cached) {
        if (expression == null || expression.trim().length() == 0) {
            throw new CompileExpressionErrorException("Blank expression");
        }

        if (cached) {
            FutureTask<Expression> task = cacheExpressions.get(expression);
            if (task != null) {
                return getCompiledExpression(expression, task);
            }
            task = new FutureTask<Expression>(new Callable<Expression>() {
                @Override
                public Expression call() throws Exception {
                    return innerCompile(expression, cached);
                }

            });
            FutureTask<Expression> existedTask = cacheExpressions.putIfAbsent(expression, task);
            if (existedTask == null) {
                existedTask = task;
                existedTask.run();
            }
            return getCompiledExpression(expression, existedTask);

        }
        else {
            return innerCompile(expression, cached);
        }

    }


    private static Expression getCompiledExpression(final String expression, FutureTask<Expression> task) {
        try {
            return task.get();
        }
        catch (Exception e) {
            cacheExpressions.remove(expression);
            throw new CompileExpressionErrorException("Compile expression failure:" + expression, e);
        }
    }


    private static Expression innerCompile(final String expression, boolean cached) {
        ExpressionLexer lexer = new ExpressionLexer(expression);
        CodeGenerator codeGenerator = newCodeGenerator(cached);
        ExpressionParser parser = new ExpressionParser(lexer, codeGenerator);
        return parser.parse();
    }


    private static int getOptimizeLevel() {
        return getOption(Options.OPTIMIZE_LEVEL);
    }


    private static CodeGenerator newCodeGenerator(boolean cached) {
        switch (getOptimizeLevel()) {
        case COMPILE:
            ASMCodeGenerator asmCodeGenerator =
                    new ASMCodeGenerator(getAviatorClassLoader(cached), traceOutputStream,
                        (Boolean) getOption(Options.TRACE));
            asmCodeGenerator.start();
            return asmCodeGenerator;
        case EVAL:
            return new OptimizeCodeGenerator(getAviatorClassLoader(cached), traceOutputStream,
                (Boolean) getOption(Options.TRACE));
        default:
            throw new IllegalArgumentException("Unknow option " + getOptimizeLevel());
        }

    }


    /**
     * Compile a text expression to Expression Object without caching
     * 
     * @param expression
     * @return
     */
    public static Expression compile(String expression) {
        return compile(expression, false);
    }


    /**
     * Execute a text expression with values that are variables order in the
     * expression.It only runs in EVAL mode,and it will cache the compiled
     * expression.
     * 
     * @param expression
     * @param values
     * @return
     */
    public static Object exec(String expression, Object... values) {
        if (getOptimizeLevel() != EVAL) {
            throw new IllegalStateException("Aviator evaluator is not in EVAL mode.");
        }
        Expression compiledExpression = compile(expression, true);
        if (compiledExpression != null) {
            List<String> vars = compiledExpression.getVariableNames();
            if (!vars.isEmpty()) {
                int valLen = values == null ? 0 : values.length;
                if (valLen != vars.size()) {
                    throw new IllegalArgumentException("Expect " + vars.size() + " values,but has " + valLen);
                }
                Map<String, Object> env = new HashMap<String, Object>();
                int i = 0;
                for (String var : vars) {
                    env.put(var, values[i++]);
                }
                return compiledExpression.execute(env);
            }
            else {
                return compiledExpression.execute();
            }
        }
        else {
            throw new ExpressionRuntimeException("Null compiled expression for " + expression);
        }
    }


    /**
     * Execute a text expression with environment
     * 
     * @param expression
     *            text expression
     * @param env
     *            Binding variable environment
     * @param cached
     *            Whether to cache the compiled result,make true to cache it.
     */
    public static Object execute(String expression, Map<String, Object> env, boolean cached) {
        Expression compiledExpression = compile(expression, cached);
        if (compiledExpression != null) {
            return compiledExpression.execute(env);
        }
        else {
            throw new ExpressionRuntimeException("Null compiled expression for " + expression);
        }
    }


    /**
     * Execute a text expression without caching
     * 
     * @param expression
     * @param env
     * @return
     */
    public static Object execute(String expression, Map<String, Object> env) {
        return execute(expression, env, false);
    }


    /**
     * Invalidate expression cache
     * 
     * @param expression
     */
    public static void invalidateCache(String expression) {
        cacheExpressions.remove(expression);
    }


    /**
     * Execute a text expression without caching and env map.
     * 
     * @param expression
     * @return
     */
    public static Object execute(String expression) {
        return execute(expression, (Map<String, Object>) null);
    }
}

性能对比

image.png

Drools (Jboss Rules) 开源业务规则引擎。

Easy Rules是一个简单而强大的Java规则引擎,提供以下功能:

  • 轻量级框架和易于学习的API

  • 基于POJO的开发与注解的编程模型

  • 定义抽象的业务规则并轻松应用它们

  • 支持从简单规则创建组合规则的能力

  • 支持使用表达式语言(如MVEL和SpEL)定义规则的能力

IKExpression 开源、可扩展,基于java 语言开发的轻量级的公式化语言解析工具

Groovy经常被认为是脚本语言, Groovy 与 Java 平台非常融合,包括大量的java类库也可以直接在groovy中使用 表达式

Binding binding = new Binding();
binding.setVariable("verifyStatus", 1); 
GroovyShell shell = new GroovyShell(binding); 
boolean result = (boolean) shell.evaluate("verifyStatus == 1");
Assert.assertTrue(result);

 

内置函数

 

函数名称说明
sysdate()返回当前日期对象 java.util.Date
rand()返回一个介于 0-1 的随机数,double 类型
print([out],obj)打印对象,如果指定 out,向 out 打印, 否则输出到控制台
println([out],obj)与 print 类似,但是在输出后换行
now()返回 System.currentTimeMillis
long(v)将值的类型转为 long
double(v)将值的类型转为 double
str(v)将值的类型转为 string
date_to_string(date,format)将 Date 对象转化化特定格式的字符串,2.1.1 新增
string_to_date(source,format)将特定格式的字符串转化为 Date 对 象,2.1.1 新增
string.contains(s1,s2)判断 s1 是否包含 s2,返回 Boolean
string.length(s)求字符串长度,返回 Long
string.startsWith(s1,s2)s1 是否以 s2 开始,返回 Boolean
string.endsWith(s1,s2)s1 是否以 s2 结尾,返回 Boolean
string.substring(s,begin[,end])截取字符串 s,从 begin 到 end,如果忽略 end 的话,将从 begin 到结尾,与 java.util.String.substring 一样。
string.indexOf(s1,s2)java 中的 s1.indexOf(s2),求 s2 在 s1 中 的起始索引位置,如果不存在为-1
string.split(target,regex,[limit])Java 里的 String.split 方法一致,2.1.1 新增函数
string.join(seq,seperator)将集合 seq 里的元素以 seperator 为间隔 连接起来形成字符串,2.1.1 新增函数
string.replace_first(s,regex,replacement)Java 里的 String.replaceFirst 方法, 2.1.1 新增
string.replace_all(s,regex,replacement)Java 里的 String.replaceAll 方法 , 2.1.1 新增
math.abs(d)求 d 的绝对值
math.sqrt(d)求 d 的平方根
math.pow(d1,d2)求 d1 的 d2 次方
math.log(d)求 d 的自然对数
math.log10(d)求 d 以 10 为底的对数
math.sin(d)正弦函数
math.cos(d)余弦函数
math.tan(d)正切函数
map(seq,fun)将函数 fun 作用到集合 seq 每个元素上, 返回新元素组成的集合
filter(seq,predicate)将谓词 predicate 作用在集合的每个元素 上,返回谓词为 true 的元素组成的集合
count(seq)返回集合大小
include(seq,element)判断 element 是否在集合 seq 中,返回 boolean 值
sort(seq)排序集合,仅对数组和 List 有效,返回排 序后的新集合
reduce(seq,fun,init)fun 接收两个参数,第一个是集合元素, 第二个是累积的函数,本函数用于将 fun 作用在集合每个元素和初始值上面,返回 最终的 init 值
seq.eq(value)返回一个谓词,用来判断传入的参数是否跟 value 相等,用于 filter 函数,如filter(seq,seq.eq(3)) 过滤返回等于3 的元素组成的集合
seq.neq(value)与 seq.eq 类似,返回判断不等于的谓词
seq.gt(value)返回判断大于 value 的谓词
seq.ge(value)返回判断大于等于 value 的谓词
seq.lt(value)返回判断小于 value 的谓词
seq.le(value)返回判断小于等于 value 的谓词
seq.nil()返回判断是否为 nil 的谓词
seq.exists()返回判断不为 nil 的谓词