在JAVA開發過程中,有時會遇到一些小運算。比如傳入一個List集合,我們需要根據集合中的某一屬性做過濾。
相信這種場景大家都有遇到過,通常的解決辦法是直接在java代碼中寫好一些比較規則,實現上也是比較簡單的。
但是如果這個規則是動態的呢,假如A類型的數據,我們根據A字段過濾,B類型的數據,我們根據字段B過濾。這時突然又來了個C類型的數據,難道又要寫個C的過濾方法,再重新發布上線嗎?
當然是不用的,JAVA的開發大牛早就幫我們想好了解決的辦法。因為JAVA本身編譯型的限制,我們可以使用JavaScript等腳本語言來實現規則的動態外置。ScriptEngineManager這個類就是java中用來運行JavaScript腳本的引擎。
舉個很簡單的例子:
public static void main(String[] args) { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine js = manager.getEngineByName("JavaScript"); //構建原始數據 JSONObject jsonObject1 = JSONObject.parseObject("{'status':'success', 'remark':'下單成功'}"); JSONObject jsonObject2 = JSONObject.parseObject("{'status':'fail', 'remark':'下單失敗,余額不足'}"); JSONObject jsonObject3 = JSONObject.parseObject("{'status':'success', 'remark':'下單成功'}"); List<JSONObject> list = new ArrayList<>(); list.add(jsonObject1); list.add(jsonObject2); list.add(jsonObject3); //構建規則參數 Map<String, String> filter2 = new TreeMap<>(); filter2.put("val1", "status"); filter2.put("val2", "remark"); String rule = "'status' === 'fail' && 'remark'.indexOf('失敗') > -1"; List<JSONObject> result = new ArrayList<>(); for (JSONObject map : list) { //構建參數實際值 List<String> listValue = new ArrayList<>(); filter2.forEach((key, val) -> { String s = map.get(val).toString(); listValue.add(s); }); String[] array = new String[listValue.size()]; array = listValue.toArray(array); //需要執行的實際規則 String evalRule = StringUtils.replaceEach(rule, new String[]{"status","remark"}, array); boolean a = false; try { //規則執行 a = (boolean) js.eval(evalRule); if (a){ result.add(map); } } catch (ScriptException e) { e.printStackTrace(); } } System.out.println(result); }
結果:[{"remark":"下單失敗,余額不足","status":"fail"}]
上述案例中,我們傳入一個size為3的list集合,根據狀態和備注字段來過濾下單失敗的訂單,輕而易舉的就得到了預期的結果值。是不是感覺在java中寫js也是一種很神奇的體驗呢。
想一想,如果我們將需要比較的規則字段和比較規則兩個屬性寫入數據庫中呢。這時候你傳入其他類型的數據,只需要在數據庫中增加相應規則的配置,而后直接根據數據庫中配置的規則和字段做比較,是不是就實現了數據的動態過濾了。再也不用為解析不同的數據而煩惱,再也不用編寫重復而冗余的過濾代碼了。