国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

php網(wǎng)站開(kāi)發(fā)文檔模板關(guān)鍵詞搜索優(yōu)化公司

php網(wǎng)站開(kāi)發(fā)文檔模板,關(guān)鍵詞搜索優(yōu)化公司,php做網(wǎng)站有哪些優(yōu)點(diǎn),單網(wǎng)頁(yè)網(wǎng)站 企業(yè)文章目錄 簡(jiǎn)介pom 規(guī)則抽象規(guī)則Rule基礎(chǔ)規(guī)則BasicRule事實(shí)類Facts:map條件接口動(dòng)作接口 四種規(guī)則定義方式注解方式RuleBuilder 鏈?zhǔn)組vel和Spel表達(dá)式Y(jié)ml配置 常用規(guī)則類DefaultRuleSpELRule(Spring的表達(dá)式注入) 組合規(guī)則UnitRuleGroup 規(guī)則引…

文章目錄

  • 簡(jiǎn)介
      • pom
  • 規(guī)則
      • 抽象規(guī)則Rule
      • 基礎(chǔ)規(guī)則BasicRule
          • 事實(shí)類Facts:map
          • 條件接口
          • 動(dòng)作接口
      • 四種規(guī)則定義方式
          • 注解方式
          • RuleBuilder 鏈?zhǔn)?/li>
          • Mvel和Spel表達(dá)式
          • Yml配置
      • 常用規(guī)則類
          • DefaultRule
          • SpELRule(Spring的表達(dá)式注入)
      • 組合規(guī)則
          • UnitRuleGroup
  • 規(guī)則引擎
      • 引擎接口
      • 引擎抽象類
      • 引擎類-DefaultRulesEngine
          • 規(guī)則引擎參數(shù)(決定規(guī)則之間是否互斥|中斷|跳過(guò)等)
  • 實(shí)戰(zhàn)
      • 場(chǎng)景1- 恒打印
          • 規(guī)則description
          • 規(guī)則
          • 規(guī)則引擎:使用DefaultRulesEngine
          • 執(zhí)行
          • fire方法執(zhí)行流程
      • 場(chǎng)景2-yml
      • 場(chǎng)景3 簡(jiǎn)單if-else
      • 場(chǎng)景4-動(dòng)態(tài)規(guī)則MVEL表達(dá)式+Json字符串
      • 場(chǎng)景5-QLExpress
      • 場(chǎng)景6- 動(dòng)態(tài)規(guī)則Mvel + Json文件
      • 場(chǎng)景7-履約缺貨處罰金額計(jì)算

簡(jiǎn)介

1、是什么

  • 基于java輕量級(jí)的規(guī)則引擎,學(xué)習(xí)成本更低、適用性更強(qiáng)
  • 本質(zhì)一個(gè)函數(shù),y=f(x1,x2,…,xn)
  • Easy Rules 每條規(guī)則都有一個(gè)條件(condition)和一個(gè)動(dòng)作(action),簡(jiǎn)單地說(shuō),可以將其看作是一組 IF THEN 或類似SQL的when-then語(yǔ)句

2、作用

  • 解決業(yè)務(wù)代碼和業(yè)務(wù)規(guī)則分離,實(shí)現(xiàn)了將業(yè)務(wù)決策從應(yīng)用程序代碼中分離。 接受數(shù)據(jù)輸入,解釋業(yè)務(wù)規(guī)則,并根據(jù)業(yè)務(wù)規(guī)則做出業(yè)務(wù)決策。

業(yè)務(wù)系統(tǒng)在應(yīng)用過(guò)程中,常常包含著要處理"復(fù)雜、多變"的部分,這部分往往是"業(yè)務(wù)規(guī)則"或者是"數(shù)據(jù)的處理邏輯"。因此這部分的動(dòng)態(tài)規(guī)則的問(wèn)題,往往需要可配置,并對(duì)系統(tǒng)性能和熱部署有一定的要求。從開(kāi)發(fā)與業(yè)務(wù)的視角主要突出以下的一些問(wèn)題:

  • 從開(kāi)發(fā)人員視角來(lái)看

1)邏輯復(fù)雜,要使用大量if-else來(lái)實(shí)現(xiàn),或者使用設(shè)計(jì)模式。但過(guò)于復(fù)雜的規(guī)則邏輯,使用設(shè)計(jì)模式也往往是存在大量并且關(guān)系復(fù)雜的類,導(dǎo)致代碼難于維護(hù),對(duì)新加入的同學(xué)極不友好。

2)變更時(shí)需要從頭梳理邏輯,在適當(dāng)?shù)牡胤竭M(jìn)行if…else…代碼邏輯調(diào)整,耗費(fèi)大量時(shí)間進(jìn)行梳理。

3)開(kāi)發(fā)周期較長(zhǎng),當(dāng)需求發(fā)生變更時(shí),需要研發(fā)人員安排開(kāi)發(fā)周期上線,對(duì)于當(dāng)下快速變化的業(yè)務(wù),傳統(tǒng)的開(kāi)發(fā)工作方式顯得捉襟見(jiàn)肘。

  • 從業(yè)務(wù)人員視角來(lái)看

1)業(yè)務(wù)人員期望友好的管理界面,不需要專業(yè)的開(kāi)發(fā)技能就能夠完成規(guī)則的管理、發(fā)布。

2)期望能夠?qū)崿F(xiàn)熱部署,由業(yè)務(wù)人員配置好之后即配即用。

3)減少業(yè)務(wù)規(guī)則對(duì)開(kāi)發(fā)人員的依賴。

4)降低需求變動(dòng)的時(shí)間成本,快速驗(yàn)證發(fā)布

3、怎么做:

你可以自己構(gòu)建一個(gè)簡(jiǎn)單的規(guī)則引擎。你所需要做的就是創(chuàng)建一組帶有條件和動(dòng)作的規(guī)則對(duì)象rule,將它們存儲(chǔ)在一個(gè)集合中rules,然后遍歷它們以評(píng)估(fire)條件(condition)并執(zhí)行這些動(dòng)作(action)。

pom

<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-core</artifactId><version>3.3.0</version>
</dependency><!--規(guī)則定義文件格式,支持json,yaml等-->
<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-support</artifactId><version>3.3.0</version>
</dependency><!--支持mvel規(guī)則語(yǔ)法庫(kù)-->
<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-mvel</artifactId><version>3.3.0</version>
</dependency><!-- https://mvnrepository.com/artifact/org.jeasy/easy-rules-spel -->
<dependency><groupId>org.jeasy</groupId><artifactId>easy-rules-spel</artifactId><version>4.1.0</version>
</dependency>

規(guī)則

大多數(shù)業(yè)務(wù)規(guī)則可以由以下定義表示:

  • 名稱name:規(guī)則命名空間中的唯一規(guī)則名稱

  • 說(shuō)明description:規(guī)則的簡(jiǎn)要說(shuō)明

  • 優(yōu)先級(jí)priority:相對(duì)于其他規(guī)則的規(guī)則優(yōu)先級(jí),較小的值表示較高的優(yōu)先級(jí)

  • 事實(shí)fact:去匹配規(guī)則時(shí)的一組已知事實(shí)

  • 條件condition:為了匹配該規(guī)則,在給定某些事實(shí)的情況下應(yīng)滿足的一組條件

    如果規(guī)則條件為true,則規(guī)則將被觸發(fā)執(zhí)行。否則,規(guī)則將被忽略

  • 動(dòng)作action:當(dāng)條件滿足時(shí)要執(zhí)行的一組動(dòng)作(可以添加/刪除/修改事實(shí))

    它可以用于實(shí)現(xiàn)各種應(yīng)用程序邏輯,例如更新數(shù)據(jù)、發(fā)送消息等。

