在 Workbench 与 kie-server 搭建及使用 一文中,我们介绍了如何快速地搭建 Workbench 及 kie-server 服务。但如果尝试过该方法的同学应该会发现一个问题,中文的规则怎么就匹配不成功呢?这也许会让很多学习 Drools 的小伙伴头疼,毕竟 Drools 的中文资料太少,并没有什么可以参考的标准。
下面我来分享一下我解决这个问题的一个思路。
首先,既然是中文相关的问题,肯定和编码有关,首先想到的就是 Workbench 里面存储的规则文件的编码是不是有什么问题。既然有了想法那我们就去验证一下,在 Workbench 里面规则是使用 git 进行管理的,那我们将 Workbench 里面的项目 clone 到本地看看,命令十分简单,在 workbench 里面,8001 默认会作为 Git 仓库的端口:
git clone ssh://admin@localhost:8001/myrepo
在 clone 的过程中可能会遇到这么一个问题,提示信息为:
Unable to negotiate with 127.0.0.1 port 8001: no matching host key type found. Their offer: ssh-dss
fatal: Could not read from remote repository.
这是因为最新版本的 openssh 默认不推荐使用 DSA 密钥,只需要修改 ~/.ssh/config
,加上如下内容即可:
Host ${your-host}
HostkeyAlgorithms +ssh-dss
其中,${your-host} 需要替换成你安装 Workbench 服务器的主机地址,这里我使用 localhost,想偷懒的话,可以直接设置成 * 号。
项目复制完成之后,来检测一下规则文件的编码,Oh,My God!!!都是 utf-8,怎么就这么正常呢?
小小地失落那么一下后,继续前行。既然规则文件没有问题,那读取规则文件的地方有没有问题呢?Drools 会不会在加载规则文件的时候指定了什么编码?又需要开始进一步地验证了,这时候最好的方法就是去阅读 Drools 的源码,当然不需要去阅读整个体系的代码,只需要阅读规则文件加载这一块的代码即可,特别是 drl 文件或 rdrl 文件的加载。
在整个规则加载编译的过程中,各种形式的规则文件会被抽象成 Resource 对象,虽然常用的 FileSystemResource 有设置编码的地方,但实际上并被使用到,而后的解析流程更是使用字节流进行处理,未进行任何转码操作。在 DrlParser 中,Drools 将规则文件 InputStream 直接交给了 ANTLRInputStream,ANTLRInputStream 又使用 InputStreamReader 加载文本,而 InputStreamReader 在未指定编码时,会通过 Charset.defaultCharset() 获取一个默认的字符集,也就是 JVM 的默认字符集。
知道了整个规则文件的加载流程,那么只需要看下 JVM 的编码对不对就可以了,原本想要通过 jinfo 命令查看,但 Workbench 镜像内置的 JDK 存在 Bug,无法在该环境下正常执行,通过查看 Workbench 的启动日志发现,自定义的 JVM 参数只有在 Dockerfile 里面定义好的三项配置,其中并没有文件编码相关的设置,那 JVM 使用的应该就是操作系统的字符集了,通过 locale 指令查得系统编码并非 utf-8,好了,问题应该就是这样产生的了。
问题找到了,解决越来相对就容易多了,有两条路子:
将系统编码修改成 utf-8
在 JVM 参数中指定文件编码
很显然,第二种方法更加优雅,为了提高复用性,修改 Dockerfile 并重新构建镜像成了唯一选择,这里面参考 showcase 的构建,列举一下具体的操作步骤:
docker pull jboss/drools-workbench-showcase:7.5.0.Final
docker run -p 8080:8080 -p 8001:8001 -d --name drools-workbench jboss/drools-workbench-showcase:7.5.0.Final
mkdir etc
docker cp drools-workbench:/opt/jboss/wildfly/standalone/configuration/standalone-full-drools.xml etc/
docker cp drools-workbench:/opt/jboss/wildfly/standalone/configuration/drools-users.properties etc/
docker cp drools-workbench:/opt/jboss/wildfly/standalone/configuration/drools-roles.properties etc/
FROM jboss/drools-workbench:7.5.0.Final
MAINTAINER "Chery" "[email protected]"
####### 环境变量 ############
# Use demo and examples by default in this showcase image (internet connection required).
ENV KIE_SERVER_PROFILE standalone-full-drools
ENV JAVA_OPTS -Xms256m -Xmx512m -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8
####### Drools Workbench 常规配置 ############
ADD etc/standalone-full-drools.xml $JBOSS_HOME/standalone/configuration/standalone-full-drools.xml
ADD etc/drools-users.properties $JBOSS_HOME/standalone/configuration/drools-users.properties
ADD etc/drools-roles.properties $JBOSS_HOME/standalone/configuration/drools-roles.properties
# 修改配置文件的归属,由原先的 root 用户分配给 jboss 用户
USER root
RUN chown jboss:jboss $JBOSS_HOME/standalone/configuration/standalone-full-drools.xml && \
chown jboss:jboss $JBOSS_HOME/standalone/configuration/drools-users.properties && \
chown jboss:jboss $JBOSS_HOME/standalone/configuration/drools-roles.properties
# 切换到用户 jboss
USER jboss
####### 启动 DROOLS-WB ############
WORKDIR $JBOSS_HOME/bin/
CMD ["./start_drools-wb.sh"]
docker build -t qchery/drools-workbench-showcase:7.5.0.Final .
docker run -p 8080:8080 -p 8001:8001 -d --name drools-wb qchery/drools-workbench-showcase:7.5.0.Final
配置规则及测试场景,规则源码如下:
import java.lang.Number;
rule "rule_001"
dialect "java"
when
Address( province == "湖北" )
then
System.out.println("hello 中文");
end
执行测试场景,可在后台日志中看到对应输出,问题解决:
15:11:20,819 INFO [stdout] (default task-29) hello 中文
同理,Kie-Server 的中文问题也可以如此解决。
注:相关配置已经上传 github,地址为:drools-dockerfile,欢迎 fork!!! 如果感觉此篇文章对您有用,帮忙点个赞!!!
参考链接: