Browse Source

init

master
许孟阳 2 years ago
commit
eab23f8499
  1. 6
      .gitignore
  2. 3
      README.md
  3. 8
      application.properties
  4. 46
      logback.xml
  5. 146
      pom.xml
  6. 14
      src/main/java/vip/xumy/drools/DroolsApplocation.java
  7. 150
      src/main/java/vip/xumy/drools/action/CdrGenerator.java
  8. 118
      src/main/java/vip/xumy/drools/conf/DroolsConfig.java
  9. 20
      src/main/java/vip/xumy/drools/conf/DroolsInitializer.java
  10. 24
      src/main/java/vip/xumy/drools/ctrl/CdrRuleController.java
  11. 51
      src/main/java/vip/xumy/drools/pojo/CDR.java
  12. 51
      src/main/java/vip/xumy/drools/pojo/DroolsBurster.java
  13. 23
      src/main/java/vip/xumy/drools/pojo/RuleSink.java
  14. 28
      src/main/java/vip/xumy/drools/service/CdrRuleService.java
  15. 39
      src/main/java/vip/xumy/drools/service/DroolsApiService.java
  16. 28
      src/main/resources/application.properties
  17. 134
      src/main/resources/rules/hello.drl

6
.gitignore vendored

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
/.classpath
/.project
/.settings
/bin/
/logs
/target

3
README.md

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
# drools demo
SpringBoot集成drools测试demo项目

8
application.properties

@ -0,0 +1,8 @@ @@ -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

46
logback.xml

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="D:/logs/drools" />
<!--控制台日志, 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度,%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!--文件日志, 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/drools-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<logger name="vip.xumy" level="DEBUG"/>
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE"/>
</root>
</configuration>

146
pom.xml

@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
</parent>
<groupId>vip.xumy.drools</groupId>
<artifactId>xumy_drools</artifactId>
<version>0.0.0</version>
<name>drools</name>
<description>xumy-drools</description>
<packaging>jar</packaging>
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<core.version>1.0.0</core.version>
<log4j.version>1.2.17</log4j.version>
<fastjson.version>1.2.46</fastjson.version>
<druid.version>1.1.9</druid.version>
<mybatis-plus.version>3.5.1</mybatis-plus.version>
<mybatis.pagehelper.version>1.4.6</mybatis.pagehelper.version>
<drools.version>7.74.1.Final</drools.version>
<kie.spring.version>7.74.1.Final</kie.spring.version>
</properties>
<dependencies>
<dependency>
<groupId>vip.xumy.core</groupId>
<artifactId>xumy_core</artifactId>
<version>${core.version}</version>
</dependency>
<!-- 代码修改之后可以实时生效,该模块在完整的打包环境下运行的时候会被禁用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<!-- 单元测试不使用Junit4,使用Junit5 -->
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--junit 测试包-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<!-- mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- alibaba的druid数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- mybatis plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- mybatis的pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${mybatis.pagehelper.version}</version>
</dependency>
<!--drools规则引擎-->
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-core</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-compiler</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.drools</groupId>
<artifactId>drools-templates</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-api</artifactId>
<version>${drools.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>${drools.version}</version>
</dependency>
</dependencies>
<!-- Package as an executable jar -->
<build>
<finalName>drools</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</project>

14
src/main/java/vip/xumy/drools/DroolsApplocation.java

@ -0,0 +1,14 @@ @@ -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);
}
}

150
src/main/java/vip/xumy/drools/action/CdrGenerator.java

@ -0,0 +1,150 @@ @@ -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<CDR> 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));
}
}

118
src/main/java/vip/xumy/drools/conf/DroolsConfig.java

@ -0,0 +1,118 @@ @@ -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();
}
}

20
src/main/java/vip/xumy/drools/conf/DroolsInitializer.java

@ -0,0 +1,20 @@ @@ -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);
}
}

24
src/main/java/vip/xumy/drools/ctrl/CdrRuleController.java

@ -0,0 +1,24 @@ @@ -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);
}
}

51
src/main/java/vip/xumy/drools/pojo/CDR.java

@ -0,0 +1,51 @@ @@ -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");
// }
}

51
src/main/java/vip/xumy/drools/pojo/DroolsBurster.java

@ -0,0 +1,51 @@ @@ -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();
}
}

23
src/main/java/vip/xumy/drools/pojo/RuleSink.java

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
package vip.xumy.drools.pojo;
import java.util.List;
public class RuleSink {
String ruleName;
String ruleInfo;
Long trapId;
List<Long> cdrIDs;
public RuleSink(Long trapId, String ruleName, String ruleInfo, List<Long> 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);
}
}

28
src/main/java/vip/xumy/drools/service/CdrRuleService.java

@ -0,0 +1,28 @@ @@ -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();
}
}

39
src/main/java/vip/xumy/drools/service/DroolsApiService.java

@ -0,0 +1,39 @@ @@ -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);
}
}

28
src/main/resources/application.properties

@ -0,0 +1,28 @@ @@ -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

134
src/main/resources/rules/hello.drl

@ -0,0 +1,134 @@ @@ -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<RuleSink> 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
*/
Loading…
Cancel
Save