In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
Java rules engine easy-rules how to understand, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.
Recently, I am thinking about a technical refactoring based on rules, which I want to implement through the rule engine. I can take this opportunity to learn more about the rule engine. The use of the rules engine easy-rules is described in more detail below.
Brief introduction
Easy Rules is a simple but powerful Java rules engine that provides the following features:
Lightweight framework and easy-to-learn API
Development based on POJO
Support for creating composite rules from original rules
Support for defining rules through expressions such as MVEL,SPEL and JEXL
Start using the introduction of dependency org.jeasy easy-rules-core 4.1.0
Only core module dependencies are introduced above. If you need other module content, you can introduce corresponding dependencies.
Define rules
Introduction
Most business rules can be represented by the following definitions:
Name: the unique rule name in the rule namespace
Description: a brief description of the rules
Priority: priority of the rule
Facts: a set of known facts when a rule is triggered
Conditions: a set of conditions that need to be met in order to apply the rule given some facts
Actions: a set of actions to be performed when conditions are met (facts may be added / deleted / modified)
Easy Rules provides abstraction for defining each key point of a business rule. The rules in Easy Rules are represented by the Rule interface:
Public interface Rule extends Comparable {/ * this method encapsulates the conditions of the rule. * @ return true if the rule can be applied according to the facts provided, otherwise false * / boolean evaluate (Facts facts); / * * this method encapsulates the operation of the rule. * @ throws if an error occurs during the operation, an exception is thrown * / void execute (Facts facts) throws Exception; / / Getters and setters for rule name, description and priority omitted.}
The evaluate () method encapsulates a condition that must be true to trigger a rule. The execute () method encapsulates the actions that should be performed if the rule conditions are met. Conditions and actions are represented by Condition and Action interfaces.
Rules can be defined in two different ways:
Declare by adding comments to the POJO
Programming through RuleBuilder API
These are the most common ways to define rules, but you can also implement the Rule interface or extend the BasicRule class if needed.
Define rules using annotations
Easy Rules provides @ Rule annotations to convert POJO into rules.
@ Rule (name = "my rule", description = "my rule description", priority = 1) public class MyRule {@ Condition public boolean when (@ Fact ("fact") fact) {/ / Rule condition return true } @ Action (order = 1) public void then (Facts facts) throws Exception {/ / Action 1} @ Action (order = 2) public void finally () throws Exception {/ / Action 2} when the rule is true
The @ Condition annotation is used to mark the method for evaluating rule conditions, which must be public, can have one or more parameters annotated with @ Fact, and return a boolean type. There is only one method that can be marked with @ Condition annotations.
The @ Action annotation is used to mark the method of performing an action, and a rule can have multiple actions. You can use the order property to perform operations in the order specified.
Define rules using RuleBuilder
RuleBuilder allows you to define rules using streaming API.
Rule rule = new RuleBuilder () .name ("myRule") .description ("myRuleDescription") .priority (3) .when (condition) .then (action1) .then (action2) .build ()
In this case, condition is an instance of the Condition interface, and action1 and action2 are instances of the Action interface.
Combination rule
Easy Rules allows you to create complex rules from the original rules. A CompositeRule consists of a set of rules. Composition rules are an abstract concept because they can be triggered in different ways. Easy Rules provides three implementations of CompositeRule.
UnitRuleGroup: a unit rule group is a combination of rules used as a unit, with either all rules applied or no rules applied.
ActivationRuleGroup: activate the rule group to trigger the first applicable rule and ignore other rules in the group. The rules are first sorted according to their natural order in the group (priority by default).
ConditionalRuleGroup: the conditional rule group takes the rule with the highest priority as a condition, and if the rule with the highest priority evaluates to true, the rest of the rules will be triggered.
Composite rules can be created from the original rules and registered like regular rules.
/ / create a combination rule from two original rules UnitRuleGroup myUnitRuleGroup = new UnitRuleGroup ("myUnitRuleGroup", "unit of myRule1 and myRule2"); myUnitRuleGroup.addRule (myRule1); myUnitRuleGroup.addRule (myRule2); / / register a combination rule Rules rules = new Rules () like a regular rule; rules.register (myUnitRuleGroup); RulesEngine rulesEngine = new DefaultRulesEngine (); rulesEngine.fire (rules, someFacts); rule priority
Each rule in Easy Rules has a priority. This indicates the default order in which registration rules are triggered. The lower the value, the higher the priority by default. To override this behavior, you should override the compareTo () method to provide a custom priority policy.
If you inherit BasicRule, you can specify a priority in the constructor or override the getPriority () method.
If you are using POJO to define a rule, you can specify a priority through the priority attribute of the @ Rule annotation, or mark a method with the @ Priority annotation. This method must be public with no parameters but the return type is Integer.
If you use RuleBuilder to define rules, you can specify a priority using the RuleBuilder#priority () method.
Rules API
A set of rules in Easy rules is represented by rules API. It can be used as follows:
Rules rules = new Rules (); rules.register (myRule1); rules.register (myRule2)
Rules represents the namespace of registered rules, so each registered rule must have a unique name under the same namespace.
Rules is compared through the Rule#compareTo () method, so the implementation of Rule should correctly implement the compareTo () method to ensure that there is a unique rule name in a single space.
Define facts
A fact in Easy Rules is represented by Fact:
Public class Fact {private final String name; private final T value;}
A fact has a name and a value, neither of which can be null. Facts API, on the other hand, represents a set of facts and acts as a namespace for facts. This means that in an Facts instance, the fact must have a unique name.
Here is an example of how to define facts:
Fact fact = new Fact ("foo", "bar"); Facts facts = new Facts (); facts.add (fact)
You can also use a shorter version to create named facts with the put method, as follows:
Facts facts = new Facts (); facts.put ("foo", "bar")
You can use the @ Fact annotation to inject facts into the conditions and methods of operation of a rule. In the following rules, rain facts are injected into the rain parameter of the itRains method:
Ruleclass WeatherRule {@ Condition public boolean itRains (@ Fact ("rain") boolean rain) {return rain;} @ Action public void takeAnUmbrella (Facts facts) {System.out.println ("It rains, take an umbrella!"); / / can add/remove/modify facts}}
Parameters of type Facts will be injected into all known facts.
Note:
If the injection fact is missing in the conditional method, the engine logs a warning and assumes that the condition is evaluated as false.
If the injection fact is missing in the action method, the action is not performed and an org.jeasy.rules.core.NoSuchFactException exception is thrown.
Define the rule engine
Easy Rules provides two implementations of the RulesEngine interface:
DefaultRulesEngine: rules are applied according to their natural order (the default is priority).
InferenceRulesEngine: keep applying rules on known facts until there are no more rules available.
Create a rules engine
You can use constructors to create a rule engine.
RulesEngine rulesEngine = new DefaultRulesEngine (); / / orRulesEngine rulesEngine = new InferenceRulesEngine ()
Registered rules can be triggered as follows.
RulesEngine.fire (rules, facts); rules engine parameters
The Easy Rules engine can configure the following parameters:
Parameter type default value rulePriorityThresholdintMaxIntskipOnFirstAppliedRulebooleanfalserulePriorityThresholdintfalseskipOnFirstFailedRulebooleanfalseskipOnFirstNonTriggeredRulebooleanfalse
SkipOnFirstAppliedRule: when a rule is successfully applied, skip the remaining rules.
SkipOnFirstFailedRule: when one rule fails, skip the remaining rules.
SkipOnFirstNonTriggeredRule: when a rule is not triggered, skip the remaining rules.
RulePriorityThreshold: when the priority exceeds the specified threshold, the remaining rules are skipped.
You can specify these parameters using RulesEngineParameters API:
RulesEngineParameters parameters = new RulesEngineParameters () .rulePriorityThreshold (10) .skipOnFirstAppliedRule (true) .skipOnFirstFailedRule (true) .skipOnFirstNonTriggeredRule (true); RulesEngine rulesEngine = new DefaultRulesEngine (parameters)
If you want to get parameters from your engine, you can use the following code snippet:
RulesEngineParameters parameters = myEngine.getParameters ()
This allows you to reset engine parameters after you create them.
Define rule listeners
You can listen for rule execution events through RuleListener API:
Public interface RuleListener {/ * is triggered before the rule is evaluated. * * @ param rule the rule being evaluated * @ param facts known facts before the evaluation rule * @ return returns true if the rule should be evaluated, otherwise false * / default boolean beforeEvaluate (Rule rule, Facts facts) {return true } / * trigger after evaluation rule * * @ param rule rule after evaluation * @ param facts known facts after evaluation rule * @ param evaluationResult evaluation result * / default void afterEvaluate (Rule rule, Facts facts Boolean evaluationResult) {} / * when a runtime exception causes a condition evaluation error, it triggers the rule after * * @ param rule evaluation * @ known facts during param facts evaluation * @ param exception the exception that occurs during condition evaluation * / default void onEvaluationError (Rule rule, Facts facts, Exception exception) {} / * is triggered before the rule operation is executed. * * @ param rule current rule * @ param facts known facts when performing a rule action * / default void beforeExecute (Rule rule, Facts facts) {} / * trigger * * @ param rule t current rule * @ param facts to perform a rule action after successful execution of the rule action * / default void onSuccess (Rule rule Facts facts) {} / * triggers * * @ param rule current rule * @ param facts known facts when performing a rule action * @ param exception exception occurred during a rule action * / default void onFailure (Rule rule, Facts facts, Exception exception) {}}
You can implement this interface to provide custom behavior to execute before / after each rule. To register the listener, use the following code snippet:
DefaultRulesEngine rulesEngine = new DefaultRulesEngine (); rulesEngine.registerRuleListener (myRuleListener)
Any number of listeners can be registered and they will be executed in the order in which they are registered.
Note: when using composition rules, the listener is called around the composition rules.
Define rule engine listeners
You can listen to the execution events of the rules engine through RulesEngineListener API:
Facts before public interface RulesEngineListener {/ * triggers * * @ param rules before executing the rule set * @ param facts triggers the rule * / default void beforeEvaluate (Rules rules Facts facts) {} / * * after executing the rule set, trigger * * @ param rules the rule set to be triggered * @ param facts before triggering the rule * / default void afterExecute (Rules rules, Facts facts) {}}
RulesEngineListener allows us to provide custom behavior before / after triggering the entire rule set. You can register listeners in the following ways.
DefaultRulesEngine rulesEngine = new DefaultRulesEngine (); rulesEngine.registerRulesEngineListener (myRulesEngineListener)
Any number of listeners can be registered and they will be executed in the order in which they are registered.
Expression language (EL) support
Easy Rules supports defining rules with MVEL, SpEL, and JEXL.
Considerations for EL provider
EL providers have some differences in behavior. For example, when a fact is missing in a condition, MVEL throws an exception, and SpEL ignores it and returns false. Therefore, you should be aware of these differences before choosing which EL to use for Easy Rules.
Define rules programmatically
Conditions, actions, and rules are represented by the MVELCondition/SpELCondition/JexlCondition, MVELAction/SpELAction/JexlAction, and MVELRule/SpELRule/ JexlRule classes, respectively. Here is an example of using MVEL to define rules:
Rule ageRule = new MVELRule () .name ("age rule") .description ("Check if person's age is > 18 and marks the person as adult") .priority (1) .when ("person.age > 18") .then ("person.setAdult (true);"); define the rule through the rule description file
You can use a rule description file to define rules and use MVELRuleFactory/SpELRuleFactory/JexlRuleFactory to create rules from a descriptor file. The following is an example of an MVEL rule defined in YAML format in alcohol-rule.yml:
Name: "alcohol rule" description: "children are not allowed to buy alcohol" priority: 2condition: "person.isAdult () = = false" actions:-"System.out.println (" Shop: Sorry, you are not allowed to buy alcohol ");" MVELRuleFactory ruleFactory = new MVELRuleFactory (new YamlRuleDefinitionReader ()); MVELRule alcoholRule = ruleFactory.createRule (new FileReader ("alcohol-rule.yml"))
You can also use a single file to create multiple rules.
-name: adult ruledescription: when age is greater than 18, then mark as adultpriority: 1condition: "person.age > 18" actions:-"person.setAdult (true);"-- name: weather ruledescription: when it rains, then take an umbrellapriority: 2condition: "rain = = true" actions:-"System.out.println (" It rains, take an umbrella! ");"
You can load these rules into the rules object as follows.
MVELRuleFactory ruleFactory = new MVELRuleFactory (new YamlRuleDefinitionReader ()); Rules rules = ruleFactory.createRules (new FileReader ("rules.yml"))
Easy Rules also supports loading rules from the JSON descriptor. Specific reference documentation, do not expand here.
Error handling in rule definition
On the engine behavior of incorrect expressions in conditions
For any runtime exceptions that may occur during conditional evaluation (missing facts, input errors in expressions, and so on), the engine logs a warning and considers the conditional evaluation to be false. You can use RuleListener#onEvaluationError to listen for evaluation errors.
About the engine behavior of incorrect expressions in operations
For any runtime exceptions that may occur when an operation is performed (missing facts, input errors in expressions, and so on), the operation will not be performed and the engine will log an error. You can use RuleListener#onFailure to listen for operation execution exceptions. When one rule fails, the engine moves to the next rule unless the skipOnFirstFailedRule parameter is set.
Actual chestnut
Ben Chestnut uses Easy Rules to implement FizzBuzz applications. FizzBuzz is a simple application that needs to count from 1 to 100, and:
If the number is a multiple of 5, print "fizz"
If the number is a multiple of 7, print "buzz"
If the number is a multiple of 5 and 7, print "fizzbuzz"
Otherwise, print the number itself.
Public class FizzBuzz {public static void main (String [] args) {for (int I = 1; I)
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.