抽象規(guī)則Rule

public interface Rule extends Comparable<Rule> {String DEFAULT_NAME = "rule";String DEFAULT_DESCRIPTION = "description";int DEFAULT_PRIORITY = 2147483646;boolean evaluate(Facts var1);void execute(Facts var1) throws Exception;
}

基礎(chǔ)規(guī)則BasicRule

package org.jeasy.rules.core;import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rule;public class BasicRule implements Rule {protected String name;//名稱protected String description;//說(shuō)明protected int priority;//優(yōu)先/*** 此方法封裝規(guī)則的條件(conditions)** @param facts :事實(shí)* @return 如果提供的事實(shí)適用于該規(guī),則條件返回true*/public boolean evaluate(Facts facts) {return false;}/*** 此方法封裝規(guī)則的操作(actions)* evaluate方法值為T(mén)RUE才能觸發(fā)execute方法(在滿足規(guī)則條件時(shí)應(yīng)執(zhí)行的操作)。* @throws 如果在執(zhí)行過(guò)程中發(fā)生錯(cuò)誤將拋出Exception*/public void execute(Facts facts) throws Exception {}}
事實(shí)類Facts:map
package org.jeasy.rules.api;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;public class Facts implements Iterable<Map.Entry<String, Object>> {private Map<String, Object> facts = new HashMap();public Object put(String name, Object fact) {Objects.requireNonNull(name);return this.facts.put(name, fact);}public Object remove(String name) {Objects.requireNonNull(name);return this.facts.remove(name);}public <T> T get(String name) {Objects.requireNonNull(name);return this.facts.get(name);}
}
  • 擴(kuò)展:可以將普通對(duì)象(包含屬性|方法)facts.put()。也可以將rpc對(duì)象put進(jìn)來(lái)
@Resource
private MqService mqService;facts.put("mqService", mqService)這樣condition方法就可以使用mqService的方法
.when("mqService.doRuleConditions(conditionList,tmpParam)")@Override
public boolean evaluate(@Facts("mqService") MqService mqService) {mqService.doRuleConditions();
}
條件接口
public interface Condition {Condition FALSE = new Condition() {public boolean evaluate(Facts facts) {return false;}};Condition TRUE = new Condition() {public boolean evaluate(Facts facts) {return true;}};boolean evaluate(Facts var1);
}
動(dòng)作接口
public interface Action {void execute(Facts var1) throws Exception;
}

四種規(guī)則定義方式

注解方式

1、eg1(也可以實(shí)現(xiàn)Rule接口)

package com.mjp.easyrules.drmo1;import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.core.BasicRule;public class MyRule extends BasicRule {@Overridepublic boolean evaluate(Facts facts) {return false;}@Overridepublic void execute(Facts facts) throws Exception {}
}

2、純注解

@Rule(name = "weather rule", description = "if it rains then take an umbrella", priority = 777)
public class WeatherRule {@Conditionpublic boolean itRains(@Fact("rain") boolean rain, @Fact("other") String other) {return rain;}@Action(order = 1)public void takeAnUmbrella() {System.out.println("It rains, take an umbrella!");}@Action(order = 2)public void then2(Facts facts) throws Exception {//my actions2}
}
RuleBuilder 鏈?zhǔn)?/h6>

1、eg1

Rule rule = new RuleBuilder().name("myRule").description("myRuleDescription").priority(2).when(facts -> true).then(facts -> {// do Action1}).then(facts -> {// do Action2}).build();

2、eg2

Rule weatherRule = new RuleBuilder().name("weather rule").description("if it rains then take an umbrella").when(facts -> facts.get("rain").equals(true)).then(facts -> System.out.println("It rains, take an umbrella!")).build();
Mvel和Spel表達(dá)式

1、eg1:Mvel表達(dá)式

Mvel表達(dá)式

Rule weatherRule = new MVELRule().name("weather rule").description("if it rains then take an umbrella").when("rain == true").then("System.out.println(\"It rains, take an umbrella!\");");
  • when:對(duì)象屬性

when方法參數(shù),只能是facts對(duì)象中key對(duì)象,內(nèi)部定義的屬性或方法

.when("person.age > 18")
.when("person.isHappy() == true") 
也可以是類的靜態(tài)方法
Demo.add(1,2)//這樣when會(huì)執(zhí)行去調(diào)用類方法add

2、補(bǔ)充:

  • when、then內(nèi)容,可以從自定義的json文件中讀取并解析成Mvel表達(dá)式形式。解析過(guò)程可參考場(chǎng)景6

3、eg2:Spel表達(dá)式同理

Spel表達(dá)式

Yml配置

eg1: weather-rule.yml

name: "weather rule"
description: "if it rains then take an umbrella"
condition: "true"
actions:- "System.out.println(\"It rains, take an umbrella!\");"
  • condition:對(duì)象方法
condition: "person.isAdult() == false"
condition: "person.getResult(person.getQualifications())"

eg2:一個(gè)yml文件創(chuàng)建多個(gè)規(guī)則

---
name: adult rule
description: when age is greater than 18, then mark as adult
priority: 1
condition: "person.age > 18"
actions:- "person.setAdult(true);"---
name: weather rule
description: when it rains, then take an umbrella
priority: 2
condition: "rain == true"
actions:- "System.out.println("It rains, take an umbrella!");"
  • 讀取多條規(guī)則
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());Rule weatherRule = ruleFactory.createRule(new FileReader("D:\\CodeBetter\\src\\main\\resources\\weather-rule.yml"));
// 多條規(guī)則
Rules rules = ruleFactory.createRules(new FileReader("rules.yml"));

常用規(guī)則類

DefaultRule
package org.jeasy.rules.core;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jeasy.rules.api.Action;
import org.jeasy.rules.api.Condition;
import org.jeasy.rules.api.Facts;class DefaultRule extends BasicRule {private Condition condition;//一個(gè)規(guī)則,一個(gè)條件。private List<Action> actions;//一個(gè)規(guī)則,當(dāng)滿足條件時(shí),可以有多個(gè)動(dòng)作public boolean evaluate(Facts facts) {return this.condition.evaluate(facts);}public void execute(Facts facts) throws Exception {Iterator var2 = this.actions.iterator();while(var2.hasNext()) {Action action = (Action)var2.next();action.execute(facts);}}
}
SpELRule(Spring的表達(dá)式注入)

表達(dá)式注入

package org.jeasy.rules.spel;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jeasy.rules.api.Action;
import org.jeasy.rules.api.Condition;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.core.BasicRule;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.ParserContext;public class SpELRule extends BasicRule {private Condition condition;//條件private final List<Action> actions;//動(dòng)作private final ParserContext parserContext;//文本解析private BeanResolver beanResolver;public boolean evaluate(Facts facts) {return this.condition.evaluate(facts);}public void execute(Facts facts) throws Exception {Iterator var2 = this.actions.iterator();while(var2.hasNext()) {Action action = (Action)var2.next();action.execute(facts);}}public SpELRule when(String condition) {this.condition = new SpELCondition(condition, this.parserContext, this.beanResolver);return this;}public SpELRule then(String action) {this.actions.add(new SpELAction(action, this.parserContext, this.beanResolver));return this;}
}
  • when方法-SpELCondition
public class SpELCondition implements Condition {private final ExpressionParser parser;private final Expression compiledExpression;private BeanResolver beanResolver;public SpELCondition(String expression, ParserContext parserContext, BeanResolver beanResolver) {this.parser = new SpelExpressionParser();this.beanResolver = beanResolver;this.compiledExpression = this.parser.parseExpression(expression, parserContext);}public boolean evaluate(Facts facts) {StandardEvaluationContext context = new StandardEvaluationContext();context.setRootObject(facts.asMap());context.setVariables(facts.asMap());if (this.beanResolver != null) {context.setBeanResolver(this.beanResolver);}return (Boolean)this.compiledExpression.getValue(context, Boolean.class);}
}
  • then方法- SpELAction
public class SpELAction implements Action {private static final Logger LOGGER = LoggerFactory.getLogger(SpELAction.class);private final ExpressionParser parser;private final String expression;private final Expression compiledExpression;private BeanResolver beanResolver;public SpELAction(String expression, ParserContext parserContext, BeanResolver beanResolver) {this.parser = new SpelExpressionParser();this.expression = expression;this.beanResolver = beanResolver;this.compiledExpression = this.parser.parseExpression(expression, parserContext);}public void execute(Facts facts) {try {StandardEvaluationContext context = new StandardEvaluationContext();context.setRootObject(facts.asMap());context.setVariables(facts.asMap());if (this.beanResolver != null) {context.setBeanResolver(this.beanResolver);}this.compiledExpression.getValue(context);} catch (Exception var3) {LOGGER.error("Unable to evaluate expression: '" + this.expression + "' on facts: " + facts, var3);throw var3;}}
}

組合規(guī)則

抽象CompositeRule類由一組規(guī)則組成。這是一個(gè)典型地組合設(shè)計(jì)模式的實(shí)現(xiàn)。可以以不同方式觸發(fā)組合規(guī)則。

三種CompositeRule具體子類:

UnitRuleGroup : 要么應(yīng)用所有規(guī)則,要么不應(yīng)用任何規(guī)則(AND邏輯)
ActivationRuleGroup : 它觸發(fā)第一個(gè)適用規(guī)則,并忽略組中的其他規(guī)則(XOR邏輯)
ConditionalRuleGroup : 如果具有最高優(yōu)先級(jí)的規(guī)則計(jì)算結(jié)果為true,則觸發(fā)其余規(guī)則

UnitRuleGroup
  • 規(guī)則1
        Rule weatherRule1 = new MVELRule().name("weather rule1").description("if it rains then move").when("isRain == true").then("System.out.println(\"rule1: It rains, move!\");");
  • 規(guī)則2
@Rule(name = "weather rule2", description = "if it rains then take an umbrella",priority = 777)
public class WeatherRule {@Conditionpublic boolean itRains(@Fact("isRain") boolean isRain) {return isRain;}@Action(order = 1)public void takeAnUmbrella() {System.out.println("rule2: action1-It rains, take an umbrella!");}@Action(order = 2)public void then(Facts facts) throws Exception {System.out.println("rule2: action2-邊打傘,邊聽(tīng)歌");}
}
  • 執(zhí)行
// 1.創(chuàng)建事實(shí)factFacts facts = new Facts();facts.put("isRain", true);// 2.創(chuàng)建規(guī)則1(Mvel形式)Rule weatherRule1 = new MVELRule().name("weather rule1").description("if it rains then move").when("isRain == true").then("System.out.println(\"rule1: It rains, move!\");");// 2.創(chuàng)建規(guī)則1(注解形式)WeatherRule weatherRule2 = new WeatherRule();// 3.創(chuàng)建組合規(guī)則UnitRuleGroup myUnitRuleGroup = new UnitRuleGroup("myUnitRuleGroup", "unit of weatherRule1 and weatherRule2");myUnitRuleGroup.addRule(weatherRule1);myUnitRuleGroup.addRule(weatherRule2);// 4.創(chuàng)建規(guī)則引擎DefaultRulesEngine defaultRulesEngine = new DefaultRulesEngine();// 5.定義RulesRules rules = new Rules();rules.register(myUnitRuleGroup);// 7.執(zhí)行defaultRulesEngine.fire(rules, facts);
  • 輸出
rule2: action1-It rains, take an umbrella!
rule2: action2-邊打傘,邊聽(tīng)歌
rule1: It rains, move!

先輸出規(guī)則2(優(yōu)先級(jí)為777),規(guī)則1(優(yōu)先級(jí)為默認(rèn)值:2147483646),值越小,優(yōu)先級(jí)越高

規(guī)則引擎

引擎接口

public interface RulesEngine {RulesEngineParameters getParameters();List<RuleListener> getRuleListeners();List<RulesEngineListener> getRulesEngineListeners();void fire(Rules var1, Facts var2);Map<Rule, Boolean> check(Rules var1, Facts var2);
}

引擎抽象類

AbstractRuleEngine作用就是抽出多個(gè)引擎類共有的,不需要再各自額外重復(fù)去實(shí)現(xiàn)

引擎類-DefaultRulesEngine

public final class DefaultRulesEngine extends AbstractRuleEngine {private static final Logger LOGGER = LoggerFactory.getLogger(DefaultRulesEngine.class);public void fire(Rules rules, Facts facts) {this.triggerListenersBeforeRules(rules, facts);this.doFire(rules, facts);this.triggerListenersAfterRules(rules, facts);}void doFire(Rules rules, Facts facts) {Iterator var3 = rules.iterator();while(var3.hasNext()) {Rule rule = (Rule)var3.next();String name = rule.getName();int priority = rule.getPriority();if (rule.evaluate(facts)) {this.triggerListenersAfterEvaluate(rule, facts, true);try {this.triggerListenersBeforeExecute(rule, facts);rule.execute(facts);this.triggerListenersOnSuccess(rule, facts);if (this.parameters.isSkipOnFirstAppliedRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstAppliedRule is set");break;}} catch (Exception var8) {this.triggerListenersOnFailure(rule, var8, facts);if (this.parameters.isSkipOnFirstFailedRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstFailedRule is set");break;}}} else {this.triggerListenersAfterEvaluate(rule, facts, false);if (this.parameters.isSkipOnFirstNonTriggeredRule()) {LOGGER.debug("Next rules will be skipped since parameter skipOnFirstNonTriggeredRule is set");break;}}}}public Map<Rule, Boolean> check(Rules rules, Facts facts) {this.triggerListenersBeforeRules(rules, facts);Map<Rule, Boolean> result = this.doCheck(rules, facts);this.triggerListenersAfterRules(rules, facts);return result;}private Map<Rule, Boolean> doCheck(Rules rules, Facts facts) {LOGGER.debug("Checking rules");Map<Rule, Boolean> result = new HashMap();Iterator var4 = rules.iterator();while(var4.hasNext()) {Rule rule = (Rule)var4.next();if (this.shouldBeEvaluated(rule, facts)) {result.put(rule, rule.evaluate(facts));}}return result;}
}
規(guī)則引擎參數(shù)(決定規(guī)則之間是否互斥|中斷|跳過(guò)等)

RulesEngineParameters

skipOnFirstAppliedRule:為true告訴引擎規(guī)則,被觸發(fā)時(shí)跳過(guò)后面的規(guī)則。使用場(chǎng)景是:各個(gè)規(guī)則之間互斥a || b || c || d,如果a為true,則b、c、d不執(zhí)行當(dāng)發(fā)現(xiàn)一個(gè)滿足條件的規(guī)則并執(zhí)行了相關(guān)操作后,便不再繼續(xù)判斷其他規(guī)則skipOnFirstFailedRule:失敗時(shí)跳過(guò)后面的規(guī)則。a && b && c && d,如果a為false,則b、c、d不執(zhí)行skipOnFirstNonTriggeredRule:一個(gè)規(guī)則不會(huì)被觸發(fā)跳過(guò)后面的規(guī)則。如果滿足當(dāng)前的規(guī)則,則執(zhí)行相應(yīng)的操作,直到遇到不滿足條件的規(guī)則為止,并且也不會(huì)對(duì)其他規(guī)則進(jìn)行判斷了
rulePriorityThreshold:如果優(yōu)先級(jí)超過(guò)定義的閾值,則跳過(guò)下一個(gè)規(guī)則。版本3.3已經(jīng)不支持更改,默認(rèn)MaxInt

實(shí)戰(zhàn)

場(chǎng)景1- 恒打印

規(guī)則description

默認(rèn)打印Hello World

規(guī)則
public class MyRule extends BasicRule {@Overridepublic String getName() {return "my rule";}@Overridepublic String getDescription() {return "my rule description";}@Overridepublic boolean evaluate(Facts facts) {return true;}@Overridepublic void execute(Facts facts) throws Exception {System.out.println("我是一個(gè)打印Hello World的規(guī)則");}
}
規(guī)則引擎:使用DefaultRulesEngine
執(zhí)行
public static void main(String[] args) {// 1.創(chuàng)建事實(shí)factFacts facts = new Facts();// 2.創(chuàng)建條件condition(這里MyRule中默認(rèn)為true,就不自定義Condition實(shí)現(xiàn)類了)// 3.創(chuàng)建動(dòng)作action(這里MyRule中默認(rèn)為:打印HelloWorld,就不自定義Action實(shí)現(xiàn)類了)// 4.創(chuàng)建規(guī)則MyRule myRule = new MyRule();// 5.定義RulesRules rules = new Rules();rules.register(myRule);// 6.創(chuàng)建規(guī)則引擎DefaultRulesEngine defaultRulesEngine = new DefaultRulesEngine();// 7.執(zhí)行defaultRulesEngine.fire(rules, facts);}

輸出

DefaultRulesEngineListener - Rules evaluation started
DefaultRuleListener - Rule 'my rule' triggered我是一個(gè)打印Hello World的規(guī)則DefaultRuleListener - Rule 'my rule' performed successfully
fire方法執(zhí)行流程
第一步:List<RulesEngineListener> rulesEngineListeners;執(zhí)行 void beforeEvaluate(Rule var1, Facts var2)第二步:MyRuleboolean evaluate(Facts facts)第三步:List<RuleListener> ruleListeners;執(zhí)行void afterEvaluate(Rule var1, Facts var2, boolean evaluateResult)第四步:List<RuleListener> ruleListeners;執(zhí)行void beforeExecute(Rule var1, Facts var2);第五步:MyRulevoid execute(Facts facts)第六步:List<RuleListener> ruleListeners;執(zhí)行void onSuccess(Rule var1, Facts var2);

場(chǎng)景2-yml

1、規(guī)則description

if it rains then take an umbrella

2、定義規(guī)則

weather-rule.yml

name: "weather rule"
description: "if it rains then take an umbrella"
condition: "isRain == true"
actions:- "System.out.println(\"It rains, take an umbrella!\");"

3、自定義規(guī)則引擎:使用默認(rèn)的

4、執(zhí)行

// 1.創(chuàng)建事實(shí)factFacts facts = new Facts();facts.put("isRain", true);// 2.創(chuàng)建條件condition(weatherRule中:isRain == true,就不自定義Condition實(shí)現(xiàn)類了)// 3.創(chuàng)建動(dòng)作action(weatherRule中默認(rèn)為:It rains, take an umbrella!,就不自定義Action實(shí)現(xiàn)類了)// 4.創(chuàng)建規(guī)則(Yml形式)MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());Rule weatherRule = ruleFactory.createRule(new FileReader("D:\\CodeBetter\\src\\main\\resources\\weather-rule.yml"));// 5.創(chuàng)建規(guī)則引擎DefaultRulesEngine defaultRulesEngine = new DefaultRulesEngine();// 6.定義RulesRules rules = new Rules();rules.register(weatherRule);// 7.執(zhí)行defaultRulesEngine.fire(rules, facts);

場(chǎng)景3 簡(jiǎn)單if-else

1、功能描述

從1數(shù)到100,并且:

  • 需求1:如果數(shù)字是5的倍數(shù),則打印"i :是5的倍數(shù)"
  • 需求2:如果數(shù)字是7的倍數(shù),請(qǐng)打印"i :是7的倍數(shù)"
  • 需求3:如果數(shù)字是5和7的倍數(shù),請(qǐng)打印"i :是5的倍數(shù)、7的倍數(shù)"
  • 需求4:否則打印數(shù)字本身

2、常規(guī)實(shí)現(xiàn)方法

public class FizzBuzz {public static void main(String[] args) {for(int i = 1; i <= 100; i++) {if (((i % 5) == 0) && ((i % 7) == 0))System.out.print("fizzbuzz");else if ((i % 5) == 0) System.out.print("fizz");else if ((i % 7) == 0) System.out.print("buzz");else System.out.print(i);}}
}

3、使用Easy Rules規(guī)則引擎實(shí)現(xiàn)

將每個(gè)需求編寫(xiě)一條規(guī)則:

  • rule1
@Rule(name = "Mod5Rule", description = "mod5", priority = 1)
public class Mod5Rule {@Conditionpublic boolean canMod5(@Fact("number") Integer number) {return number % 5 == 0;}@Actionpublic void action(Facts facts) {Integer i = facts.get("number");System.out.print(i + " :是5的倍數(shù)");}
}
  • rule2
@Rule(name = "Mod7Rule", description = "mod7", priority = 2)
public class Mod7Rule {@Conditionpublic boolean canMod7(@Fact("number") Integer number) {return number % 7 == 0;}@Actionpublic void action(Facts facts) {Integer i = facts.get("number");System.out.print(i + " :是7的倍數(shù)");}
}
  • rule3
public class Mod5And7Rule extends UnitRuleGroup {public Mod5And7Rule(Object... rules) {for (Object rule : rules) {addRule(rule);}}@Overridepublic int getPriority() {return 0;}
}
  • rule4
@Rule(name = "OtherRule", description = "不是5和7的倍數(shù)", priority = 3)
public class OtherRule {@Conditionpublic boolean canNotMod5Or7(@Fact("number") Integer number) {return number % 5 != 0 || number % 7 != 0;}@Actionpublic void action(@Fact("number") Integer number) {System.out.print(number);}
}
  • 執(zhí)行
// 創(chuàng)建規(guī)則引擎RulesEngineParameters parameters = new RulesEngineParameters().skipOnFirstAppliedRule(true);RulesEngine fizzBuzzEngine = new DefaultRulesEngine(parameters);// 創(chuàng)建規(guī)則Rules rules = new Rules();rules.register(new Mod5Rule());rules.register(new Mod7Rule());rules.register(new Mod5And7Rule(new Mod5Rule(), new Mod7Rule()));rules.register(new OtherRule());// 觸發(fā)規(guī)則Facts facts = new Facts();for (int i = 1; i <= 100; i++) {facts.put("number", i);fizzBuzzEngine.fire(rules, facts);}
  • 這里規(guī)則引擎參數(shù):skipOnFirstAppliedRule(true):告訴引擎,被觸發(fā)時(shí)跳過(guò)后面的規(guī)則。

    即當(dāng)i = 5時(shí),滿足規(guī)則1(mod5),執(zhí)行完action1,就不會(huì)再去匹配其他rule2、3、4規(guī)則了。使用場(chǎng)景是:各個(gè)規(guī)則之間互斥

場(chǎng)景4-動(dòng)態(tài)規(guī)則MVEL表達(dá)式+Json字符串

如圖1

在這里插入圖片描述

輸入facts:NORMAL_NUMBER和ERROR_NUMBER兩個(gè)值,使用Mvel表達(dá)式解析facts是否滿足上述json中定義的condition

  • 操作符枚舉類(加減乘除,> 、<)
package com.mjp.easyrules.csdn;public enum OperationEnum {GREATER_THAN("GREATER_THAN", "%s > %s", "大于"),GREATER_THAN_EQUAL("GREATER_THAN_EQUAL", "%s >= %s", "大于等于"),LESS_THAN("LESS_THAN", "%s < %s", "小于"),LESS_THAN_EQUAL("LESS_THAN_EQUAL", "%s <= %s", "小于等于"),EQUAL("EQUAL", "%s == %s", "等于"),UNEQUAL("UNEQUAL", "%s != %s", "不等于"),BETWEEN("BETWEEN", "%s >= %s && %s <= %s", "介于之間"),OUT_OF_RANGE("OUT_OF_RANGE", "%s >= %s || %s >= %s", "超出范圍"),CONTAINS("CONTAINS", "%s.contains(\"%s\")", "包含"),STARTSWITH("STARTSWITH", "%s.startsWith(\"%s\")", "前綴"),ENDSWITH("ENDSWITH", "%s.endsWith(\"%s\")", "后綴"),;public static OperationEnum getOperationByOperator(String operator) {OperationEnum[] list = OperationEnum.values();for (OperationEnum item : list) {String compareOperator = item.getOperator();if (compareOperator.equals(operator)) {return item;}}return null;}private final String operator;private final String expression;private final String remark;OperationEnum(String operator, String expression, String remark) {this.operator = operator;this.expression = expression;this.remark = remark;}public String getOperator() {return operator;}public String getExpression() {return expression;}public String getRemark() {return remark;}
}
  • 邏輯運(yùn)算符(&&、||、and、or)
public class EasyRulesConstants {// 事實(shí)別名public static final String FACT_ALIAS = "fact";// 結(jié)果別名public static final String RESULT_ALIAS = "result";// and關(guān)系public static final String RELATION_AND = "and";// or關(guān)系public static final String RELATION_OR = "or";// 匹配成功信息public static final String MATCH_SUCCESS_MESSAGE = "匹配成功";public static final String FIELD_TYPE = "type";public static final String FIELD_OPERATOR = "operator";public static final String FIELD_NAME = "metricName";public static final String FIELD_VALUE = "value";public static final String FIELD_CHILDREN = "children";public static final String EXPRESSION_TYPE = "EXPRESSION";public static final String RELATION_TYPE = "RELATION";public static final String LEFT_BRACKETS = "(";public static final String RIGHT_BRACKETS = ")";public static final String SYMBOL_SPACE = " ";public static final String SYMBOL_EMPTY = "";public static final String LOGICAL_AND = "&&";public static final String LOGICAL_OR = "||";
}
  • 工具類(負(fù)責(zé)解析自定義json字符串中的condition和action內(nèi)容,賦值給Mvel規(guī)則when、then)
package com.mjp.easyrules.csdn;@Slf4j
public class EasyRulesUtil {/*** 執(zhí)行規(guī)則匹配* @param fact 事實(shí)json* @param ruleModel 規(guī)則模型*/public static RuleResult match(JSONObject fact, RuleModel ruleModel){// 結(jié)果RuleResult result = new RuleResult();result.setRuleId(ruleModel.getRuleId());// 規(guī)則實(shí)例Facts facts = new Facts();facts.put(FACT_ALIAS, fact);facts.put(RESULT_ALIAS, result);// 規(guī)則內(nèi)容Rule mvelrule = new MVELRule().name(ruleModel.getRuleName()).description(ruleModel.getDescription()).when(ruleModel.getWhenExpression()).then(ruleModel.getThenExpression());// 規(guī)則集合Rules rules = new Rules();// 將規(guī)則添加到集合rules.register(mvelrule);// 創(chuàng)建規(guī)則執(zhí)行引擎,并執(zhí)行規(guī)則RulesEngine rulesEngine = new DefaultRulesEngine();rulesEngine.fire(rules, facts);return result;}/*** 構(gòu)建mvel條件表達(dá)式* @param json 節(jié)點(diǎn)json,例如:* {*     "type": "EXPRESSION",*     "operator": "LESS_THAN",*     "metricName": "NORMAL_NUMBER",*     "value": "11",*     "children": []* }*/public static String buildWhenExpression(JSONObject json) {StringBuilder mvelExpressionSB = new StringBuilder();String type = json.getString(FIELD_TYPE);String operator = json.getString(FIELD_OPERATOR);switch (type) {case EXPRESSION_TYPE:String fieldName = json.getString(FIELD_NAME);String fieldValue = json.getString(FIELD_VALUE);mvelExpressionSB.append(buildOperatorExpress(operator, fieldName, fieldValue));break;case RELATION_TYPE:JSONArray children = json.getJSONArray(FIELD_CHILDREN);if (children.size() == 0) {return SYMBOL_EMPTY;}operator = convertRelationExpress(operator);StringBuilder sb = new StringBuilder();for (int i = 0; i < children.size(); i++) {JSONObject child = children.getJSONObject(i);// 遞歸構(gòu)建單個(gè)規(guī)則條件String childExpression = buildWhenExpression(child);if (!childExpression.isEmpty()) {if (sb.length() > 0) {sb.append(SYMBOL_SPACE).append(operator).append(SYMBOL_SPACE);}sb.append(LEFT_BRACKETS).append(childExpression).append(RIGHT_BRACKETS);}}mvelExpressionSB.append(sb);break;default:break;}return mvelExpressionSB.toString();}/*** 構(gòu)建mvel表達(dá)式* @param operator 操作符* @param fieldName 字段名稱* @param value 字段值*/private static String buildOperatorExpress(String operator, String fieldName, Object value) {OperationEnum operationEnum = OperationEnum.getOperationByOperator(operator);if (ObjectUtils.isNotEmpty(operationEnum)) {String expression = operationEnum.getExpression();return String.format(expression, buildValueExpress(fieldName), value);}return SYMBOL_EMPTY;}/*** 構(gòu)建mvel取值表達(dá)式* @param fieldName 字段名稱*/private static String buildValueExpress(String fieldName) {return String.format("%s.get(\"%s\")", FACT_ALIAS, fieldName);}/*** 轉(zhuǎn)換條件連接符* @param relation 條件連接符*/private static String convertRelationExpress(String relation) {if (StringUtils.isEmpty(relation)){return SYMBOL_EMPTY;} else if(relation.equalsIgnoreCase(RELATION_AND)){return LOGICAL_AND;} else if(relation.equalsIgnoreCase(RELATION_OR)){return LOGICAL_OR;}return relation;}/*** 構(gòu)建mvel結(jié)果表達(dá)式*/public static String buildThenExpression() {StringBuilder sb = new StringBuilder();sb.append(RESULT_ALIAS).append(".setValue(\"").append(MATCH_SUCCESS_MESSAGE).append("\");");log.info("thenExpression: {}", sb);return sb.toString();}@Datapublic static class RuleModel {private String ruleId;String ruleName;String description;String whenExpression;String thenExpression;}@Datapublic static class RuleResult {// 規(guī)則主鍵private String ruleId;// 是否匹配, 默認(rèn)falseboolean isMatch = false;// 匹配信息,默認(rèn)為匹配失敗String message = "匹配失敗";/*** 匹配成功后設(shè)置成功信息*/public void setValue(String message){this.message = message;this.isMatch = true;}}
}
  • 測(cè)試
		// 1. 新增規(guī)則EasyRulesUtil.RuleModel ruleModel = new EasyRulesUtil.RuleModel();ruleModel.setRuleId("1");ruleModel.setRuleName("rule1");ruleModel.setDescription("測(cè)試規(guī)則");// 2. 設(shè)置規(guī)則條件String ruleJson = "{\n" +"    \"validateCondition\": {\n" +"        \"type\": \"RELATION\",\n" +"        \"operator\": \"OR\",\n" +"        \"children\": [\n" +"            {\n" +"                \"type\": \"EXPRESSION\",\n" +"                \"operator\": \"LESS_THAN\",\n" +"                \"metricName\": \"NORMAL_NUMBER\",\n" +"                \"value\": \"11\",\n" +"                \"children\": []\n" +"            },\n" +"            {\n" +"                \"type\": \"EXPRESSION\",\n" +"                \"operator\": \"LESS_THAN_EQUAL\",\n" +"                \"metricName\": \"ERROR_NUMBER\",\n" +"                \"value\": \"11\",\n" +"                \"children\": []\n" +"            },\n" +"            {\n" +"                \"type\": \"RELATION\",\n" +"                \"children\": [\n" +"                    {\n" +"                        \"type\": \"EXPRESSION\",\n" +"                        \"metricName\": \"NORMAL_NUMBER\",\n" +"                        \"operator\": \"GREATER_THAN\",\n" +"                        \"value\": 10,\n" +"                        \"children\": []\n" +"                    },\n" +"                    {\n" +"                        \"type\": \"EXPRESSION\",\n" +"                        \"metricName\": \"ERROR_NUMBER\",\n" +"                        \"operator\": \"GREATER_THAN\",\n" +"                        \"value\": 100,\n" +"                        \"children\": []\n" +"                    },\n" +"                    {\n" +"                        \"type\": \"RELATION\",\n" +"                        \"children\": [\n" +"                            {\n" +"                                \"type\": \"EXPRESSION\",\n" +"                                \"metricName\": \"NORMAL_NUMBER\",\n" +"                                \"operator\": \"EQUAL\",\n" +"                                \"value\": 1,\n" +"                                \"children\": []\n" +"                            },\n" +"                            {\n" +"                                \"type\": \"EXPRESSION\",\n" +"                                \"metricName\": \"ERROR_NUMBER\",\n" +"                                \"operator\": \"EQUAL\",\n" +"                                \"value\": 1,\n" +"                                \"children \": []\n" +"                            }\n" +"                        ],\n" +"                        \"operator\": \"OR\"\n" +"                    }\n" +"                ],\n" +"                \"operator\": \"OR\"\n" +"            }\n" +"        ]\n" +"    }\n" +"}";JSONObject conditionJson = JSON.parseObject(ruleJson);// 3. 設(shè)置factString whenExpression = EasyRulesUtil.buildWhenExpression(conditionJson.getJSONObject("validateCondition"));ruleModel.setWhenExpression(whenExpression);// 4. 設(shè)置結(jié)果表達(dá)式ruleModel.setThenExpression(EasyRulesUtil.buildThenExpression());// 5. 設(shè)置匹配條件JSONObject json = new JSONObject();json.put("NORMAL_NUMBER", 12);json.put("ERROR_NUMBER", 12);json.put("省=陜西;市=西安;", 100);// 6. 調(diào)用規(guī)則匹配EasyRulesUtil.RuleResult result = EasyRulesUtil.match(json, ruleModel);System.out.println(result);

結(jié)果分析:顯然結(jié)果匹配成功。原因如圖2

在這里插入圖片描述

facts:NORMAL_NUMBER = 10、ERROR_NUMBER = 10

condition:如圖1

顯然NORMAL_NUMBER = 10,滿足第一個(gè)條件 < 11,直接返回true。

如果我們?cè)O(shè)置fact:NORMAL_NUMBER = 12,則NORMAL_NUMBER 不滿足第一個(gè)條件。

但是fact中ERROR_NUMBER = 10 <= 11滿足第二個(gè)條件,直接返回True

場(chǎng)景5-QLExpress

1、使用阿里的QLExpress

        <dependency><groupId>com.alibaba</groupId><artifactId>QLExpress</artifactId><version>3.3.2</version></dependency>
ExpressRunner runner = new ExpressRunner();DefaultContext<String, MetaRuleResult> context = new DefaultContext<>();context.put("o", MetaRuleResult.builder().skuId(1L).result(true).metaRule("o").failureReason("").build());context.put("l", MetaRuleResult.builder().skuId(1L).result(false).metaRule("l").failureReason("鎖庫(kù)存不可更改").build());context.put("s", MetaRuleResult.builder().skuId(1L).result(true).metaRule("s").failureReason("").build());context.put("w", MetaRuleResult.builder().skuId(1L).result(true).metaRule("w").failureReason("售罄預(yù)警").build());context.put("lo", MetaRuleResult.builder().skuId(1L).result(true).metaRule("lo").failureReason("").build());context.put("llo", MetaRuleResult.builder().skuId(1L).result(false).metaRule("llo").failureReason("鎖庫(kù)且修改值小于等于OR值可以更改").build());Object result;DefaultContext<String, Object> computeContext = new DefaultContext<>();for (Map.Entry<String, MetaRuleResult> entry : context.entrySet()) {computeContext.put(entry.getKey(), entry.getValue().getResult());}String ruleExpress = "o&&l&&s&&w&&lo&&llo";result = runner.execute(ruleExpress, computeContext, null, true, false);Boolean bResult = (Boolean) result;System.out.println(bResult);//false
  • MetaRuleResult
@Data
@Builder
public class MetaRuleResult {private Long skuId;private Boolean result;private String metaRule;private String failureReason;
}

2、使用EasyRules實(shí)現(xiàn)上述功能

  • 規(guī)則1
@Rule(name = "oRule", description = "修改值>=OR可修改")
public class ORule {@Conditionpublic boolean when(@Fact("oRule") MetaRuleResult oRule) {return oRule.getResult();}@Actionpublic void then(Facts facts) {System.out.println("修改值>=OR可修改");}
}

這里的規(guī)則是原子規(guī)則

  • 規(guī)則2
@Rule(name = "lRule", description = "鎖庫(kù)不可更改")
public class LRule {@Conditionpublic boolean when(@Fact("lRule") MetaRuleResult lRule) {return lRule.getResult();}@Actionpublic void then(Facts facts) {System.out.println("沒(méi)鎖庫(kù)可更改");}
}
  • 自定義組合規(guī)則
public class MyUnitRuleGroup extends CompositeRule {public MyUnitRuleGroup() {}public MyUnitRuleGroup(String name) {super(name);}public MyUnitRuleGroup(String name, String description) {super(name, description);}public MyUnitRuleGroup(String name, String description, int priority) {super(name, description, priority);}public boolean evaluate(Facts facts) {if (!this.rules.isEmpty()) {Iterator var2 = this.rules.iterator();Rule rule;do {if (!var2.hasNext()) {return true;}rule = (Rule)var2.next();} while(rule.evaluate(facts));// 將失敗的facts記錄失敗的原因String ruleName = rule.getName();MetaRuleResult metaRuleResult = facts.get(ruleName);facts.put("執(zhí)行失敗" + ruleName, metaRuleResult);return false;} else {return false;}}public void execute(Facts facts) throws Exception {Iterator var2 = this.rules.iterator();while(var2.hasNext()) {Rule rule = (Rule)var2.next();rule.execute(facts);}}
}

作用:這里的規(guī)則是組合規(guī)則,是原子規(guī)則的組合形式,可擴(kuò)展

這里的自定義規(guī)則組合,是快速失敗機(jī)制:即l&&o中如果lRule的condiotion為false,則直接失敗,使用facts記錄一個(gè)失敗原因。也可以自定義將每個(gè)rule-condition為false的原因都記錄下來(lái)

  • 自定義condition-after-listeren
public class MyRuleListener implements RuleListener {@Overridepublic boolean beforeEvaluate(Rule rule, Facts facts) {return true;}@Overridepublic void afterEvaluate(Rule rule, Facts facts, boolean b) {String ruleName = rule.getName();if (b) {// 只有l(wèi)&&o為true,才會(huì)走到這個(gè)邏輯,否則走下面邏輯facts.put(ruleName, MetaRuleResult.builder().skuId(1L).result(true).metaRule(ruleName).failureReason("").build());} else {// l&&o有一個(gè)不滿足,則總體失敗,將各個(gè)失敗的原因都記錄下來(lái)StringBuilder sb = new StringBuilder();for (Map.Entry<String, Object> fact : facts) {String key = fact.getKey();if (key.contains("失敗")) {MetaRuleResult result = (MetaRuleResult)fact.getValue();// 這里result中有中間參數(shù)比如lockStatus,則原因就可以寫(xiě):lockStatus=true,已鎖庫(kù),不允許修改sb.append(result.getFailureReason()+ "且");}}facts.put(ruleName, MetaRuleResult.builder().skuId(1L).result(false).metaRule(ruleName).failureReason(sb.toString()).build());}}@Overridepublic void beforeExecute(Rule rule, Facts facts) {}@Overridepublic void onSuccess(Rule rule, Facts facts) {}@Overridepublic void onFailure(Rule rule, Facts facts, Exception e) {}
}

作用:組合規(guī)則,執(zhí)行結(jié)果。成功|失敗,已經(jīng)失敗原因

  • 執(zhí)行
		// 1.factFacts facts = new Facts();facts.put("oRule",          MetaRuleResult.builder().skuId(1L).result(true).metaRule("o").failureReason("").build());facts.put("lRule",      MetaRuleResult.builder().skuId(1L).result(false).metaRule("l").failureReason("").build());// 2.ruleORule oRule = new ORule();LRule lRule = new LRule();String oAndLRuleName = "o&&l";MyUnitRuleGroup oAndL = new MyUnitRuleGroup(oAndLRuleName, ">=OR且未鎖過(guò)庫(kù)規(guī)則校驗(yàn)");oAndL.addRule(oRule);oAndL.addRule(lRule);// 3.rulesRules rules = new Rules();rules.register(oAndL);// 4.引擎DefaultRulesEngine engine = new DefaultRulesEngine();engine.registerRuleListener(new MyRuleListener());engine.fire(rules,facts);MetaRuleResult result = facts.get(oAndLRuleName);if (!result.getResult()) {System.out.println(oAndLRuleName + result.getFailureReason());}
  • 擴(kuò)展

1)db獲取規(guī)則表達(dá)式:

先根據(jù)網(wǎng)店+品類+角色+修改類型,查詢db獲取組合規(guī)則,比如l&&o

2)工廠模式解析組合規(guī)則

然后根據(jù)l&&o,解析出規(guī)則為l和o,組合成l&&o

3)facts獲取數(shù)據(jù)

自定義策略模式,key為枚舉類型,value為對(duì)應(yīng)的rpc查詢接口

facts.put("o",          MetaRuleResult.builder().skuId(1L).result(queryData("o")).metaRule("o").failureReason("").build());

這里的queryData方法,根據(jù)規(guī)則類型o,獲取對(duì)應(yīng)的Rpc接口-ORGateway,然后查詢or值,然后比較結(jié)果

4)組合規(guī)則中,判斷每個(gè)原子規(guī)則是否執(zhí)行通過(guò),失敗則記錄對(duì)應(yīng)執(zhí)行失敗原因

5)在condition-after中自定義listeren,如果組合規(guī)則condition為false,則記錄組合規(guī)則整體的執(zhí)行失敗以及失敗原因

6)如果組合規(guī)則整體執(zhí)行失敗,則本次結(jié)果為false

