总体:

  • 最后发版为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转换而来

rulebook 简单记录相关推荐

  1. python 绘图脚本系列简单记录

    简单记录平时画图用到的python 便捷小脚本 1. 从单个文件输入 绘制坐标系图 #!/usr/bin/python # coding: utf-8 import matplotlib.pyplot ...

  2. ubuntu bind9 配置简单记录

    ubuntu bind9 配置简单记录 ubuntu版本:Ubuntu 12.04.2 bind9安装:apt-get install bind9 bind9配置文件目录:/etc/bind bind ...

  3. 简单记录一下fabric版本1.4的环境搭建,

    简单记录一下fabric版本1.4的环境搭建,运行环境为Ubuntu18.04,其中一些内容是根据官方文档整理的,如有错误欢迎批评指正. 本文只介绍最简单的环境搭建方法,具体的环境搭建解析在这里深入解 ...

  4. oracle 9i 手工建库,简单记录Oracle 9i数据库手工建库过程

    简单记录Oracle 9i数据库手工建库过程Oracle 9i手工建库 By Oracle老菜 今天客户要用oracle 9.2.0.5,aix 6.1已经不支持了,只好从别的数据库把软件拷贝过来重编 ...

  5. mysql signal函数_MySQL:简单记录信号处理

    码版本:5.7.29 简单记录信号如何生效的.poll收到信号后如何中断后如何处理的,需要确认. --- ###一 初始化信号处理方式,设置信号的处理的处理方式,屏蔽某些信号,并且继承到子线程(pth ...

  6. 简单记录双系统安装Ububtu22.04

    简单记录双系统安装Ububtu22.04 tag: #Linux #Ubuntu 双系统安装Ububtu22.04 设备:R9000P 2021 系统:win11 + ubuntu22.04 1.制作 ...

  7. 关于majaro安装后的配置,简单记录 机型华硕FZ53v

    关于majaro安装后的配置,简单记录 机型华硕FZ53v 关于majaro安装后的配置,简单记录 机型华硕FZ53v 关于majaro安装后的配置,简单记录 机型华硕FZ53v ##关于v2ray配 ...

  8. 简单记录下几家公司的面试经历(Java一年经验)

    一年经验,记录下最近几家公司的面试经历. 1.深圳缇铭科技有限公司 1)先让自我介绍,讲一下最近的项目 根据项目提问,比如: redis你是如何部署的?你的code是直接套用他们的模板去编写,还是自己 ...

  9. git版本回退简单记录

    简单记录git版本回退的命令,参考的是这篇文章1 首先查看以前存档的版本: git log 1. 知道要回退的版本和现在的版本差了多少代 回退上一代版本(1个以前) git reset –hard H ...

最新文章

  1. Snmp在Windows下的实现----WinSNMP编程原理
  2. Tungsten Fabric SDN — VNC API — API Server 的 API Specification
  3. 成功解决SyntaxError: (unicode error) ‘unicodeescape‘ codec can‘t decode bytes in position 6-7: malformed
  4. yamlcpp遍历_OpenCV文件输入和输出使用XML和YAML文件
  5. VirtualBox中的Linux读取Windows共享目录
  6. 【MSDN文摘】使用自定义验证组件库扩展 Windows 窗体: Form Scope
  7. internet网络 checksum校验和计算方法
  8. 解决:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal
  9. 趣图:嫁人就嫁程序员,大妈都懂的!
  10. 未找到“SocialiteProviders \ Manager \ ServiceProvider”类
  11. 沪深股市股票交易规则
  12. 2018年阿里巴巴重要开源项目汇总(持续更新中)
  13. FAF世链区块链大会|DarkHorse商学院院长何沐庭:看好DeFi的未来
  14. atoi atol实现
  15. php 把数字转化为大写中文(完善版)
  16. 手机录屏并转换成gif动图
  17. C# 监控笔记本/平板的充电/电源状态
  18. 通过keil使用汇编语言生成二进制文件,并使用vivado仿真cortexm0处理器
  19. 平安科技王健宗:所有AI前沿技术,都能在联邦学习中大展身手
  20. 卷积神经网络(LeNet)——【torch学习笔记】

热门文章

  1. DES与3DES加密C++实现
  2. 图片流转base64遇到的坑
  3. 深度学习相关概念:交叉熵损失
  4. 记一次ThinkStation上Centos显卡驱动的大坑
  5. 团体程序设计天梯赛 L2-016. 愿天下有情人都是失散多年的兄妹
  6. 副高级职称计算机考试内容
  7. 歌手阿正回应《楚汉传奇》剧组质疑
  8. Android的学习之旅
  9. pv添加入vG和VG中删除pv
  10. android - 图片压缩,防止崩溃OOM