From eab23f8499d04e1113a42f1d6400fb53c66a2998 Mon Sep 17 00:00:00 2001 From: mengyxu Date: Fri, 22 Sep 2023 16:57:09 +0800 Subject: [PATCH] init --- .gitignore | 6 + README.md | 3 + application.properties | 8 + logback.xml | 46 ++++++ pom.xml | 146 +++++++++++++++++ .../vip/xumy/drools/DroolsApplocation.java | 14 ++ .../vip/xumy/drools/action/CdrGenerator.java | 150 ++++++++++++++++++ .../vip/xumy/drools/conf/DroolsConfig.java | 118 ++++++++++++++ .../xumy/drools/conf/DroolsInitializer.java | 20 +++ .../xumy/drools/ctrl/CdrRuleController.java | 24 +++ src/main/java/vip/xumy/drools/pojo/CDR.java | 51 ++++++ .../vip/xumy/drools/pojo/DroolsBurster.java | 51 ++++++ .../java/vip/xumy/drools/pojo/RuleSink.java | 23 +++ .../xumy/drools/service/CdrRuleService.java | 28 ++++ .../xumy/drools/service/DroolsApiService.java | 39 +++++ src/main/resources/application.properties | 28 ++++ src/main/resources/rules/hello.drl | 134 ++++++++++++++++ 17 files changed, 889 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 application.properties create mode 100644 logback.xml create mode 100644 pom.xml create mode 100644 src/main/java/vip/xumy/drools/DroolsApplocation.java create mode 100644 src/main/java/vip/xumy/drools/action/CdrGenerator.java create mode 100644 src/main/java/vip/xumy/drools/conf/DroolsConfig.java create mode 100644 src/main/java/vip/xumy/drools/conf/DroolsInitializer.java create mode 100644 src/main/java/vip/xumy/drools/ctrl/CdrRuleController.java create mode 100644 src/main/java/vip/xumy/drools/pojo/CDR.java create mode 100644 src/main/java/vip/xumy/drools/pojo/DroolsBurster.java create mode 100644 src/main/java/vip/xumy/drools/pojo/RuleSink.java create mode 100644 src/main/java/vip/xumy/drools/service/CdrRuleService.java create mode 100644 src/main/java/vip/xumy/drools/service/DroolsApiService.java create mode 100644 src/main/resources/application.properties create mode 100644 src/main/resources/rules/hello.drl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1f3947 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +/.classpath +/.project +/.settings +/bin/ +/logs +/target diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a38559 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# drools demo + +​ SpringBoot集成drools测试demo项目 \ No newline at end of file diff --git a/application.properties b/application.properties new file mode 100644 index 0000000..e4d222e --- /dev/null +++ b/application.properties @@ -0,0 +1,8 @@ +server.port=80 +server.servlet.context-path=/ +dev=on +# 程序自身数据源配置 +spring.datasource.url=jdbc:mysql://localhost:3306/admin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true +spring.datasource.username=root +spring.datasource.password=51131420 + diff --git a/logback.xml b/logback.xml new file mode 100644 index 0000000..0c05c5c --- /dev/null +++ b/logback.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + + + + + ${LOG_HOME}/drools-%d{yyyy-MM-dd}.log + + 30 + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n + + + + 10MB + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..31b55d7 --- /dev/null +++ b/pom.xml @@ -0,0 +1,146 @@ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.1 + + vip.xumy.drools + xumy_drools + 0.0.0 + drools + xumy-drools + jar + + + 17 + UTF-8 + UTF-8 + + 1.0.0 + 1.2.17 + 1.2.46 + 1.1.9 + 3.5.1 + 1.4.6 + 7.74.1.Final + 7.74.1.Final + + + + + + vip.xumy.core + xumy_core + ${core.version} + + + + + org.springframework.boot + spring-boot-devtools + true + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + + + + junit + junit + + + org.junit.vintage + junit-vintage-engine + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + + + mysql + mysql-connector-java + runtime + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + + + com.baomidou + mybatis-plus-boot-starter + ${mybatis-plus.version} + + + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${mybatis.pagehelper.version} + + + + + + org.drools + drools-core + ${drools.version} + + + org.drools + drools-compiler + ${drools.version} + + + org.drools + drools-templates + ${drools.version} + + + org.kie + kie-api + ${drools.version} + + + org.kie + kie-spring + ${drools.version} + + + + + + + + drools + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + \ No newline at end of file diff --git a/src/main/java/vip/xumy/drools/DroolsApplocation.java b/src/main/java/vip/xumy/drools/DroolsApplocation.java new file mode 100644 index 0000000..b6bd916 --- /dev/null +++ b/src/main/java/vip/xumy/drools/DroolsApplocation.java @@ -0,0 +1,14 @@ +package vip.xumy.drools; + +import org.springframework.boot.SpringApplication; + +import vip.xumy.drools.conf.DroolsInitializer; + +public class DroolsApplocation { + + public static void main(String[] args) { + Class[] arr = new Class[] { DroolsInitializer.class }; + SpringApplication.run(arr, args); + } + +} diff --git a/src/main/java/vip/xumy/drools/action/CdrGenerator.java b/src/main/java/vip/xumy/drools/action/CdrGenerator.java new file mode 100644 index 0000000..c48c1d8 --- /dev/null +++ b/src/main/java/vip/xumy/drools/action/CdrGenerator.java @@ -0,0 +1,150 @@ +package vip.xumy.drools.action; + +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import org.drools.core.time.SessionPseudoClock; +import org.kie.api.runtime.KieSession; + +import lombok.extern.log4j.Log4j2; +import vip.xumy.core.utils.DateUtil; +import vip.xumy.drools.pojo.CDR; + +/** + * Ownership belongs to the company + * + * @author:mengyxu + * @date:2023年9月22日 + */ + +@Log4j2 +public class CdrGenerator { + public static final List CDRS = new ArrayList<>(); + static { + CDRS.add(new CDR(0, "CN", "CN", "460018765432101", "8618601234567", 2, null)); + CDRS.add(new CDR(1, "CN", "CN", "460018765432101", "8618601234567", 3, null)); + CDRS.add(new CDR(2, "CN", "CN", "460018765437788", "8618601237788", 2, null)); + CDRS.add(new CDR(3, "JP", "CN", "460018765432101", "8618601234567", 2, null)); + CDRS.add(new CDR(4, "CN", "CN", "460018765437755", "8618601237755", 2, null)); + CDRS.add(new CDR(5, "JP", "CN", "460018765432101", "8618601234567", 45, null)); + CDRS.add(new CDR(6, "CN", "CN", "460018765432101", "8618601234567", 3, null)); + CDRS.add(new CDR(7, "JP", "CN", "460018765432101", "8618601234567", 2, null)); + CDRS.add(new CDR(8, "CN", "CN", "460018765436633", "8618601236633", 2, null)); + CDRS.add(new CDR(9, "CN", "CN", "460018765432101", "8618601234567", 3, null)); + CDRS.add(new CDR(10, "CN", "CN", "460018765437755", "8618601237755", 2, null)); + CDRS.add(new CDR(11, "CN", "CN", "460018765432101", "8618601234567", 2, null)); + CDRS.add(new CDR(12, "CN", "CN", "460018765437788", "8618601237788", 2, null)); + CDRS.add(new CDR(13, "CN", "CN", "460018765437755", "8618601237755", 2, null)); + CDRS.add(new CDR(14, "CN", "CN", "460018765436633", "8618601236633", 2, null)); + CDRS.add(new CDR(15, "CN", "CN", "460018765432102", "8618601234568", 2, null)); + CDRS.add(new CDR(16, "CN", "CN", "460018765432102", "8618601234568", 3, null)); + CDRS.add(new CDR(17, "CN", "CN", "460018765437789", "8618601237789", 2, null)); + CDRS.add(new CDR(18, "JP", "CN", "460018765432102", "8618601234568", 2, null)); + CDRS.add(new CDR(19, "CN", "CN", "460018765437756", "8618601237756", 2, null)); + CDRS.add(new CDR(20, "JP", "CN", "460018765432102", "8618601234568", 45, null)); + CDRS.add(new CDR(21, "CN", "CN", "460018765432102", "8618601234568", 3, null)); + CDRS.add(new CDR(22, "JP", "CN", "460018765432102", "8618601234568", 2, null)); + CDRS.add(new CDR(23, "CN", "CN", "460018765436634", "8618601236634", 2, null)); + CDRS.add(new CDR(24, "CN", "CN", "460018765432102", "8618601234568", 3, null)); + CDRS.add(new CDR(25, "CN", "CN", "460018765437756", "8618601237756", 2, null)); + CDRS.add(new CDR(26, "CN", "CN", "460018765432102", "8618601234568", 2, null)); + CDRS.add(new CDR(27, "CN", "CN", "460018765437789", "8618601237789", 2, null)); + CDRS.add(new CDR(28, "CN", "CN", "460018765437756", "8618601237756", 2, null)); + CDRS.add(new CDR(29, "CN", "CN", "460018765436634", "8618601236634", 2, null)); + CDRS.add(new CDR(30, "CN", "HK", "454018765432101", "8521234567", 2, null)); + CDRS.add(new CDR(31, "CN", "HK", "454018765432101", "8521234567", 3, null)); + CDRS.add(new CDR(32, "CN", "HK", "454018765437788", "8521237788", 2, null)); + CDRS.add(new CDR(33, "JP", "HK", "454018765432101", "8521234567", 2, null)); + CDRS.add(new CDR(34, "CN", "HK", "454018765437755", "8521237755", 2, null)); + CDRS.add(new CDR(35, "JP", "HK", "454018765432101", "8521234567", 45, null)); + CDRS.add(new CDR(36, "CN", "HK", "454018765432101", "8521234567", 3, null)); + CDRS.add(new CDR(37, "JP", "HK", "454018765432101", "8521234567", 2, null)); + CDRS.add(new CDR(38, "CN", "HK", "454018765436633", "8521236633", 2, null)); + CDRS.add(new CDR(39, "CN", "HK", "454018765432101", "8521234567", 3, null)); + CDRS.add(new CDR(40, "CN", "HK", "454018765437755", "8521237755", 2, null)); + CDRS.add(new CDR(41, "CN", "HK", "454018765432101", "8521234567", 2, null)); + CDRS.add(new CDR(42, "CN", "HK", "454018765437788", "8521237788", 2, null)); + CDRS.add(new CDR(43, "CN", "HK", "454018765437755", "8521237755", 2, null)); + CDRS.add(new CDR(44, "CN", "HK", "454018765436633", "8521236633", 2, null)); + CDRS.add(new CDR(45, "CN", "HK", "454017765437755", "8522237755", 2, null)); + CDRS.add(new CDR(46, "CN", "HK", "454017765432101", "8522234567", 2, null)); + CDRS.add(new CDR(47, "CN", "HK", "454017765437788", "8522237788", 2, null)); + CDRS.add(new CDR(48, "CN", "HK", "454017765437755", "8522237755", 2, null)); + CDRS.add(new CDR(49, "CN", "HK", "454017765436633", "8522236633", 2, null)); + } + + private KieSession ks; + private SessionPseudoClock clock; + private long currentTime = System.currentTimeMillis(); + private long timestamp = System.currentTimeMillis(); + private int maxNum; + private int maxTime; + private int sum; + private int loop; + private boolean running = false; + + public CdrGenerator(KieSession ks, int maxNum, int maxTime, int loop) { + this.ks = ks; + this.clock = ks.getSessionClock(); + this.maxNum = maxNum; + this.maxTime = maxTime; + this.loop = loop; + } + + public void start() { + running = true; + new Thread(this::run).start(); + new Thread(this::log).start(); + } + + private void log() { + while (running) { + log.debug(MessageFormat.format("loop:{0},已匹配{1}次规则", loop, sum)); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void run() { + currentTime = System.currentTimeMillis(); + clock.advanceTime(currentTime, TimeUnit.MILLISECONDS); + Random rand = new Random(); + long start = System.currentTimeMillis(); + log.debug(MessageFormat.format("开始匹配{0}条数据", loop * CDRS.size())); + + CDR cdr; + long id = 0; + long count = 0; + while (loop-- > 0) { + for (CDR item : CDRS) { + timestamp += rand.nextInt(1000); + cdr = new CDR(item); + cdr.setId(id++); + cdr.setCreateTime(new Date(timestamp)); + ks.insert(cdr); + if (count >= maxNum || timestamp - currentTime > maxTime) { + clock.advanceTime(timestamp - currentTime, TimeUnit.MILLISECONDS); + currentTime = timestamp; + count = 0; + sum += ks.fireAllRules(); + } + count++; + } + } + sum += ks.fireAllRules(); + ks.dispose(); + running = false; + long finish = System.currentTimeMillis(); + log.debug("数据最后时间:" + DateUtil.format(new Date(timestamp))); + log.debug(MessageFormat.format("数据匹配完成,{0}开始,{1}结束,耗时{2}秒,匹配到{3}次规则", DateUtil.format(new Date(start)), + DateUtil.format(new Date(finish)), (finish - start) / 1000, sum)); + } + +} diff --git a/src/main/java/vip/xumy/drools/conf/DroolsConfig.java b/src/main/java/vip/xumy/drools/conf/DroolsConfig.java new file mode 100644 index 0000000..02cfaad --- /dev/null +++ b/src/main/java/vip/xumy/drools/conf/DroolsConfig.java @@ -0,0 +1,118 @@ +package vip.xumy.drools.conf; + +import java.io.File; +import java.io.IOException; + +import org.kie.api.KieBase; +import org.kie.api.KieBaseConfiguration; +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.conf.EventProcessingOption; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.KieSessionConfiguration; +import org.kie.api.runtime.conf.ClockTypeOption; +import org.kie.internal.io.ResourceFactory; +import org.kie.spring.KModuleBeanFactoryPostProcessor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.system.ApplicationHome; +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; + +@Configuration +public class DroolsConfig { + private static final String RULES_PATH = "rules/"; + public static final String JAR_ROOT_PATH; + public static final String CLASSPATH = "classpath:"; +// private static final String JAVA_ROOT = "src/main/java/"; +// private static final String RESOURCES_ROOT = "src/main/resources/"; + + static { + ApplicationHome h = new ApplicationHome(DroolsConfig.class); + File jarF = h.getSource(); + JAR_ROOT_PATH = jarF.getParentFile().getAbsolutePath() + '/'; + } + + @Bean + @ConditionalOnMissingBean(KieFileSystem.class) + public KieFileSystem kieFileSystem() throws IOException { + KieFileSystem kieFileSystem = getKieServices().newKieFileSystem(); + File dir = new File(JAR_ROOT_PATH + RULES_PATH); + if (dir.exists()) { + for (File file : dir.listFiles()) { + kieFileSystem.write(ResourceFactory.newFileResource(file)); + } + } else { + ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + Resource[] resources = resourcePatternResolver.getResources(CLASSPATH + RULES_PATH + "**/*.*"); + for (Resource resource : resources) { + kieFileSystem.write(ResourceFactory.newFileResource(resource.getFile())); + } + } + return kieFileSystem; + } + +// private String getPath(org.kie.api.io.Resource resource) { +// String target = resource.getTargetPath() != null ? resource.getTargetPath() : resource.getSourcePath(); +// if (target != null) { +// String prefix = resource.getResourceType() == ResourceType.JAVA ? JAVA_ROOT : RESOURCES_ROOT; +// int prefixPos = target.indexOf(prefix); +// String path = prefixPos >= 0 ? target.substring(prefixPos) : prefix + target; +// path = path.replace(java.io.File.separatorChar, '/'); +// return path; +// } else { +// throw new RuntimeException( +// "Resource does not have neither a source nor a target path. Impossible to add it to the bundle. Please set either the source or target name of the resource before adding it." +// + resource.toString()); +// } +// } + + @Bean + @ConditionalOnMissingBean(KieContainer.class) + public KieContainer kieContainer() throws IOException { + KieServices kieServices = getKieServices(); + final KieRepository kieRepository = kieServices.getRepository(); + // 设置时间格式 + System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss"); + kieRepository.addKieModule(kieRepository::getDefaultReleaseId); + build(); + return kieServices.newKieContainer(kieRepository.getDefaultReleaseId()); + } + + public KieServices getKieServices() { + return KieServices.Factory.get(); + } + + public void build() throws IOException { + KieBuilder kieBuilder = getKieServices().newKieBuilder(kieFileSystem()); + kieBuilder.buildAll(); + } + + @Bean + @ConditionalOnMissingBean(KieBase.class) + public KieBase kieBase() throws IOException { + KieBase kieBase = kieContainer().getKieBase(); + return kieBase; + } + + @Bean + @ConditionalOnMissingBean(KieSession.class) + public KieSession kieSession() throws IOException { + KieBaseConfiguration baseConf = KieServices.Factory.get().newKieBaseConfiguration(); + baseConf.setOption(EventProcessingOption.STREAM); + KieSessionConfiguration sessConf = KieServices.Factory.get().newKieSessionConfiguration(); + sessConf.setOption(ClockTypeOption.get("pseudo")); + return kieContainer().newKieSession(sessConf); + } + + @Bean + @ConditionalOnMissingBean(KModuleBeanFactoryPostProcessor.class) + public KModuleBeanFactoryPostProcessor kiePostProcessor() { + return new KModuleBeanFactoryPostProcessor(); + } +} diff --git a/src/main/java/vip/xumy/drools/conf/DroolsInitializer.java b/src/main/java/vip/xumy/drools/conf/DroolsInitializer.java new file mode 100644 index 0000000..180fd2a --- /dev/null +++ b/src/main/java/vip/xumy/drools/conf/DroolsInitializer.java @@ -0,0 +1,20 @@ +package vip.xumy.drools.conf; + +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; + +@EnableAutoConfiguration(exclude = DataSourceAutoConfiguration.class) +@ComponentScan(value = "vip.xumy.drools, vip.xumy.core") +@MapperScan({ "vip.xumy.drools.mapper" }) +public class DroolsInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder.sources(DroolsInitializer.class); + } + +} diff --git a/src/main/java/vip/xumy/drools/ctrl/CdrRuleController.java b/src/main/java/vip/xumy/drools/ctrl/CdrRuleController.java new file mode 100644 index 0000000..555ee61 --- /dev/null +++ b/src/main/java/vip/xumy/drools/ctrl/CdrRuleController.java @@ -0,0 +1,24 @@ +package vip.xumy.drools.ctrl; + +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import vip.xumy.drools.service.CdrRuleService; + +@RestController +@RequestMapping("rule/cdr") +public class CdrRuleController { + @Autowired + private CdrRuleService cdrRuleService; + + @GetMapping("test/{loop}") + public void fireAllRules4One(@PathVariable("loop")Integer loop) throws IOException { + cdrRuleService.test(loop); + } + +} \ No newline at end of file diff --git a/src/main/java/vip/xumy/drools/pojo/CDR.java b/src/main/java/vip/xumy/drools/pojo/CDR.java new file mode 100644 index 0000000..bd60894 --- /dev/null +++ b/src/main/java/vip/xumy/drools/pojo/CDR.java @@ -0,0 +1,51 @@ +package vip.xumy.drools.pojo; + +import java.util.Date; + +import lombok.Data; + +@Data +public class CDR { + private Long id; + private String callerCN; + private String calledCN; + private String imsi; + private String msisdn; + private int msgType; + private Date createTime; + private long duration; + + public CDR(long id, String callerCN, String calledCN, String imsi, String msisdn, int msgType, Date date) { + this.id = id; + this.callerCN = callerCN; + this.calledCN = calledCN; + this.imsi = imsi; + this.msisdn = msisdn; + this.msgType = msgType; + if (date == null) + this.createTime = new Date(); + else + this.createTime = date; + this.duration = 50; + } + + public CDR() { + } + + public CDR(CDR cdr) { + id = cdr.id; + callerCN = cdr.callerCN; + calledCN = cdr.calledCN; + imsi = cdr.imsi; + msisdn = cdr.msisdn; + msgType = cdr.msgType; + createTime = cdr.createTime; + duration = cdr.duration; + } + +// @Override +// protected void finalize() throws Throwable { +// System.out.println(this.id + " is deleted"); +// } + +} diff --git a/src/main/java/vip/xumy/drools/pojo/DroolsBurster.java b/src/main/java/vip/xumy/drools/pojo/DroolsBurster.java new file mode 100644 index 0000000..5850e87 --- /dev/null +++ b/src/main/java/vip/xumy/drools/pojo/DroolsBurster.java @@ -0,0 +1,51 @@ +package vip.xumy.drools.pojo; + +import java.util.concurrent.TimeUnit; + +import org.drools.core.time.SessionPseudoClock; +import org.kie.api.runtime.KieSession; + +//@Log4j2 +public class DroolsBurster { + private KieSession ks; + private SessionPseudoClock clock; + private long currentTime; + private int burst; + private int count; + + public DroolsBurster(KieSession ks, String clockType, int burst) { + this.ks = ks; + if (clockType == "pseudo") + clock = ks.getSessionClock(); + else + clock = null; + currentTime = 0; + currentTime = System.currentTimeMillis(); + clock.advanceTime(currentTime, TimeUnit.MILLISECONDS); + count = 0; + this.burst = burst; + } + + // 将事件插入KieSession,并根据时间戳(ms)推进时钟,在一定时间间隔触发规则 + public int insert(Object evt, long timestamp) { + ks.insert(evt); + if (count >= burst || timestamp - currentTime > 1000) { + if (clock != null) { + clock.advanceTime(timestamp - currentTime, TimeUnit.MILLISECONDS); + currentTime = timestamp; + } + + count = 0; + int num = ks.fireAllRules(); + return num; + } + count++; + return 0; + } + + public void dispose() { + if (ks != null) + ks.dispose(); + } + +} diff --git a/src/main/java/vip/xumy/drools/pojo/RuleSink.java b/src/main/java/vip/xumy/drools/pojo/RuleSink.java new file mode 100644 index 0000000..ab24071 --- /dev/null +++ b/src/main/java/vip/xumy/drools/pojo/RuleSink.java @@ -0,0 +1,23 @@ +package vip.xumy.drools.pojo; +import java.util.List; + + + +public class RuleSink { + String ruleName; + String ruleInfo; + Long trapId; + List cdrIDs; + + public RuleSink(Long trapId, String ruleName, String ruleInfo, List cdrIDs) { + this.ruleName = ruleName; + this.ruleInfo = ruleInfo; + this.trapId = trapId; + this.cdrIDs = cdrIDs; + //this.cdrIDs.add(0, trapId); + } + + public String toString() { + return String.format("{\"trapId\" : %d, \"cdrs\": %s, \"rule\" : \"%s\", \"info\" : \"%s\"}\n", trapId, cdrIDs, ruleName, ruleInfo); + } +} diff --git a/src/main/java/vip/xumy/drools/service/CdrRuleService.java b/src/main/java/vip/xumy/drools/service/CdrRuleService.java new file mode 100644 index 0000000..39efd1f --- /dev/null +++ b/src/main/java/vip/xumy/drools/service/CdrRuleService.java @@ -0,0 +1,28 @@ +package vip.xumy.drools.service; + +import java.io.IOException; + +import org.kie.api.runtime.KieSession; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import vip.xumy.drools.action.CdrGenerator; + +/** + * Ownership belongs to the company + * + * @author:mengyxu + * @date:2023年9月19日 + */ + +@Service +public class CdrRuleService { + @Autowired + private DroolsApiService droolsApiService; + + public void test(Integer loop) throws IOException { + KieSession ks = droolsApiService.createSession(true); + new CdrGenerator(ks, 500, 10000, loop).start(); + } + +} diff --git a/src/main/java/vip/xumy/drools/service/DroolsApiService.java b/src/main/java/vip/xumy/drools/service/DroolsApiService.java new file mode 100644 index 0000000..fcaa73f --- /dev/null +++ b/src/main/java/vip/xumy/drools/service/DroolsApiService.java @@ -0,0 +1,39 @@ +package vip.xumy.drools.service; + +import java.io.IOException; + +import org.kie.api.KieServices; +import org.kie.api.runtime.KieContainer; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.KieSessionConfiguration; +import org.kie.api.runtime.conf.ClockTypeOption; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import vip.xumy.drools.conf.DroolsConfig; + +/** + * Ownership belongs to the company + * + * @author:mengyxu + * @date:2023年9月20日 + */ + +@Service +public class DroolsApiService { + private static final KieSessionConfiguration sessConf; + static { + sessConf = KieServices.Factory.get().newKieSessionConfiguration(); + sessConf.setOption(ClockTypeOption.get("pseudo")); + } + @Autowired + private KieContainer kieContainer; + private DroolsConfig config = new DroolsConfig(); + + public KieSession createSession(boolean reBuild) throws IOException { + if(reBuild) + config.build(); + return kieContainer.newKieSession(sessConf); + } + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..ca0da53 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,28 @@ +logging.config:logback.xml + +spring.main.banner-mode=off + +spring.datasource.type=com.alibaba.druid.pool.DruidDataSource +spring.datasource.driver-class-name=com.mysql.jdbc.Driver +spring.datasource.initialSize=1 +spring.datasource.minIdle=1 +spring.datasource.maxActive=20 +spring.datasource.maxWait=60000 +spring.datasource.timeBetweenEvictionRunsMillis=60000 +spring.datasource.minEvictableIdleTimeMillis=300000 +spring.datasource.validationQuery=SELECT 1 FROM DUAL +spring.datasource.keepAlive=true +spring.datasource.testWhileIdle=true +spring.datasource.testOnBorrow=false +spring.datasource.testOnReturn=false +spring.datasource.poolPreparedStatements=false + +mybatis.configuration.map-underscore-to-camel-case=true + +quartz.cron.clean.global=0 */10 * * * ? + +pagehelper.helperDialect=mysql +pagehelper.reasonable=true +pagehelper.supportMethodsArguments=true +pagehelper.params=count=countSql +pagehelper.returnPageInfo=check diff --git a/src/main/resources/rules/hello.drl b/src/main/resources/rules/hello.drl new file mode 100644 index 0000000..3bc277d --- /dev/null +++ b/src/main/resources/rules/hello.drl @@ -0,0 +1,134 @@ +package rules +import vip.xumy.drools.pojo.CDR +import vip.xumy.drools.pojo.RuleSink + +import java.util.ArrayList; +import java.util.LinkedList; + +//global java.lang.Integer count; +//global java.util.LinkedList sink; + + + +declare CDR + @role(event) + @timestamp(createTime) + @expires(15s) + //@duration(duration) +end + + + + +/* +rule "test002" + enabled false + when + accumulate(CDR(msgType == 2) over window:time(1s), $cnt:count()) + then + //System.out.println("match rule test002, count = " + $cnt); +end + + +rule "test003" + enabled true + when + $al : ArrayList() from collect(CDR(msgType == 2) over window:time(5s)) + then + //count++; + //System.out.println("match rule " + drools.getRule().getName() + " count = " + $al.size()); +end + +rule "test004" + enabled true + when + $b : CDR() over window:time(5s) + $a : CDR(imsi==$b.imsi, this after $b) + then + //System.out.println("match rule " + drools.getRule().getName() + "\nevent: " + $a + "\nevent: " + $b); +end + + +rule "test005" + enabled true + when + $b : CDR() + $a : CDR(imsi==$b.imsi, this after $b) + then + //System.out.println("match rule " + drools.getRule().getName() + "\nevent: " + $a + "\nevent: " + $b); +end + +rule "test006" + //no-loop true + //lock-on-active true + enabled true + when + $b : CDR(msgType==3) + //$al : ArrayList(size>1) from collect(CDR(imsi==$b.imsi, this before[1ms, 10s] $b)) + //ArrayList(size>0) from collect(CDR(msgType==45, this before[1ms, 20s] $b)) + exists CDR(msgType==45, imsi==$b.imsi, this before[1ms, 10s] $b) + then + //System.out.println("match rule " + drools.getRule().getName() + "\nevent: " + $a + "\nevent: " + $b); + //System.out.println("match rule " + drools.getRule().getName() + " count = " + $al.size() + " event: " + $b); + //for(int i=0; i<$al.size(); i++) + // System.out.println($al.get(i)); +end + +*/ + +//在10s内,出现不同国家发起的两次位置更新并在此之后有短信行为 +rule "test007" + no-loop true + lock-on-active true + when + $b : CDR(msgType==44||msgType==45||msgType==46) + //accumulate(CDR(msgType==2, imsi==$b.imsi, this before[0ms, 10s] $b, $this:this, $cn:callerCN), $cnt:count($cn), $al:collectList($this)) + accumulate(CDR(msgType==2, imsi==$b.imsi, this before[1ms, 15s] $b, $this:this, $cn:callerCN, $id:id), $cnt:count($cn), $al:collectList($this), $ids:collectList($id)) + eval($cnt > 1) + then + //System.out.println("match rule " + drools.getRule().getName() + " count = " + $al.size() + " event: " + $b); + //for(int i=0; i<$al.size(); i++) + // System.out.println($al.get(i)); + //sink.sink(drools.getRule().getName(), "has many updatelocation from other CN before sm in 20s", $ids); + + //RuleSink ri = new RuleSink($b.getId(), drools.getRule().getName(), "has many updatelocation from other CN before sm in 10s", $ids); + //sink.add(ri); +end + + +/* +//在10s内,出现不同国家发起的两次位置更新并在此之后有短信行为 +rule "test008" + //no-loop true + //lock-on-active true + when + $b : CDR(msgType==2) + //accumulate(CDR(msgType==2, imsi==$b.imsi, this before[0ms, 10s] $b, $this:this, $cn:callerCN), $cnt:count($cn), $al:collectList($this)) + accumulate(CDR(msgType==2, imsi==$b.imsi, this before[1ms, 30s] $b, $this:this, $cn:callerCN, $id:id), $cnt:count($cn), $al:collectList($this), $ids:collectList($id)) + eval($cnt > 1) + //accumulate (CDR(this before[1ms, 10s] $b, msgType==2, imsi==$b.imsi, $this:this), $cnt1:count($this)) + //accumulate (CDR(this before[1ms, 10s] $b, msgType==3, imsi==$b.imsi, $this:this), $cnt2:count($this)) + //eval($cnt1 > 1 && $cnt2 > 1) + then + //System.out.println("match rule " + drools.getRule().getName() + " count = " + $al.size() + " event: " + $b); + //for(int i=0; i<$al.size(); i++) + // System.out.println($al.get(i)); + //sink.sink(drools.getRule().getName(), "has many updatelocation from other CN before sm in 20s", $ids); + + //RuleSink ri = new RuleSink($b.getId(), drools.getRule().getName(), "has many updatelocation from other CN before sm in 10s", $ids); + //sink.add(ri); +end +*/ + + +/* +rule "retract event" +salience -999999 +when + $e: CDR() +then + retract( $e ); +end +*/ + +