場(chǎng)景6- 動(dòng)態(tài)規(guī)則Mvel + Json文件

1、背景

動(dòng)態(tài)規(guī)則就是由于業(yè)務(wù)場(chǎng)景的變化,之前的規(guī)則已經(jīng)不適用現(xiàn)在的業(yè)務(wù)場(chǎng)景,需要更改相對(duì)應(yīng)的規(guī)則。

例如:之前是滿300減30,現(xiàn)在是滿200-30

  • 正常情況下我們需要改規(guī)則類里面的比較參數(shù)代碼,然后打包上線。
  • 如果使用動(dòng)態(tài)規(guī)則,修改一下配置中的規(guī)則json文件即可,線上代碼會(huì)讀取最新的規(guī)則配置文件,無(wú)需上線

2、前提說(shuō)明

1)規(guī)則類中的condtion方法,可以入?yún)魅隖acts參數(shù),然后使用facts.get()方法獲取內(nèi)容 ,但是規(guī)則文件(eg:json)的condtion中無(wú)法傳入Facts參數(shù),也就無(wú)法使用此參數(shù)

2) 自定義RuleListener監(jiān)聽(tīng)會(huì)作用到所有執(zhí)行的規(guī)則,如何僅處理我們指定的規(guī)則

@Override
public void afterEvaluate(Rule rule, Facts facts, boolean evaluateResult) {if(evaluateResult && Objects.equals(rule.getName(), "我們指定的規(guī)則名稱")) {}
}

