我们在平常开发的时候,难免会遇到涉及数学公式计算的业务场景。
例如给一个公式,(1+P)*T=?,其中P和T是两个变量,当T=11、P=110时,这个公式计算的结果是多少呢?
下面给出具体实现的工具类,其实现逻辑是在Java里运行JavaScript代码。
直接运行main方法就可以得到结果了,想要换一个公式或者公式里的变量或值,就直接改下红色字体的代码即可。
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.CollectionUtils;
import javax.script.*;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 使用java进行数学公式计算
* @Author: 夏威夷8080
* @Date: 2011/9/27 14:59
*/
@Slf4j
public class ComputeUtil {
/**
* js 关键词 黑名单
*/
private static final Set<String> blacklist = Sets.newHashSet(
// Java 全限定类名
"java.io.File", "java.io.RandomAccessFile", "java.io.FileInputStream", "java.io.FileOutputStream",
"java.lang.Class", "java.lang.ClassLoader", "java.lang.Runtime", "java.lang.System", "System.getProperty",
"java.lang.Thread", "java.lang.ThreadGroup", "java.lang.reflect.AccessibleObject", "java.net.InetAddress",
"java.net.DatagramSocket", "java.net.DatagramSocket", "java.net.Socket", "java.net.ServerSocket",
"java.net.MulticastSocket", "java.net.MulticastSocket", "java.net.URL", "java.net.HttpURLConnection",
"java.security.AccessControlContext", "java.lang.ProcessBuilder",
// JavaScript 方法
"eval","new function");
static Compilable compilable;
static Bindings bindings;
static {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("javascript");
compilable = (Compilable) engine;
// Local级别的Binding
bindings = engine.createBindings();
}
/**
* 设置变量值
* @param key 变量key
* @param value 变量value
*/
public static void putBindings(String key, String value){
bindings.put(key, value);
}
/**
* 清除变量值
*/
public static void clearBindings(){
bindings.clear();
}
/**
* 计算公式
* @param script 示例:(1+0.1 * (F/10) * T)*P
*/
public static Double eval(String script) throws ScriptException {
checkInsecureKeyword(script);
CompiledScript JSFunction = compilable.compile(script);
return Double.valueOf(String.valueOf(JSFunction.eval(bindings)));
}
private static void checkInsecureKeyword(String script) throws ScriptException {
// 去除注释
String removeComment = RegExUtils.replacePattern(script, "(?:/\\*(?:[^*]|(?:\\*+[^*/]))*\\*+/)|(?://.*)", "");
// 多个空格替换为一个
String finalCode = RegExUtils.replacePattern(removeComment, "\\s+", " ");
Set<String> insecure = blacklist.stream().filter(s -> StringUtils.containsIgnoreCase(finalCode, s))
.collect(Collectors.toSet());
if (!CollectionUtils.isEmpty(insecure)) {
throw new ScriptException("解析到js脚本[" + script + "]是不安全的");
}
}
public static void main(String[] args) {
bindings.put("T", 11);
bindings.put("P", 110);
try {
System.out.println(eval("(1+P)*T"));
} catch (ScriptException e) {
e.printStackTrace();
}
}
}
以上就是如何在Java里进行数学公式计算的介绍,希望对你有帮助。