配置:
路径:resources/META-INF/kmodule.xml
1、DroolsConfig:
package com.drools;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.KieRepository;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.kie.spring.KModuleBeanFactoryPostProcessor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException;
/**
* decription 规则引擎配置类
* @author wangjingjing
* @date 2020/7/31 10:07
*/
@Configuration
public class DroolsConfig {
private static final String RULE_PATH = "rules/";
private final KieServices kieServices = KieServices.Factory.get();
@Bean
public KieServices getKieServices(){
return kieServices;
}
@Bean
@ConditionalOnMissingBean
public KieFileSystem kieFileSystem() throws IOException {
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm");
KieFileSystem kieFileSystem = kieServices.newKieFileSystem();
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource[] files = resourcePatternResolver.getResources("classpath*:" + RULE_PATH + "*.drl");
String path = null;
for (Resource file : files) {
path = RULE_PATH + file.getFilename();
kieFileSystem.write(ResourceFactory.newClassPathResource(path, "UTF-8"));
}
return kieFileSystem;
}
@Bean
@ConditionalOnMissingBean
public KieContainer kieContainer() throws IOException {
KieRepository kieRepository = kieServices.getRepository();
kieRepository.addKieModule(kieRepository::getDefaultReleaseId);
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem());
kieBuilder.buildAll();
return kieServices.newKieContainer(kieRepository.getDefaultReleaseId());
}
@Bean
@ConditionalOnMissingBean
public KieBase kieBase() throws IOException {
return kieContainer().getKieBase();
}
@Bean
public KModuleBeanFactoryPostProcessor kiePostProcessor() {
return new KModuleBeanFactoryPostProcessor();
}
}
2、RuleService:
package com.drools;
import com.haidilao.edge.config.ConstantConfig;
import com.haidilao.edge.rabbitmq.DirectProducer;
import com.haidilao.edge.vo.ServiceMessage;
import org.drools.core.base.RuleNameStartsWithAgendaFilter;
import org.kie.api.KieBase;
import org.kie.api.runtime.KieSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class RuleService {
@Autowired
private KieBase kieBase;
@Autowired
private DirectProducer directProducer;
public void ruleByName(ServiceMessage obj,String ruleName) {
KieSession kieSession = kieBase.newKieSession();
kieSession.insert(obj);
kieSession.setGlobal("topic", ConstantConfig.SERVICE_DOWNLINK_TOPIC);
kieSession.setGlobal("directProducer", directProducer);
//todo 后期不用过滤
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter(ruleName));
kieSession.dispose();
}
public void rule() {
KieSession kieSession = kieBase.newKieSession();
kieSession.setGlobal("topic", ConstantConfig.SERVICE_DOWNLINK_TOPIC);
kieSession.setGlobal("directProducer", directProducer);
kieSession.fireAllRules();
kieSession.dispose();
}
}
3、rule文件配置:
路径:resources/rules/Mqtt.drl
import com.vo.ServiceMessage
import com.config.ConstantConfig
import com.rabbitmq.DirectProducer
global String topic
global DirectProducer directProducer
rule "Mqtt"
when
$msg:ServiceMessage(identify == "order")
then
JSONObject jsonObject=new JSONObject();
String payload="触发事件上报内容";
jsonObject.put("identify","触发事件");
jsonObject.put("payload",payload);
System.out.println("directProducer:"+directProducer+";$msg:"+$msg);
directProducer.sendDirectMessage($msg.getPayload(), ConstantConfig.DIRECT_EXCHANGE, ConstantConfig.ROUTING);
MqttClientInit.getEmqInstance(true).publish($msg.getTopic().replace("output","input"), payload.getBytes(), 1, true);
System.out.println($msg.getIdentify()+"mqtt消息规则触发。。。。。");
end
4、controller:
@Autowired
private RuleService ruleService;
@RequestMapping("/testRule")
@ResponseBody
public String testTule() {
ruleService.rule();
return "ok";
}
5、实现规则热部署:
a、热部署配置ReloadDroolsRules:
package com.drools;
import org.drools.core.util.StringUtils;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.Message;
import org.kie.api.builder.Results;
import org.kie.api.runtime.KieContainer;
import org.kie.internal.io.ResourceFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;
import java.io.IOException;
@Service
public class ReloadDroolsRules {
@Autowired
private KieContainer kieContainer;
@Autowired
private KieServices kieServices;
@Autowired
private KieFileSystem kieFileSystem;
private static final String RULE_PATH = "rules/";
public void reload(String drlName) throws Exception {
// loadDBRules(drlName, kfs);
loadFileRules(drlName, kieFileSystem);
KieBuilder kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll();
Results results = kieBuilder.getResults();
if (results.hasMessages(Message.Level.ERROR)) {
System.out.println(results.getMessages());
throw new IllegalStateException("### errors ###");
}
kieContainer = kieServices.newKieContainer(kieServices.getRepository().getDefaultReleaseId());
System.out.println("新规则重载成功");
}
private void loadDBRules(String drlName, KieFileSystem kfs) {
// String path = "src/main/resources/rules/address.drl";
String path = "src/main/resources/" + RULE_PATH + "/" + drlName + ".drl";
// 从数据库加载的规则
kfs.write(path, "package plausibcheck.adress\n\n import com.neo.drools.model.Address;\n import com.neo.drools.model.fact.AddressCheckResult;\n\n rule \"Postcode 6 numbers\"\n\n when\n then\n System.out.println(\"打印日志:更新rules成功!\");\n end");
}
private void loadFileRules(String drlName, KieFileSystem kfs) throws IOException {
// 从classess/rules加载的规则
for (Resource file : getRuleFiles(drlName)) {
kfs.write(ResourceFactory.newClassPathResource(RULE_PATH + file.getFilename(), "UTF-8"));
}
}
private Resource[] getRuleFiles(String drlName) throws IOException {
if (StringUtils.isEmpty(drlName)) {
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources(RULE_PATH + "**/*.*");
}
ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
return resourcePatternResolver.getResources(RULE_PATH + "**/" + drlName + ".*");
}
}
b、调用热部署接口:我这里采用文件上传的方式:
@RequestMapping("/updateDrlFile")
@ResponseBody
public String updateDrlFile(HttpServletRequest request, MultipartFile file, @RequestParam("drlName") String drlName) throws Exception {
//更新drl后,再调用reload方法重载。即可热部署
String path = ResourceUtils.getURL("classpath:").getPath() + "rules/" + file.getOriginalFilename();
System.out.println("规则上传目录:" + path+",请注意每次规则热部署后要往项目路径里也放入一份,避免重启后规则丢失");
File dest = new File(path);
file.transferTo(dest);
reloadDroolsRules.reload(drlName);
return "ok";
}
好啦~完成!
奥对了,maven配置也加上吧!
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.3.1.RELEASE
com.wangjingjing
drools-study
0.0.1-SNAPSHOT
drools-study
Demo project for Spring Boot
1.8
3.4
1.2.50
2.10.1
2.8.6
1.7.7
1.9.22
28.1-jre
1.8.4.Final
7.40.0.Final
junit
junit
4.12
org.drools
drools-compiler
${drools-compiler.version}
org.drools
drools-templates
${drools-compiler.version}
org.kie
kie-api
${drools-compiler.version}
org.kie
kie-spring
${drools-compiler.version}
org.springframework
spring-tx
org.springframework
spring-beans
org.springframework
spring-core
org.springframework
spring-context
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-amqp
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.apache.commons
commons-lang3
${commons.lang3.version}
org.slf4j
slf4j-log4j12
${jslf4j-log4j12.version}
org.springframework.boot
spring-boot-starter-thymeleaf
net.sourceforge.nekohtml
nekohtml
${nekohtml.version}
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
com.alibaba
fastjson
${fastjson.version}
com.fasterxml.jackson.core
jackson-core
${fasterxml.jackson.version}
com.fasterxml.jackson.core
jackson-databind
${fasterxml.jackson.version}
com.fasterxml.jackson.core
jackson-annotations
${fasterxml.jackson.version}
org.projectlombok
lombok
true
com.google.code.gson
gson
${gson.version}
com.google.guava
guava
${guava.version}
com.aliyun.openservices
ons-client
${ons-client.version}
org.springframework.boot
spring-boot-maven-plugin
org.apache.maven.plugins
maven-war-plugin
iot-common
lib/
WEB-INF/lib
**/*.jar
以上!如有问题,欢迎交流~