3、場(chǎng)景

  • 輸入一個(gè)人的信息,信息中包含了這個(gè)人的學(xué)歷等級(jí),作為規(guī)則事實(shí)

    • 方式一:condition中制定(推薦,可以動(dòng)態(tài)配置0和11)
    • @Condition修飾方法入?yún)? @Fact(“person”) Person person )
    [{"name": "newEducationAdd","description": "修改學(xué)歷添加列表","condition": "person.getQualifications() >= 0 && person.getQualifications()<=11","priority": 3,"actions": ["System.out.println(\"新規(guī)則執(zhí)行了\")"]}
    ]
    
    • 方式二:將condition條件判斷,自定在fact-key中對(duì)象的屬性和方法中(不推薦)
[{"name": "newEducationAdd","description": "修改學(xué)歷添加列表","condition": "person.getResult(person.getQualifications())","priority": 3,"actions": ["System.out.println(\"新規(guī)則執(zhí)行了\")"]
}]
@Data
public class Person {// 姓名private String name;// 年齡private int age;// 描述private String dec;// 學(xué)歷等級(jí)private int qualifications;private List<Education> educationList;public boolean getResult(int level){return AddEducation.getResult(level);}
}@UtilityClass
public class AddEducation {public static boolean getResult(int level){return level >= 0 && level <= 11;}
}
  • 如果學(xué)歷等級(jí)符合規(guī)則,則去查詢學(xué)歷證書(shū)情況(集合存儲(chǔ))

  • 查出完學(xué)歷證書(shū)后,在檢測(cè)學(xué)歷證書(shū)與他的學(xué)歷等級(jí)是否匹配,匹配規(guī)則為:

    • 學(xué)歷證書(shū)數(shù)量與學(xué)歷等級(jí)相同
    • 最大學(xué)歷證書(shū)的學(xué)歷等級(jí)與學(xué)歷等級(jí)一致
  • 匹配通過(guò)則學(xué)歷真實(shí),信息中會(huì)添加真實(shí)學(xué)歷匹配結(jié)果

  • 未匹配通過(guò)則學(xué)歷造假嫌疑,信息中會(huì)添加造假學(xué)歷信息

上線

2、前提說(shuō)明

1)規(guī)則類中的condtion方法,可以入?yún)魅隖acts參數(shù),然后使用facts.get()方法獲取內(nèi)容 ,但是規(guī)則文件(eg:json)的condtion中無(wú)法傳入Facts參數(shù),也就無(wú)法使用此參數(shù)

2) 自定義RuleListener監(jiān)聽(tīng)會(huì)作用到所有執(zhí)行的規(guī)則,如何僅處理我們指定的規(guī)則

@Override
public void afterEvaluate(Rule rule, Facts facts, boolean evaluateResult) {if(evaluateResult && Objects.equals(rule.getName(), "我們指定的規(guī)則名稱")) {}
}

3、場(chǎng)景

  • 輸入一個(gè)人的信息,信息中包含了這個(gè)人的學(xué)歷等級(jí),作為規(guī)則事實(shí)

    • 方式一:condition中制定(推薦,可以動(dòng)態(tài)配置0和11)
    • @Condition修飾方法入?yún)? @Fact(“person”) Person person )
    [{"name": "newEducationAdd","description": "修改學(xué)歷添加列表","condition": "person.getQualifications() >= 0 && person.getQualifications()<=11","priority": 3,"actions": ["System.out.println(\"新規(guī)則執(zhí)行了\")"]}
    ]
    
    • 方式二:將condition條件判斷,自定在fact-key中對(duì)象的屬性和方法中(不推薦)
