今天在公司項目中,發現一個計算運費的妙招。由於運費規則各種各樣,因此寫一個公式存到數據庫。下次需要計算運費時,直接取出這個公式,把公式的未知變量給替換掉,然后計算出結果就是ok了。
一、先看幾張圖
(1)數據庫存的公式
(2)怎么在java代碼中計算出結果,見下面2張圖
這圖,是在map集合中存了 key為"\\$w" value為重量的參數。關鍵是下面這圖
這圖中方法接收參數為 (公式,公式中變量的真實內容的Map集合)
比較巧妙的地方是,它把這個公式
字符串
變成js形式的變量運算字符串;然后執行js腳本,這樣就把結果算出來了。
就相當於在java中,把"1+2" 這個字符串給算出結果來了。而且它這里還巧妙的使用了js的Math的一些方法。
二、來寫個demo
寫個方法,實現傳入公式和參數,計算出結果。直接上代碼吧
package com.zxy.test;
import java.util.HashMap;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.junit.Test;
/**
* 如何將一個字符串公式,計算出結果
* @author ZENG.XIAO.YAN
* @date Oct 26, 2017 7:34:08 PM
* @version V1.0
*/
public class RunJsOnJava {
@Test
public void test01() throws ScriptException {
String formula = "(a+b)*(a-b)";
HashMap<String,Object> map = new HashMap<String,Object>();
map.put("a", 20.1);
map.put("b", 11.1);
Double result = (Double) this.calculateResultByFormula(formula, map);
System.out.println(result); //280.80000000000007
}
/**
* 通過字符串公式,和參數,計算出結果
* @param formula
* @param paramMap
* @return
* @throws ScriptException
*/
public Object calculateResultByFormula (String formula,Map<String,Object> paramMap) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine scriptEngine = manager.getEngineByName("js");
for (String key : paramMap.keySet()) {
formula = formula.replaceAll(key, paramMap.get(key).toString());
}
//此時 formula="(20.1+11.1)*(20.1-11.1)"
Object result = scriptEngine.eval(formula); // 運行js腳本
return result;
}
}
x
1
package com.zxy.test;
2
import java.util.HashMap;
3
import java.util.Map;
4
import javax.script.ScriptEngine;
5
import javax.script.ScriptEngineManager;
6
import javax.script.ScriptException;
7
import org.junit.Test;
8
9
/**
10
* 如何將一個字符串公式,計算出結果
11
* @author ZENG.XIAO.YAN
12
* @date Oct 26, 2017 7:34:08 PM
13
* @version V1.0
14
*/
15
16
public class RunJsOnJava {
17
18
@Test
19
public void test01() throws ScriptException {
20
String formula = "(a+b)*(a-b)";
21
HashMap<String,Object> map = new HashMap<String,Object>();
22
map.put("a", 20.1);
23
map.put("b", 11.1);
24
Double result = (Double) this.calculateResultByFormula(formula, map);
25
System.out.println(result); //280.80000000000007
26
}
27
28
/**
29
* 通過字符串公式,和參數,計算出結果
30
* @param formula
31
* @param paramMap
32
* @return
33
* @throws ScriptException
34
*/
35
public Object calculateResultByFormula (String formula,Map<String,Object> paramMap) throws ScriptException {
36
ScriptEngineManager manager = new ScriptEngineManager();
37
ScriptEngine scriptEngine = manager.getEngineByName("js");
38
for (String key : paramMap.keySet()) {
39
formula = formula.replaceAll(key, paramMap.get(key).toString());
40
}
41
//此時 formula="(20.1+11.1)*(20.1-11.1)"
42
Object result = scriptEngine.eval(formula); // 運行js腳本
43
return result;
44
}
45
}
三、小結
通過百度,發現通過
ScriptEngineManager
相關api可以在java運行各種腳本。這種運行js腳本的方式,我們可以用來處理一些計算規則靈活多變的業務。就比如本項目中計算運費的模塊,由於運費計算規則比較多變,所以就采用這種方式實現。
