Drools使用注意事项

使用场景:

public void doCustomer() {
//
People people = new People();
people.setName("哒");
people.setSex(1);
people.setDrlType("people");
//
KieServices kieServices = KieServices.Factory.get();
StatelessKieSession kieSession = kieServices.getKieClasspathContainer().newStatelessKieSession("my-test");
List<Command> commands = new ArrayList<>();
KieCommands kieCommands = kieServices.getCommands();
commands.add(kieCommands.newInsert(people, "input"));

ExecutionResults execute = kieSession.execute(kieCommands.newBatchExecution(commands));

}
项目中,有两个地方调用doCustomer方法,一个是rabbitMq的监听类,一个是Controller接口处
这两处的调用,由于当前线程的上下文加载器不同,导致只能有其中一处的调用正常,另外一个报错

异常问题:

抛出异常There's already another KieContainer created from a different ClassLoader

解决方案:

通过分析源码,发现:
// 使用Holder内部类的方式,创建了一个单例对象
KieServices kieServices = KieServices.Factory.get();

// 使用Volatile + Double-Check的方式,创建了一个单例对象;
KieContainer kieContainer = kieServices.getKieClasspathContainer(); 但是,代码中,会校验classLoader != classpathClassLoader ???

前者为当前线程上下文类加载器,后者为第一次创建KieContainer的线程类加载器这么一分析,发现是两处的调用,线程上下文加载器不一致导致的报错。
解决办法之一,就是,在项目启动的时候,初始化 KieServices 和 KieContainer 对象
或者
KieServices kieServices = KieServices.Factory.get();
StatelessKieSession kieSession = kieServices.getKieClasspathContainer(this.getClass().getClassLoader()).newStatelessKieSession("my-test");

 

posted @ 2020-12-16 00:00  艳阳下的小菜园  阅读(649)  评论(0编辑  收藏  举报