[{"name": "newEducationAdd","description": "修改學(xué)歷添加列表","condition": "person.getResult(person.getQualifications())","priority": 3,"actions": ["System.out.println(\"新規(guī)則執(zhí)行了\")"]
}]
@Data
public class Person {// 姓名private String name;// 年齡private int age;// 描述private String dec;// 學(xué)歷等級(jí)private int qualifications;private List<Education> educationList;public boolean getResult(int level){return AddEducation.getResult(level);}
}@UtilityClass
public class AddEducation {public static boolean getResult(int level){return level >= 0 && level <= 11;}
}
  • 如果學(xué)歷等級(jí)符合規(guī)則,則去查詢學(xué)歷證書(shū)情況(集合存儲(chǔ))

  • 查出完學(xué)歷證書(shū)后,在檢測(cè)學(xué)歷證書(shū)與他的學(xué)歷等級(jí)是否匹配,匹配規(guī)則為:

    • 學(xué)歷證書(shū)數(shù)量與學(xué)歷等級(jí)相同
    • 最大學(xué)歷證書(shū)的學(xué)歷等級(jí)與學(xué)歷等級(jí)一致
  • 匹配通過(guò)則學(xué)歷真實(shí),信息中會(huì)添加真實(shí)學(xué)歷匹配結(jié)果

  • 未匹配通過(guò)則學(xué)歷造假嫌疑,信息中會(huì)添加造假學(xué)歷信息

