diff --git a/cola-components/cola-component-ruleengine/README.md b/cola-components/cola-component-ruleengine/README.md
new file mode 100644
index 000000000..35a95bbbf
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/README.md
@@ -0,0 +1,20 @@
+## 介绍
+这是COLA规则引擎
+
+## 使用
+hello world 案例:
+```java
+ RuleEngine ruleEngine = new DefaultRuleEngine();
+ Rule rule = new RuleBuilder()
+ .name("hello world rule")
+ .description("always say hello world")
+ .priority(1)
+ .when(facts -> true)
+ .then(facts -> System.out.println("hello world"))
+ .build();
+ Rules rules = new Rules();
+ rules.register(rule);
+
+ ruleEngine.fire(rules, null);
+```
+
diff --git a/cola-components/cola-component-ruleengine/gitignore.txt b/cola-components/cola-component-ruleengine/gitignore.txt
new file mode 100644
index 000000000..9a1655a05
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/gitignore.txt
@@ -0,0 +1,26 @@
+target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+out/
+
+### NetBeans ###
+nbproject/private/
+build/
+nbbuild/
+dist/
+nbdist/
+bin/
+doc/
+.DS_Store
diff --git a/cola-components/cola-component-ruleengine/pom.xml b/cola-components/cola-component-ruleengine/pom.xml
new file mode 100644
index 000000000..ff0028faf
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/pom.xml
@@ -0,0 +1,85 @@
+
+
+ 4.0.0
+
+ com.alibaba.cola
+ cola-components-parent
+ 4.4.0-SNAPSHOT
+
+
+ cola-component-ruleengine
+ jar
+ ${project.artifactId}:${project.version}
+ ${project.artifactId}
+ https://github.com/alibaba/COLA
+
+
+
+ GNU Lesser General Public License v2.1
+ https://github.com/alibaba/COLA/blob/master/LICENSE
+ repo
+
+
+
+ scm:git:https://github.com/alibaba/COLA.git
+ scm:git:https://github.com/alibaba/COLA.git
+ https://github.com/alibaba/COLA
+
+
+ https://github.com/alibaba/COLA/issues
+ GitHub Issues
+
+
+
+ significantfrank
+ Frank Zhang
+ 25216348(at)qq.com
+
+ Developer
+ Architect
+
+ +8
+ https://github.com/significantfrank
+
+
+ oldratlee
+ Jerry Lee
+ oldratlee(at)gmail.com
+
+ Developer
+ CI/SCM Engineer
+
+ +8
+ https://github.com/oldratlee
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+
+ org.slf4j
+ slf4j-simple
+ test
+
+
+ junit
+ junit
+ test
+
+
+ org.assertj
+ assertj-core
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Action.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Action.java
new file mode 100644
index 000000000..9638c84ef
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Action.java
@@ -0,0 +1,7 @@
+package com.alibaba.cola.ruleengine.api;
+
+@FunctionalInterface
+public interface Action {
+ void execute(Facts facts);
+}
+
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Condition.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Condition.java
new file mode 100644
index 000000000..f5d90a73f
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Condition.java
@@ -0,0 +1,36 @@
+package com.alibaba.cola.ruleengine.api;
+
+import java.util.Objects;
+
+@FunctionalInterface
+public interface Condition {
+
+ boolean evaluate(Facts facts);
+
+ //谓词and逻辑,参考Predicate
+ default Condition and(Condition other) {
+ Objects.requireNonNull(other);
+ return (facts) -> {
+ return this.evaluate(facts) && other.evaluate(facts);
+ };
+ }
+
+ //谓词or逻辑,参考Predicate
+ default Condition or(Condition other) {
+ Objects.requireNonNull(other);
+ return (facts) -> {
+ return this.evaluate(facts) || other.evaluate(facts);
+ };
+ }
+
+ /**
+ * A NoOp {@link Condition} that always returns false.
+ */
+ Condition FALSE = facts -> false;
+
+ /**
+ * A NoOp {@link Condition} that always returns true.
+ */
+ Condition TRUE = facts -> true;
+}
+
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Fact.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Fact.java
new file mode 100644
index 000000000..b4d4d358e
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Fact.java
@@ -0,0 +1,63 @@
+package com.alibaba.cola.ruleengine.api;
+
+import java.util.Objects;
+
+public class Fact {
+
+ private final String name;
+ private final T value;
+
+ /**
+ * Create a new fact.
+ * @param name of the fact
+ * @param value of the fact
+ */
+ public Fact(String name, T value) {
+ Objects.requireNonNull(name, "name must not be null");
+ Objects.requireNonNull(value, "value must not be null");
+ this.name = name;
+ this.value = value;
+ }
+
+ /**
+ * Get the fact name.
+ * @return fact name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the fact value.
+ * @return fact value
+ */
+ public T getValue() {
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "Fact{" +
+ "name='" + name + '\'' +
+ ", value=" + value +
+ '}';
+ }
+
+ /*
+ * The Facts API represents a namespace for facts where each fact has a unique name.
+ * Hence, equals/hashcode are deliberately calculated only on the fact name.
+ */
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ Fact> fact = (Fact>) o;
+ return name.equals(fact.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name);
+ }
+}
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Facts.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Facts.java
new file mode 100644
index 000000000..68b089554
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Facts.java
@@ -0,0 +1,140 @@
+package com.alibaba.cola.ruleengine.api;
+
+import java.util.*;
+
+public class Facts implements Iterable> {
+
+ private final Set> facts = new HashSet<>();
+
+ /**
+ * Add a fact, replacing any fact with the same name.
+ *
+ * @param name of the fact to add, must not be null
+ * @param value of the fact to add, must not be null
+ */
+ public void put(String name, T value) {
+ Objects.requireNonNull(name, "fact name must not be null");
+ Objects.requireNonNull(value, "fact value must not be null");
+ Fact> retrievedFact = getFact(name);
+ if (retrievedFact != null) {
+ remove(retrievedFact);
+ }
+ add(new Fact<>(name, value));
+ }
+
+ /**
+ * Add a fact, replacing any fact with the same name.
+ *
+ * @param fact to add, must not be null
+ */
+ public void add(Fact fact) {
+ Objects.requireNonNull(fact, "fact must not be null");
+ Fact> retrievedFact = getFact(fact.getName());
+ if (retrievedFact != null) {
+ remove(retrievedFact);
+ }
+ facts.add(fact);
+ }
+
+ /**
+ * Remove a fact by name.
+ *
+ * @param factName name of the fact to remove, must not be null
+ */
+ public void remove(String factName) {
+ Objects.requireNonNull(factName, "fact name must not be null");
+ Fact> fact = getFact(factName);
+ if (fact != null) {
+ remove(fact);
+ }
+ }
+
+ /**
+ * Remove a fact.
+ *
+ * @param fact to remove, must not be null
+ */
+ public void remove(Fact fact) {
+ Objects.requireNonNull(fact, "fact must not be null");
+ facts.remove(fact);
+ }
+
+ /**
+ * Get the value of a fact by its name. This is a convenience method provided
+ * as a short version of {@code getFact(factName).getValue()}.
+ *
+ * @param factName name of the fact, must not be null
+ * @param type of the fact's value
+ * @return the value of the fact having the given name, or null if there is
+ * no fact with the given name
+ */
+ @SuppressWarnings("unchecked")
+ public T get(String factName) {
+ Objects.requireNonNull(factName, "fact name must not be null");
+ Fact> fact = getFact(factName);
+ if (fact != null) {
+ return (T) fact.getValue();
+ }
+ return null;
+ }
+
+ /**
+ * Get a fact by name.
+ *
+ * @param factName name of the fact, must not be null
+ * @return the fact having the given name, or null if there is no fact with the given name
+ */
+ public Fact> getFact(String factName) {
+ Objects.requireNonNull(factName, "fact name must not be null");
+ return facts.stream()
+ .filter(fact -> fact.getName().equals(factName))
+ .findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * Return a copy of the facts as a map. It is not intended to manipulate
+ * facts outside of the rules engine (aka other than manipulating them through rules).
+ *
+ * @return a copy of the current facts as a {@link HashMap}
+ */
+ public Map asMap() {
+ Map map = new HashMap<>();
+ for (Fact> fact : facts) {
+ map.put(fact.getName(), fact.getValue());
+ }
+ return map;
+ }
+
+ /**
+ * Return an iterator on the set of facts. It is not intended to remove
+ * facts using this iterator outside of the rules engine (aka other than doing it through rules)
+ *
+ * @return an iterator on the set of facts
+ */
+ @Override
+ public Iterator> iterator() {
+ return facts.iterator();
+ }
+
+ /**
+ * Clear facts.
+ */
+ public void clear() {
+ facts.clear();
+ }
+
+ @Override
+ public String toString() {
+ Iterator> iterator = facts.iterator();
+ StringBuilder stringBuilder = new StringBuilder("[");
+ while (iterator.hasNext()) {
+ stringBuilder.append(iterator.next().toString());
+ if (iterator.hasNext()) {
+ stringBuilder.append(",");
+ }
+ }
+ stringBuilder.append("]");
+ return stringBuilder.toString();
+ }
+}
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Rule.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Rule.java
new file mode 100644
index 000000000..4a16db3e4
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Rule.java
@@ -0,0 +1,65 @@
+package com.alibaba.cola.ruleengine.api;
+
+public interface Rule extends Comparable {
+
+ /**
+ * Default rule name.
+ */
+ String DEFAULT_NAME = "rule";
+
+ /**
+ * Default rule description.
+ */
+ String DEFAULT_DESCRIPTION = "description";
+
+ /**
+ * Default rule priority.
+ */
+ int DEFAULT_PRIORITY = Integer.MAX_VALUE - 1;
+
+ /**
+ * Getter for rule name.
+ * @return the rule name
+ */
+ default String getName() {
+ return DEFAULT_NAME;
+ }
+
+ /**
+ * Getter for rule description.
+ * @return rule description
+ */
+ default String getDescription() {
+ return DEFAULT_DESCRIPTION;
+ }
+
+ /**
+ * Getter for rule priority.
+ * @return rule priority
+ */
+ default int getPriority() {
+ return DEFAULT_PRIORITY;
+ }
+
+ /**
+ * This method implements the rule's condition(s).
+ * Implementations should handle any runtime exception and return true/false accordingly
+ *
+ * @return true if the rule should be applied given the provided facts, false otherwise
+ */
+ boolean evaluate(Facts facts);
+
+ /**
+ * This method implements the rule's action(s).
+ * @throws Exception thrown if an exception occurs when performing action(s)
+ */
+ void execute(Facts facts);
+
+ /**
+ * This method apply facts to the rule, which is the combination of evaluation and execution
+ * @param facts
+ * @return true if this rule is applied successfully, false otherwise
+ */
+ boolean apply(Facts facts);
+
+}
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/RuleEngine.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/RuleEngine.java
new file mode 100644
index 000000000..3f15c1228
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/RuleEngine.java
@@ -0,0 +1,9 @@
+package com.alibaba.cola.ruleengine.api;
+
+public interface RuleEngine {
+ /**
+ * Fire all registered rules on given facts.
+ */
+ void fire(Rules rules, Facts facts);
+
+}
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Rules.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Rules.java
new file mode 100644
index 000000000..db28ca38f
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/api/Rules.java
@@ -0,0 +1,77 @@
+package com.alibaba.cola.ruleengine.api;
+
+import java.util.*;
+
+public class Rules implements Iterable {
+
+ private List rules = new ArrayList<>();
+
+ /**
+ * Create a new {@link Rules} object.
+ *
+ * @param rules to register
+ */
+ public Rules(Rule... rules) {
+ Collections.addAll(this.rules, rules);
+ }
+
+ /**
+ * Register one or more new rules.
+ *
+ * @param rules to register, must not be null
+ */
+ public void register(Rule... rules) {
+ Objects.requireNonNull(rules);
+ for (Rule rule : rules) {
+ Objects.requireNonNull(rule);
+ this.rules.add(rule);
+ }
+ }
+
+ /**
+ * Unregister one or more rules.
+ *
+ * @param rules to unregister, must not be null
+ */
+ public void unregister(Rule... rules) {
+ Objects.requireNonNull(rules);
+ for (Rule rule : rules) {
+ Objects.requireNonNull(rule);
+ this.rules.remove(rule);
+ }
+ }
+
+ public void sortRulesByPriority(){
+ Collections.sort(rules);
+ }
+
+ /**
+ * Check if the rule set is empty.
+ *
+ * @return true if the rule set is empty, false otherwise
+ */
+ public boolean isEmpty() {
+ return rules.isEmpty();
+ }
+
+ /**
+ * Clear rules.
+ */
+ public void clear() {
+ rules.clear();
+ }
+
+ /**
+ * Return how many rules are currently registered.
+ *
+ * @return the number of rules currently registered
+ */
+ public int size() {
+ return rules.size();
+ }
+
+ @Override
+ public Iterator iterator() {
+ return rules.iterator();
+ }
+}
diff --git a/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/core/AbstractRule.java b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/core/AbstractRule.java
new file mode 100644
index 000000000..58ec21faa
--- /dev/null
+++ b/cola-components/cola-component-ruleengine/src/main/java/com/alibaba/cola/ruleengine/core/AbstractRule.java
@@ -0,0 +1,169 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2021, Mahmoud Ben Hassine (mahmoud.benhassine@icloud.com)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package com.alibaba.cola.ruleengine.core;
+
+import com.alibaba.cola.ruleengine.api.Facts;
+import com.alibaba.cola.ruleengine.api.Rule;
+
+import java.util.Objects;
+
+/**
+ * Basic rule implementation class that provides common methods.
+ *