rulebook 简单记录

总体:

  • 最后发版为2018年
  • 相比EASY RULE,不支持jexl等脚本语言
  • 支持Spring
  • 内部执行都是使用jdk proxy模式,无论是annotation还是builder模式
  • 可以使用CoRRuleBook 实现chain模式,在chain内按order进行执行
  • 一个rule里面可以有多个action(@Then),多个fact(@Given),多个condition(@When),但注意When只有一个会执行
  • 支持将一个java package的所有rule类组成一个Chain-CoRRuleBook
  • 支持audit

核心概念

Much like the Given-When-Then language for defining tests that was popularized by BDD, RuleBook uses a Given-When-Then language for defining rules. The RuleBook Given-When-Then methods have the following meanings.

  • Given some Fact(s)
  • When a condition evaluates to true
  • Then an action is triggered

核心类及示意代码

rule执行类:GoldenRule

/**
A standard implementation of {@link Rule}.
@param the fact type
@param the Result type
*/
public class GoldenRule<T, U> implements Rule<T, U> {

action 识别代码

public List<Object> getActions() {if (_rule.getActions().size() < 1) {List<Object> actionList = new ArrayList<>();for (Method actionMethod : getAnnotatedMethods(Then.class, _pojoRule.getClass())) {actionMethod.setAccessible(true);Object then = getThenMethodAsBiConsumer(actionMethod).map(Object.class::cast).orElse(getThenMethodAsConsumer(actionMethod).orElse(factMap -> { }));actionList.add(then);}_rule.getActions().addAll(actionList);}return _rule.getActions();
}

condition 设置和获取,可以手工指定condition 如:auditableRule.setCondition(condition);
如果没有设置,使用如下代码识别

@Override
@SuppressWarnings("unchecked")
public Predicate<NameValueReferableMap> getCondition() {//Use what was set by then() first, if it's thereif (_rule.getCondition() != null) {return _rule.getCondition();}//If nothing was explicitly set, then convert the method in the class_rule.setCondition(Arrays.stream(_pojoRule.getClass().getMethods()).filter(method -> method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class).filter(method -> Arrays.stream(method.getDeclaredAnnotations()).anyMatch(When.class::isInstance)).findFirst()

注意findFirst,代表只有一个生效

Chain 管理类 CoRRuleBook 使用Reflections 识别package下所有rule类的核心代码如下:

/*** Gets the POJO Rules to be used by the RuleBook via reflection of the specified package.* @return  a List of POJO Rules*/protected List<Class<?>> getPojoRules() {Reflections reflections = new Reflections(_package);List<Class<?>> rules = reflections.getTypesAnnotatedWith(com.deliveredtechnologies.rulebook.annotation.Rule.class).stream().filter(rule -> _package.equals(rule.getPackage().getName())) // Search only within package, not subpackages.filter(rule -> rule.getAnnotatedSuperclass() != null) // Include classes only, exclude interfaces, etc..collect(Collectors.toList());rules.sort(comparingInt(aClass ->getAnnotation(com.deliveredtechnologies.rulebook.annotation.Rule.class, aClass).order()));return rules;}

Fact管理

/*** A Fact is a single piece of data that can be supplied to a {@link Rule}.* Facts are not immutable; they may be changed by rules and used to derive a result state.*/
public class Fact<T> implements NameValueReferable<T> {private String _name;private T _value;/*** A FactMap decorates {@link Map}; it stores facts by their name and provides convenience methods for* accessing {@link Fact} objects.*/
public class FactMap<T> implements NameValueReferableMap<T> {private Map<String, NameValueReferable<T>> _facts;public FactMap(Map<String, NameValueReferable<T>> facts) {_facts = facts;}

实际上有点key重复的感觉,每个fact 本身还有name和value

Then/action 的执行核心代码 在goldenRule里面

//invoke the actionStream.of(action.getClass().getMethods()).filter(method -> method.getName().equals("accept")).findFirst().ifPresent(method -> {try {method.setAccessible(true);method.invoke(action,ArrayUtils.combine(new Object[]{new TypeConvertibleFactMap<>(usingFacts)},new Object[]{getResult().orElseGet(() -> result)},method.getParameterCount()));if (result.getValue() != null) {_result = result;}} catch (IllegalAccessException | InvocationTargetException err) {LOGGER.error("Error invoking action on " + action.getClass(), err);if (_actionType.equals(ERROR_ON_FAILURE)) {throw err.getCause() == null ? new RuleException(err) :err.getCause() instanceof RuleException ? (RuleException)err.getCause() :new RuleException(err.getCause());}}});facts.putAll(usingFacts);
}

多fact示意

fact 通过@Given进行命名

@Rule
public class HelloWorld {@Given("hello")private String hello;@Given("world")private String world;

然后复制

facts.setValue("hello", "Hello");
facts.setValue("world", "World");

Spring 使用

@Configuration
@ComponentScan("com.example.rulebook.helloworld")
public class SpringConfig {
@Bean
public RuleBook ruleBook() {
RuleBook ruleBook = new SpringAwareRuleBookRunner("com.example.rulebook.helloworld");
return ruleBook;
}
}

扩展

可以扩展rule类,参考RuleAdapter

public RuleAdapter(Object pojoRule, Rule rule) throws InvalidClassException {com.deliveredtechnologies.rulebook.annotation.Rule ruleAnnotation =getAnnotation(com.deliveredtechnologies.rulebook.annotation.Rule.class, pojoRule.getClass());if (ruleAnnotation == null) {throw new InvalidClassException(pojoRule.getClass() + " is not a Rule; missing @Rule annotation");}_actionType = ruleAnnotation.ruleChainAction();_rule = rule == null ? new GoldenRule(Object.class, _actionType) : rule;_pojoRule = pojoRule;
}

扩展RuleBook(The RuleBook interface for defining objects that handle the behavior of rules chained together.)

/*** Creates a new RuleBookRunner using the specified package and the supplied RuleBook.* @param ruleBookClass the RuleBook type to use as a delegate for the RuleBookRunner.* @param rulePackage   the package to scan for POJO rules.*/public RuleBookRunner(Class<? extends RuleBook> ruleBookClass, String rulePackage) {super(ruleBookClass);_prototypeClass = ruleBookClass;_package = rulePackage;}

当然chain类也可以自己写。

其它

使用predicate的test 来判断condition 来
boolean test(T t)
Evaluates this predicate on the given argument.
Parameters:
t - the input argument
Returns:
true if the input argument matches the predicate, otherwise false

使用isAssignableFrom 来判断输入的fact 是否满足rule类里面的定义
isAssignableFrom是用来判断子类和父类的关系的,或者接口的实现类和接口的关系的,默认所有的类的终极父类都是
Object。如果
A.isAssignableFrom(B)结果是true,证明
B可以转换成为
A,也就是
A可以由
B转换而来

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/4054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity 调用C++ dll 操作升级套娃函数调用

之前一直以为C生成dll&#xff0c;在unity中调用时要把传出去的值设置在主函数中&#xff0c;以参数或反回值的形式。 当然在DLL工程中可以说没有主函数&#xff0c;那个可以运行一个函数&#xff0c;其会调用其他函数从而一直调其他相关函数。 那问题是在层级是二或三------…

前端工程中的设计模式应用

本文旨在系统性介绍一下23种设计模式&#xff0c;给出通俗易懂的案例、结构图及代码示例&#xff0c;这也是我自身学习理解的过程。或许其中的几种设计模式写的并不是很清晰明了易懂&#xff0c;更详细的可根据提到的参考文献进行深入学习。 什么是设计模式 设计模式这个概念是…

Java解决new date出现的时区问题(差8小时)

1、设置当前时区 SimpleDateFormat format new SimpleDateFormat("yyyy/MM/dd"); format.setTimeZone(TimeZone.getTimeZone("GMT8:00")); 2、设置全局时区 创建一个全局配置类&#xff0c;用于配置项目全局时区。 这样就不用专门在各个地方设置时区了…

干货!3个技巧让你轻松增强客户实时聊天的体验感

在当今竞争激烈的商业环境中&#xff0c;提供出色的客户服务成为企业成功的关键要素之一。尤其是在实时聊天平台上&#xff0c;为客户提供优质的体验感&#xff0c;对于建立良好的客户关系和提高销售转化率至关重要。如果你还在苦恼如何增强用户体验感&#xff0c;苦恼如何增加…

剑指offer刷题笔记--Num51-60

1--数组中的逆序对&#xff08;51&#xff09; 主要思路&#xff1a; 基于归并排序&#xff0c;视频讲解参考&#xff1a;数组中的逆序对 #include <iostream> #include <vector>class Solution { public:int reversePairs(std::vector<int>& nums) {if(…

iOS-Block

Blocks的学习 Block的分类 Block根据其类型可以分为三类&#xff1a; 全局Block&#xff08;NSGlobalBlock&#xff09;栈Block&#xff08;NSMallocBlock&#xff09;堆Block&#xff08;NSStackBlock&#xff09; 而其区分的规则为&#xff1a; 如果没有引用局部变量&…

arping命令 ip地址冲突检测 根据ip查mac地址

arping命令介绍 arping 命令主要用来获取ip对应的mac地址&#xff0c;更新本地arp缓存表。平时主要用来探测ip地址是否冲突即同一个网络里&#xff0c;同一个ip不同mac地址的情况。ip地址冲突将导致网络故障。 arping常用命令参数 arping [参数] ip -U 强制更新邻近主机的a…

记一场面试中遇到的问题

第一题&#xff1a; 简单的字符串拆分、组合的题目。本来题目是很简单&#xff0c;但是里面的一些细节自己没有考虑周全&#xff0c;和面试官在这道题目上讨论了一段时间。后来发现自己把自己差点绕迷糊了&#xff0c;多亏面试官及时提醒。关于技术上的问题还是应该多和别人讨…

关于电脑显示器屏幕看不出灰色,灰色和白色几乎一样无法区分,色彩调整方法

问题&#xff1a; 电脑显示器屏幕看不出灰色&#xff0c;灰色和白色几乎一样无法区分。白色和灰色有色差。 解决方法&#xff1a; 打开“控制面板” ->“色彩管理” ->“高级” ->“校正显示器” 在下一步调节中调成中间这一个实例的样子就可以了 进行微调&#x…

【hadoop】部署hadoop全分布模式

hadoop全分布模式 全分布模式特点部署全分布模式准备工作正式配置hadoop-env.shhdfs-site.xmlcore-site.xmlmapred-site.xmlyarn-site.xmlslaves对NameNode进行格式化复制到另外两台虚拟机启动 对部署是否成功进行测试 全分布模式特点 真正的分布式环境&#xff0c;用于生产具…

【Vue】day02-Vue基础入门

目录 day02 一、今日学习目标 1.指令补充 2.computed计算属性 3.watch侦听器 4.综合案例 &#xff08;演示&#xff09; 二、指令修饰符 1.什么是指令修饰符&#xff1f; 2.按键修饰符 3.v-model修饰符 4.事件修饰符 三、v-bind对样式控制的增强-操作class 1.语法…

边缘检测之loG算子

note // 边缘检测之loG算子&#xff1a;对高斯函数求二阶导数 // G(x,y) exp(-1 * (x*x y*y) / 2 / sigma / sigma) // loG(x,y) ((x*x y*y - 2 * sigma * sigma) / (sigma^4)) * exp(-1 * (x*x y*y) / 2 / sigma /sigma) /* [ 0,0,-1,0,0; 0,-1,-2,-1,0; -1,-2,16,-2…

uni-app实现emoj表情包发送(nvue版)

uni-app实现表情包发送&#xff0c; vue实现思路直接使用grideview网格布局加载emoj表情包即可实现&#xff0c;很简单&#xff0c;但是nvue稍微复杂&#xff0c;这里采用的方案是nvue提供的组件list 看效果 代码 <template><view style"margin-right: 10rpx;m…

Elasticsearch集群状态灯代表含义

了解指示灯状态之前需要先了解下什么是分片和副本。 Sharing(分片、水平扩展) 比如我们的ES集群是3节点的,每个节点最多只能存放300G的文档。当前我们有个大索引有900G,就可以进行分片拆分成3个小索引,每个节点300G,如果我们有10个节点就一个就可以存放一个3T的大索引。…

【Rust 基础篇】Rust Deref Trait 的使用

导言 在 Rust 中&#xff0c;Deref trait 是一种特殊的 trait&#xff0c;用于重载解引用操作符 *。通过实现 Deref trait&#xff0c;我们可以定义类型的解引用行为&#xff0c;使其在使用 * 运算符时表现得像引用类型。 本篇博客将详细介绍 Rust 中如何实现和使用 Deref tr…

C++的static、this和final关键字介绍

C的static、this和final关键字介绍 ☆static关键字&#xff1a;static可以用于不同的上下文&#xff0c;其主要作用如下&#xff1a; 在类中&#xff0c;static成员表示类的静态成员&#xff0c;即属于整个类而不是类的实例。静态成员可以被所有该类的对象所共享&#xff0c;且…

如何使用自有数据微调ChatGLM-6B

构建自己的数据集 数据格式&#xff1a;问答对 官网例子 ADGEN 数据集任务为根据输入&#xff08;content&#xff09;生成一段广告词&#xff08;summary&#xff09;。 { "content": "类型#上衣*版型#宽松*版型#显瘦*图案#线条*衣样式#衬衫*衣袖型#泡泡袖…

3.8 Bootstrap 面包屑导航(Breadcrumbs)

文章目录 Bootstrap 面包屑导航&#xff08;Breadcrumbs&#xff09; Bootstrap 面包屑导航&#xff08;Breadcrumbs&#xff09; 面包屑导航&#xff08;Breadcrumbs&#xff09;是一种基于网站层次信息的显示方式。以博客为例&#xff0c;面包屑导航可以显示发布日期、类别或…

Stable Diffusion + EbSynth + ControlNet 解决生成视频闪烁

一、安装 1.1、安装ffmpeg 下载地址&#xff1a; 解压&#xff0c;配置环境变量 E:\AI\ffmpeg\bin 检查是否安装成功 1.2、安装SD的 EbSynth 插件 插件地址 https://github.com/s9roll7/ebsynth_utility 报错&#xff1a;ModuleNotFoundError: No module named extension…

【广州华锐互动】AR远程巡检系统在设备维修保养中的作用

随着科技的不断发展&#xff0c;AR(增强现实)远程巡检系统在设备检修中发挥着越来越重要的作用。这种系统可以将AR技术与远程通信技术相结合&#xff0c;实现对设备检修过程的实时监控和远程指导&#xff0c;提高设备检修的效率和质量。 首先&#xff0c;AR远程巡检系统可以帮助…