場(chǎng)景7-履約缺貨處罰金額計(jì)算

http://m.aloenet.com.cn/news/34078.html

相關(guān)文章:

  • 常德舉報(bào)網(wǎng)站seo在線工具
  • wordpress部分文字管理員可見(jiàn)百度seo推廣首選帝搜軟件
  • 免費(fèi)商城系統(tǒng)下載福建網(wǎng)絡(luò)seo關(guān)鍵詞優(yōu)化教程
  • 動(dòng)態(tài)網(wǎng)站建設(shè)案例教程下載男生短期培訓(xùn)就業(yè)
  • wordpress哪些文件需要給777成都網(wǎng)站seo技巧
  • php網(wǎng)站數(shù)據(jù)遷移鄭州網(wǎng)站建設(shè)七彩科技
  • 河南如何做網(wǎng)站seo優(yōu)化公司信
  • 青島旅游網(wǎng)站建設(shè)怎么制作一個(gè)網(wǎng)站5個(gè)網(wǎng)頁(yè)
  • 天津網(wǎng)絡(luò)關(guān)鍵詞排名石家莊seo網(wǎng)站排名
  • wordpress最新功能網(wǎng)站優(yōu)化技術(shù)
  • 哪個(gè)網(wǎng)站做首飾批發(fā)好百度網(wǎng)頁(yè)版登錄入口官網(wǎng)
  • 廣東東莞網(wǎng)站建設(shè)微信管理軟件哪個(gè)最好
  • wordpress標(biāo)簽別名轉(zhuǎn)換網(wǎng)絡(luò)seo招聘
  • 湖南哪里有做網(wǎng)站的愛(ài)站工具包手機(jī)版
  • 網(wǎng)站做廣告費(fèi)用關(guān)鍵詞調(diào)價(jià)工具哪個(gè)好
  • 邢臺(tái)網(wǎng)站建設(shè) 冀icp備信息流優(yōu)化師證書(shū)
  • 淄博企業(yè)網(wǎng)站建設(shè)自動(dòng)的網(wǎng)站設(shè)計(jì)制作
  • 網(wǎng)站年費(fèi)怎么做分錄十大免費(fèi)貨源網(wǎng)站免費(fèi)版本
  • 建立一個(gè)公司的網(wǎng)站嗎百度競(jìng)價(jià)點(diǎn)擊神器
  • 曲靖做網(wǎng)站價(jià)格超級(jí)seo外鏈
  • 網(wǎng)站開(kāi)發(fā)課程設(shè)計(jì)參考文獻(xiàn)5118網(wǎng)站如何使用免費(fèi)版
  • 地方網(wǎng)站做的好的百度競(jìng)價(jià)產(chǎn)品
  • 網(wǎng)站建設(shè) 服務(wù)器友情鏈接工具
  • 外貿(mào)公司網(wǎng)站多少錢(qián)網(wǎng)頁(yè)制作作業(yè)100例
  • 深圳建站公司推薦seo網(wǎng)站建設(shè)是什么意思
  • 查看網(wǎng)站流量跨境電商平臺(tái)推廣
  • 合肥市中小企業(yè)局網(wǎng)站實(shí)時(shí)seo排名點(diǎn)擊軟件
  • 膠州專業(yè)建站湖北seo服務(wù)
  • 做外貿(mào)商城網(wǎng)站鄭州網(wǎng)絡(luò)推廣平臺(tái)
  • 厚街做網(wǎng)站公司代做網(wǎng)頁(yè)設(shè)計(jì)平臺(tái)