动态计算

应用中可能会遇到一些自定义公式功能, 比如,用户可能自定义输入一些公式 a +b, a%2, '000'+s.substr(0,3), 如果你对这样的需求比较头痛, 请往下看吧, 我们马上解决.

Groovy

groovy是一种基于JVM的敏捷开发语言, 代码能够和java很好的结合, groovy 还可以使用java的类型, 是不是能力超强, 基本上你想到的都可以解决.

如何使用GroovyShell

在使用GroovyShell之前,先Import

import groovy.lang.Binding;

import groovy.lang.GroovyShell;

import groovy.lang.Script;

先看看下面的例子:

GroovyShell shell = new GroovyShell();

Object result = shell.evaluate("(1+5)/2");

System.out.println(result);

这么简单的示例, 相信大家都不会出错, 我们继续深入

绑定参数

实际应用中公式{ (a+b)/2 }是用户定义的, 值是应用系统中的数值, 比如系统中的当前a=1, b=5, 如何将值绑定给公式呢, 一切看代码

Binding binding = new Binding();

binding.setVariable("p",3.1415926);

binding.setVariable("r",5);

GroovyShell shell = new GroovyShell(binding);

Object result = shell.evaluate("p*r*r");

System.out.println(result);

result: 78.539815

引用数学函数

Java中的数学函数很多, 见Math.xxx, 上面的计算结果因为小数位太长, 我们需求四舍五入, 可以直接用Math.round,

Object result = shell.evaluate("Math.round(p*r*r)");

System.out.println(result);

result: 79

这时候的结果可能并不满意, 我们需要保留2位小数, 这时候Math.xxx其实并没有这样的函数直接拿来即用, groovy代码可能是这么写的:

import java.math.RoundingMode

def result = 78.539815

BigDecimal bg = new BigDecimal(result)

bg.setScale(2,RoundingMode.HALF_DOWN).doubleValue()

要是能够将上面的代码写成一个function, 直接调用那就简单多了...

自定义函数

自定义函数, 这个其实可以的, 我们先创建一个Java Class

public class EvalBaseScript extends Script {

@Override

public Object run() {

Method[] methods = EvalBaseScript.class.getDeclaredMethods();

StringBuilder sb=new StringBuilder();

for (Method method : methods) {

sb.append(method);

}

return sb.substring(0, sb.length()-1);

}

public static double round(String value, int scale) {

BigDecimal bd = new BigDecimal(value);

return bd.setScale(scale, 4).doubleValue();

}

public static double round(double value, int scale) {

BigDecimal bd = new BigDecimal(value);

return bd.setScale(scale, 4).doubleValue();

}

下面我们看看groovy中如何使用上面的class

Binding binding = new Binding();

if(vars!=null) {

vars.keySet().forEach(name ->

binding.setVariable(name, vars.get(name))

);

}

CompilerConfiguration cfg = new CompilerConfiguration();

cfg.setScriptBaseClass(EvalBaseScript.class.getName());

GroovyShell shell = new GroovyShell(binding,cfg);

try {

Script script = shell.parse(buildScript());

return script.run();

} catch (Exception ex) {

logger.error("catch script execution error, script:"+buildScript(), ex);

return 0;

}

至此java中执行自定义script的能力已经足够了, 你可以定义出你想要的, 任何脚本.

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