我正在使用drools来评估某些对象的系统。但是,这些对象可以是使用jodd在运行时加载的类。我可以使用以下函数加载文件:
public static void loadClassFile(File file) {
try {
// use Jodd ClassLoaderUtil to load class into the current ClassLoader
ClassLoaderUtil.defineClass(getBytesFromFile(file));
} catch (IOException e) {
exceptionLog(LOG_ERROR, getInstance(), e);
}
}
现在假设我创建了一个名为Tire的类,并使用上面的函数加载它。有没有办法可以在我的规则文件中使用Tire类:
rule "Tire Operational"
when
$t: Tire(pressure == 30)
then
end
现在,如果我尝试添加此规则,则会收到错误消息,指出无法解析ObjectType Tire。我的假设是我会在某种程度上需要在规则中导入Tire,但我不确定如何做到这一点。
答案 0 :(得分:1)
自版本3以来没有使用Drools,但无论如何都会尝试提供帮助。当您以这种方式加载类时(动态地,在运行时,无论您是否使用例如Class.forName()或Jodd),加载的类名都无法在代码中显式使用。我相信我们可以使用以下sudo-code来简化您的问题,首先加载一个类,然后尝试使用它的名称:
defineClass('Tire.class');
Tire tire = new Tire();
这显然不起作用,因为在编译时Tire类型不可用:编译器不知道在执行期间你要加载什么类型。
让Tire实现某些界面(例如VehiclePart)会起作用。那么你可以使用以下sudo-code:
Class tireClass = defineClass('Tire.class');
VehiclePart tire = tireClass.newInstance();
System.out.println(tire.getPartName()); // prints 'tire' for example
然后,您可以通过VehiclePart和getPartName()属性接口构建Drools规则。
<强>附录强>
只有当界面涵盖动态加载类的所有属性时才有意义。在大多数情况下,这不是一个有效的解决方案:动态加载的类根本不共享属性。所以,这是另一种方法。
可以通过“扩展”类加载器类路径来解决此问题,而不是使用显式类加载。请注意,这是 hack !
在Jodd中,有一种方法: ClassLoaderUtil.addFileToClassPath(),它可以在运行时中添加文件或路径到类加载器。以下是适用于我的步骤:
1)将所有动态创建的类放入一些根文件夹中,并尊重其包。例如,假设我们要使用 jodd.samples.TestBean 类,它有两个属性: number (int)和 value (串)。然后,我们需要将此类放入 root / jodd / samples 文件夹中。
2)构建所有动态类之后,扩展类加载器路径:
ClassLoaderUtil.addFileToClassPath("root", ClassLoader.getSystemClassLoader());
3)加载类并在创建KnowledgeBuilder之前创建它:
Class testBeanClass = Class.forName("jodd.samples.TestBean");
Object testBean = testBeanClass.newInstance();
4)此时你可以使用BeanUtils(来自Jodd,例如:)来操作testBean实例的属性
5)创建Drools内容并将insert testBean添加到session:
knowledgeSession.insert(testBean);
6)在规则文件中使用它:
import jodd.samples.TestBean;
rule "xxx"
when
$t: TestBean(number == 173)
then
System.out.println("!!!");
end
这对我有用。请注意,在步骤#2中,您可以尝试使用不同的类加载器,但您可能需要它通过KnowledgeBuilderConfiguration(即PackageBuilderConfiguration)将其传递给KnowledgeBuilderFactory。
另一种解决方案
另一种解决方案是简单地将所有对象属性复制到地图,并处理规则文件中的地图。所以你可以在第4步使用这样的东西:
Map map = new HashMap();
BeanTool.copy(testBean, map);
以后(步骤#5)将地图添加到Drools上下文而不是bean实例。在这种情况下,使用 defineClass()方法明确定义每个类会更好。