commit
eab23f8499
17 changed files with 889 additions and 0 deletions
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
/.classpath |
||||
/.project |
||||
/.settings |
||||
/bin/ |
||||
/logs |
||||
/target |
@ -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 |
||||
|
@ -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> |
@ -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> |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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)); |
||||
} |
||||
|
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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");
|
||||
// }
|
||||
|
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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 |
@ -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…
Reference in new issue