使用 Java 脚本引擎实现业务规则可配置化

提出问题

  • 在有些项目中存在大量经常变化的规则逻辑,比如审核、风控规则。

  • 如果规则硬编码在 Java 代码中,每次修改规则都要重新修改代码、测试、重启发布,很麻烦。

解决思路

  • 从 JDK6 开始,Java 提供了 ScriptEngine 接口,支持执行解释性语言,例如 Javascript。使得可在 Java 代码中执行 Javascript 代码。
  • ScriptEngine 提供了 eval 方法,可执行传入的 Javascript 字符串或流形式的代码块。
  • 这样,整个 Script 脚本就相当于配置文件独立于代码之外。我们可以将其保存在配置中心、数据库或 Zookeeper 中,方便及时响应业务变化。

示例

下面举个简单的例子(深圳小汽车摇号政策)

新建 rool.js 脚本文件,里面维护具体的规则逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 定义因子
var
RESIDE_CITY, // 居住地
HAS_DRIVER_LICENSE, // 是否有 C 以上驾照
HAS_CAR, // 是否有本地小汽车
o;

// 定义规则函数
function doRool() {
if (RESIDE_CITY != '440300') {
return "非本地居住";
}

if (HAS_DRIVER_LICENSE != 'Y') {
return "无 C 以上驾照";
}

if (HAS_CAR != 'N') {
return "本地已有小汽车";
}

return ""; // 没有被拦截。
}

// 执行规则
doRool();

Java 代码执行 rool.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
String js = FileUtils.readFileToString(new File("D:/rool.js")); // 读取脚本。

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("javascript");

// 向脚本传递参数
engine.put("RESIDE_CITY", "440300");
engine.put("HAS_DRIVER_LICENSE", "Y");
engine.put("HAS_CAR", "Y");

// 执行并打印
System.out.println(engine.eval(js));

>:本地已有小汽车