This is an automated email from the ASF dual-hosted git repository.

likeguo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new f7f0d49d5 [type:refactor] refactor shenyu trie (#4536)
f7f0d49d5 is described below

commit f7f0d49d55a74005789827eeef75914283f93bb6
Author: moremind <[email protected]>
AuthorDate: Sun Apr 9 21:52:31 2023 +0800

    [type:refactor] refactor shenyu trie (#4536)
    
    * [type:refactor] rename shenyu trie
    
    * [type:refactor] rename shenyu trie
    
    * fix ci
---
 .../apache/shenyu/common/config/ShenyuConfig.java  |   6 +-
 ...eMatchModeEvent.java => TrieMatchModeEnum.java} |  19 +-
 .../base/cache/CommonPluginDataSubscriber.java     |  18 +-
 .../apache/shenyu/plugin/base/trie/ShenyuTrie.java | 438 +++++++++++----------
 .../plugin/base/AbstractShenyuPluginTest.java      |   4 +-
 .../base/cache/CommonPluginDataSubscriberTest.java |   7 +-
 .../shenyu/plugin/base/trie/ShenyuTrieTest.java    | 143 ++++---
 .../starter/gateway/ShenyuConfiguration.java       |   7 +-
 .../web/controller/LocalPluginControllerTest.java  |   7 +-
 9 files changed, 377 insertions(+), 272 deletions(-)

diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java 
b/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
index c9a9a4723..358cc5ee1 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/config/ShenyuConfig.java
@@ -19,7 +19,7 @@ package org.apache.shenyu.common.config;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.concurrent.MemoryLimitCalculator;
-import org.apache.shenyu.common.enums.TrieMatchModeEvent;
+import org.apache.shenyu.common.enums.TrieMatchModeEnum;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -1857,9 +1857,9 @@ public class ShenyuConfig {
 
         /**
          * match mode.
-         * @see TrieMatchModeEvent
+         * @see TrieMatchModeEnum
          */
-        private String matchMode = 
TrieMatchModeEvent.ANT_PATH_MATCH.getMatchMode();
+        private String matchMode = 
TrieMatchModeEnum.ANT_PATH_MATCH.getMatchMode();
     
         /**
          * get match enabled.
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/TrieMatchModeEvent.java
 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/TrieMatchModeEnum.java
similarity index 66%
rename from 
shenyu-common/src/main/java/org/apache/shenyu/common/enums/TrieMatchModeEvent.java
rename to 
shenyu-common/src/main/java/org/apache/shenyu/common/enums/TrieMatchModeEnum.java
index 8bc51d374..a339cd178 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/TrieMatchModeEvent.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/TrieMatchModeEnum.java
@@ -17,10 +17,12 @@
 
 package org.apache.shenyu.common.enums;
 
+import java.util.Arrays;
+
 /**
  * Shenyu match mode event.
  */
-public enum TrieMatchModeEvent {
+public enum TrieMatchModeEnum {
     /**
      * ant path match.
      */
@@ -33,7 +35,7 @@ public enum TrieMatchModeEvent {
 
     private final String matchMode;
 
-    TrieMatchModeEvent(final String matchMode) {
+    TrieMatchModeEnum(final String matchMode) {
         this.matchMode = matchMode;
     }
 
@@ -45,4 +47,17 @@ public enum TrieMatchModeEvent {
     public String getMatchMode() {
         return matchMode;
     }
+    
+    /**
+     * get {@linkplain TrieMatchModeEnum} by match mode.
+     *
+     * @param matchMode match mode
+     * @return {@linkplain TrieMatchModeEnum}
+     */
+    public static TrieMatchModeEnum acquireTrieMatch(final String matchMode) {
+        return Arrays.stream(TrieMatchModeEnum.values())
+                .filter(e -> e.getMatchMode().equals(matchMode))
+                .findFirst()
+                .orElseThrow(() -> new IllegalArgumentException("Shenyu trie 
match mode is error, match mode:" + matchMode));
+    }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
index 49d49060f..9121037f6 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriber.java
@@ -18,6 +18,7 @@
 package org.apache.shenyu.plugin.base.cache;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.shenyu.common.config.ShenyuConfig.ShenyuTrieConfig;
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
@@ -51,14 +52,18 @@ public class CommonPluginDataSubscriber implements 
PluginDataSubscriber {
     private final Map<String, PluginDataHandler> handlerMap;
 
     private ApplicationEventPublisher eventPublisher;
+    
+    private final ShenyuTrieConfig shenyuTrieConfig;
 
     /**
      * Instantiates a new Common plugin data subscriber.
      *
      * @param pluginDataHandlerList the plugin data handler list
+     * @param shenyuTrieConfig shenyu trie config
      */
-    public CommonPluginDataSubscriber(final List<PluginDataHandler> 
pluginDataHandlerList) {
+    public CommonPluginDataSubscriber(final List<PluginDataHandler> 
pluginDataHandlerList, final ShenyuTrieConfig shenyuTrieConfig) {
         this.handlerMap = 
pluginDataHandlerList.stream().collect(Collectors.toConcurrentMap(PluginDataHandler::pluginNamed,
 e -> e));
+        this.shenyuTrieConfig = shenyuTrieConfig;
     }
 
     /**
@@ -66,11 +71,14 @@ public class CommonPluginDataSubscriber implements 
PluginDataSubscriber {
      *
      * @param pluginDataHandlerList the plugin data handler list
      * @param eventPublisher        eventPublisher is used to publish sort 
plugin event
+     * @param shenyuTrieConfig      shenyu trie config
      */
     public CommonPluginDataSubscriber(final List<PluginDataHandler> 
pluginDataHandlerList,
-                                      final ApplicationEventPublisher 
eventPublisher) {
+                                      final ApplicationEventPublisher 
eventPublisher,
+                                      final ShenyuTrieConfig shenyuTrieConfig) 
{
         this.handlerMap = 
pluginDataHandlerList.stream().collect(Collectors.toConcurrentMap(PluginDataHandler::pluginNamed,
 e -> e));
         this.eventPublisher = eventPublisher;
+        this.shenyuTrieConfig = shenyuTrieConfig;
     }
 
     /**
@@ -207,6 +215,9 @@ public class CommonPluginDataSubscriber implements 
PluginDataSubscriber {
             Optional.ofNullable(handlerMap.get(ruleData.getPluginName()))
                     .ifPresent(handler -> handler.handlerRule(ruleData));
             
MatchDataCache.getInstance().removeRuleData(ruleData.getPluginName());
+            if (!shenyuTrieConfig.getEnabled()) {
+                return;
+            }
             if (ruleData.getEnabled()) {
                 if 
(CollectionUtils.isEmpty(ruleData.getBeforeConditionDataList())) {
                     eventPublisher.publishEvent(new 
RuleTrieEvent(RuleTrieEventEnum.INSERT, ruleData));
@@ -262,6 +273,9 @@ public class CommonPluginDataSubscriber implements 
PluginDataSubscriber {
             Optional.ofNullable(handlerMap.get(ruleData.getPluginName()))
                     .ifPresent(handler -> handler.removeRule(ruleData));
             
MatchDataCache.getInstance().removeRuleData(ruleData.getPluginName());
+            if (!shenyuTrieConfig.getEnabled()) {
+                return;
+            }
             eventPublisher.publishEvent(new 
RuleTrieEvent(RuleTrieEventEnum.REMOVE, ruleData));
         }
     }
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/trie/ShenyuTrie.java
 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/trie/ShenyuTrie.java
index 8a04f0114..08a539ad4 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/trie/ShenyuTrie.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/trie/ShenyuTrie.java
@@ -19,23 +19,29 @@ package org.apache.shenyu.plugin.base.trie;
 
 import com.google.common.collect.Lists;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.cache.WindowTinyLFUMap;
 import org.apache.shenyu.common.dto.RuleData;
-import org.apache.shenyu.common.enums.TrieMatchModeEvent;
+import org.apache.shenyu.common.enums.TrieMatchModeEnum;
+import org.apache.shenyu.common.exception.ShenyuException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.stream.Collectors;
 
 public class ShenyuTrie {
-
+    
+    private static final Logger LOG = 
LoggerFactory.getLogger(ShenyuTrie.class);
+    
     private static final String WILDCARD = "*";
 
     private static final String MATCH_ALL = "**";
@@ -49,7 +55,7 @@ public class ShenyuTrie {
     private final Long pathVariableSize;
 
     /**
-     * the mode includes antPathMatch and pathPattern, please see {@linkplain 
TrieMatchModeEvent}.
+     * the mode includes antPathMatch and pathPattern, please see {@linkplain 
TrieMatchModeEnum}.
      * antPathMatch means all full match, pathPattern is used in web.
      */
     private final String matchMode;
@@ -97,124 +103,57 @@ public class ShenyuTrie {
     }
 
     /**
-     * put node to trie.
+     * put node to trie, shenyu trie support *, **, path, pathVariable 
parameters.<br>
+     * <p>* means match 0 or more character</p>
+     * <p>** means match 0 or more dictory directory</p>
+     * <p>pathVariable maybe like {name}</p>
      *
      * @param uriPath uri path
      * @param ruleData rule data
      * @param bizInfo biz info
+     * @see org.springframework.util.AntPathMatcher
+     * @see org.springframework.web.util.pattern.PathPattern
      */
     public void putNode(final String uriPath, final RuleData ruleData, final 
Object bizInfo) {
         if (StringUtils.isNotBlank(uriPath)) {
             String strippedPath = StringUtils.strip(uriPath, "/");
             String[] pathParts = StringUtils.split(strippedPath, "/");
-            if (pathParts.length > 0) {
-                ShenyuTrieNode node = root;
-                for (int i = 0; i < pathParts.length; i++) {
-                    boolean endOfPath = isMatchAllOrWildcard(pathParts[i]) && 
judgeEqual(i, pathParts.length - 1);
-                    node = putNode0(pathParts[i], node, matchMode, endOfPath);
-                    if (Objects.isNull(node)) {
-                        return;
-                    }
-                }
-                // after insert node, set full path and end of path
-                node.setFullPath(uriPath);
-                node.setEndOfPath(true);
-                node.setSelectorId(ruleData.getSelectorId());
-                node.setBizInfo(bizInfo);
-                if (Objects.isNull(node.getPathRuleCache())) {
-                    node.setPathRuleCache(new 
WindowTinyLFUMap<>(pathRuleCacheSize));
-                }
-                List<RuleData> ruleDataList = getVal(node.getPathRuleCache(), 
ruleData.getSelectorId());
-                if (CollectionUtils.isNotEmpty(ruleDataList)) {
-                    // synchronized list
-                    synchronized (ruleData.getSelectorId()) {
-                        ruleDataList.add(ruleData);
-                        
ruleDataList.sort(Comparator.comparing(RuleData::getSort));
-                        node.getPathRuleCache().put(ruleData.getSelectorId(), 
ruleDataList);
-                    }
-                } else {
-                    node.getPathRuleCache().put(ruleData.getSelectorId(), 
Lists.newArrayList(ruleData));
-                }
+            if (ArrayUtils.isEmpty(pathParts)) {
+                return;
             }
-        }
-    }
-    
-    /**
-     * put node to trie.
-     *
-     * @param segment current string
-     * @param shenyuTrieNode current trie node
-     * @param matchMode match mode
-     * @param isPathEnd end path
-     * @return {@linkplain ShenyuTrieNode}
-     */
-    private ShenyuTrieNode putNode0(final String segment, final ShenyuTrieNode 
shenyuTrieNode,
-                                    final String matchMode, final boolean 
isPathEnd) {
-        // if match mode is path pattern, when segment is * and **, return 
current node
-        if (TrieMatchModeEvent.PATH_PATTERN.getMatchMode().equals(matchMode)) {
-            if (isMatchAll(segment)) {
-                // put node, and return node
-                return this.put(segment, shenyuTrieNode, true);
-            }
-            if (isMatchWildcard(segment)) {
-                ShenyuTrieNode wildcardNode = this.put(segment, 
shenyuTrieNode, true);
-                wildcardNode.setWildcard(true);
-                return wildcardNode;
+            ShenyuTrieNode node = root;
+            TrieMatchModeEnum trieMatchMode = 
TrieMatchModeEnum.acquireTrieMatch(matchMode);
+            if (trieMatchMode.equals(TrieMatchModeEnum.PATH_PATTERN)) {
+                checkLegalPath(uriPath, pathParts);
             }
-        }
-        if 
(TrieMatchModeEvent.ANT_PATH_MATCH.getMatchMode().equals(matchMode)) {
-            if (isMatchAll(segment) && isPathEnd) {
-                return this.put(segment, shenyuTrieNode, true);
+            for (int i = 0; i < pathParts.length; i++) {
+                boolean pathEnd = judgeEqual(i, pathParts.length - 1);
+                node = putNode0(pathParts[i], node, pathEnd);
+                if (Objects.isNull(node)) {
+                    remove(StringUtils.join(pathParts, "/", 0, i), ruleData);
+                    return;
+                }
             }
-            if (isMatchWildcard(segment) && isPathEnd) {
-                ShenyuTrieNode wildcardNode = this.put(segment, 
shenyuTrieNode, true);
-                wildcardNode.setWildcard(true);
-                return wildcardNode;
+            // after insert node, set full path and end of path
+            node.setFullPath(uriPath);
+            node.setEndOfPath(true);
+            node.setSelectorId(ruleData.getSelectorId());
+            node.setBizInfo(bizInfo);
+            if (Objects.isNull(node.getPathRuleCache())) {
+                node.setPathRuleCache(new 
WindowTinyLFUMap<>(pathRuleCacheSize));
             }
-        }
-        // dynamic route
-        if (isPathVariable(segment)) {
-            ShenyuTrieNode childNode;
-            // contains key, get current pathVariable node
-            if (containsKey(shenyuTrieNode.getPathVariablesSet(), segment)) {
-                childNode = getVal(shenyuTrieNode.getPathVariablesSet(), 
segment);
-            } else {
-                childNode = new ShenyuTrieNode();
-                childNode.setMatchStr(segment);
-                childNode.setEndOfPath(false);
-                if (Objects.isNull(shenyuTrieNode.getPathVariablesSet())) {
-                    shenyuTrieNode.setPathVariablesSet(new 
WindowTinyLFUMap<>(pathVariableSize));
+            List<RuleData> ruleDataList = getVal(node.getPathRuleCache(), 
ruleData.getSelectorId());
+            if (CollectionUtils.isNotEmpty(ruleDataList)) {
+                // synchronized list
+                synchronized (ruleData.getId()) {
+                    ruleDataList.add(ruleData);
+                    ruleDataList.sort(Comparator.comparing(RuleData::getSort));
+                    node.getPathRuleCache().put(ruleData.getSelectorId(), 
ruleDataList);
                 }
-                shenyuTrieNode.getPathVariablesSet().put(segment, childNode);
-                shenyuTrieNode.setPathVariableNode(childNode);
+            } else {
+                node.getPathRuleCache().put(ruleData.getSelectorId(), 
Lists.newArrayList(ruleData));
             }
-            return childNode;
-        }
-        return this.put(segment, shenyuTrieNode, false);
-    }
-    
-    /**
-     * put node.
-     *
-     * @param segment segment
-     * @param shenyuTrieNode shenyu trie node
-     * @param endOfPath end of path
-     * @return ShenyuTrieNode
-     */
-    private ShenyuTrieNode put(final String segment, final ShenyuTrieNode 
shenyuTrieNode, final boolean endOfPath) {
-        if (Objects.isNull(shenyuTrieNode.getChildren())) {
-            shenyuTrieNode.setChildren(new WindowTinyLFUMap<>(childrenSize));
-        }
-        ShenyuTrieNode childrenNode;
-        if (containsKey(shenyuTrieNode.getChildren(), segment)) {
-            childrenNode = getVal(shenyuTrieNode.getChildren(), segment);
-        } else {
-            childrenNode = new ShenyuTrieNode();
-            childrenNode.setMatchStr(segment);
-            childrenNode.setEndOfPath(endOfPath);
-            shenyuTrieNode.getChildren().put(segment, childrenNode);
         }
-        return childrenNode;
     }
 
     /**
@@ -225,72 +164,66 @@ public class ShenyuTrie {
      * @return {@linkplain ShenyuTrieNode}
      */
     public ShenyuTrieNode match(final String uriPath, final String selectorId) 
{
-        Objects.requireNonNull(selectorId);
-        if (!StringUtils.isEmpty(uriPath)) {
-            String strippedPath = StringUtils.strip(uriPath, "/");
-            String[] pathParts = StringUtils.split(strippedPath, "/");
-            if (pathParts.length > 0) {
-                ShenyuTrieNode currentNode = root;
-                for (int i = 0; i < pathParts.length; i++) {
-                    String path = pathParts[i];
-                    boolean endPath = judgeEqual(i, pathParts.length - 1);
-                    currentNode = matchNode(path, currentNode, selectorId, 
endPath, pathParts[pathParts.length - 1]);
-                    if (Objects.nonNull(currentNode)) {
-                        // path is not end, continue to execute
-                        if (checkChildrenNotNull(currentNode) && 
!currentNode.getEndOfPath()) {
-                            continue;
-                        }
-                        // include path variable node, general node, wildcard 
node
-                        if (endPath && checkPathRuleNotNull(currentNode)
-                                && 
CollectionUtils.isNotEmpty(getVal(currentNode.getPathRuleCache(), selectorId))) 
{
-                            return currentNode;
-                        }
-                        // path is end and the match str is **, means match all
-                        if (isMatchAll(currentNode.getMatchStr()) && 
currentNode.getEndOfPath()
-                                && checkPathRuleNotNull(currentNode)
-                                && 
CollectionUtils.isNotEmpty(getVal(currentNode.getPathRuleCache(), selectorId))) 
{
-                            return currentNode;
-                        }
-                    } else {
-                        return null;
-                    }
-                }
-            }
+        String strippedPath = StringUtils.strip(uriPath, "/");
+        String[] pathParts = StringUtils.split(strippedPath, "/");
+        if (ArrayUtils.isEmpty(pathParts)) {
+            return null;
         }
-        return null;
-    }
-    
-    /**
-     * match node.
-     * <p> priority: path > * > ** > pathVariableNode </p>
-     *
-     * @param segment path segment
-     * @param node node
-     * @param selectorId selectorId
-     * @return {@linkplain ShenyuTrieNode}
-     */
-    private ShenyuTrieNode matchNode(final String segment, final 
ShenyuTrieNode node, final String selectorId,
-                                     final Boolean endOfPath, final String 
lastSegment) {
-        if (Objects.nonNull(node)) {
-            // node exist in children,first find path, avoid A plug have 
/http/**, B plug have /http/order/**
-            if (checkChildrenNotNull(node)) {
-                Pair<Boolean, ShenyuTrieNode> pair = filterTrieNode(node, 
selectorId, endOfPath, lastSegment);
-                if (pair.getLeft()) {
-                    return pair.getRight();
+        int startIndex = 0;
+        ShenyuTrieNode currentNode = root;
+        int[] matchAll = new int[pathParts.length];
+        int[] wildcard = new int[pathParts.length];
+        int[] pathVariable = new int[pathParts.length];
+        while (startIndex < pathParts.length) {
+            String key = pathParts[startIndex];
+            boolean endPath = judgeEqual(startIndex, pathParts.length - 1);
+            if (Objects.isNull(currentNode)) {
+                return null;
+            }
+            if (containsKey(currentNode.getChildren(), key)) {
+                currentNode = getVal(currentNode.getChildren(), key);
+                startIndex++;
+                if (!endPath && Objects.nonNull(currentNode) && 
!currentNode.getEndOfPath()) {
+                    continue;
+                }
+            } else if (containsKey(currentNode.getChildren(), WILDCARD) && 
wildcard[startIndex] == 0) {
+                checkAccess(wildcard, currentNode, startIndex, WILDCARD);
+                currentNode = getVal(currentNode.getChildren(), WILDCARD);
+                startIndex++;
+                if (Objects.nonNull(currentNode) && !endPath && 
!currentNode.getEndOfPath()) {
+                    continue;
                 }
-                if (containsKey(node.getChildren(), segment)) {
-                    return getVal(node.getChildren(), segment);
+            } else if (containsKey(currentNode.getChildren(), MATCH_ALL) && 
matchAll[startIndex] == 0) {
+                checkAccess(matchAll, currentNode, startIndex, MATCH_ALL);
+                currentNode = getVal(currentNode.getChildren(), MATCH_ALL);
+                startIndex++;
+                if (Objects.nonNull(currentNode) && !endPath && 
!currentNode.getEndOfPath()) {
+                    continue;
                 }
-                if (containsKey(node.getChildren(), WILDCARD)) {
-                    return getVal(node.getChildren(), WILDCARD);
+            } else if (Objects.nonNull(currentNode.getPathVariableNode())) {
+                if (pathVariable[startIndex] == 0 && 
Objects.nonNull(currentNode.getPathVariableNode())) {
+                    pathVariable[startIndex] = 1;
                 }
-                if (containsKey(node.getChildren(), MATCH_ALL)) {
-                    return getVal(node.getChildren(), MATCH_ALL);
+                currentNode = currentNode.getPathVariableNode();
+                startIndex++;
+                if (!endPath && !currentNode.getEndOfPath()) {
+                    continue;
                 }
             }
-            // if node is path variable node
-            if (Objects.nonNull(node.getPathVariableNode())) {
-                return node.getPathVariableNode();
+            if (checkNode(endPath, currentNode, selectorId)) {
+                return currentNode;
+            }
+            // resolve conflict int mathAll, wildcard, pathVariable
+            if (startIndex >= pathParts.length - 1) {
+                Pair<Integer, ShenyuTrieNode> pair = resolveConflict(wildcard, 
matchAll, pathVariable);
+                if (Objects.nonNull(pair)) {
+                    startIndex = pair.getLeft();
+                    currentNode = pair.getRight();
+                } else {
+                    return null;
+                }
+            } else {
+                startIndex++;
             }
         }
         return null;
@@ -329,7 +262,7 @@ public class ShenyuTrie {
                 // check current mapping
                 List<RuleData> ruleDataList = 
getVal(currentNode.getPathRuleCache(), ruleData.getSelectorId());
                 ruleDataList = 
Optional.ofNullable(ruleDataList).orElse(Collections.emptyList());
-                synchronized (ruleData.getSelectorId()) {
+                synchronized (ruleData.getId()) {
                     ruleDataList.removeIf(rule -> 
ruleData.getId().equals(rule.getId()));
                 }
                 if (CollectionUtils.isEmpty(ruleDataList) && 
Objects.isNull(currentNode.getChildren())
@@ -354,67 +287,152 @@ public class ShenyuTrie {
         if (StringUtils.isNotBlank(uriPath)) {
             String strippedPath = StringUtils.strip(uriPath, "/");
             String[] pathParts = StringUtils.split(strippedPath, "/");
-            if (pathParts.length > 0) {
-                return getNode0(root, pathParts);
+            // get node from path pathParts
+            ShenyuTrieNode node = root;
+            for (int i = 0; i < pathParts.length; i++) {
+                String key = pathParts[i];
+                if (Objects.nonNull(node)) {
+                    if (isPathVariable(key) && 
Objects.nonNull(node.getPathVariablesSet())) {
+                        node = node.getPathVariablesSet().get(key);
+                    } else {
+                        node = getVal(node.getChildren(), key);
+                    }
+                }
+                if (i == pathParts.length - 1) {
+                    return node;
+                }
             }
         }
         return null;
     }
     
-    private Pair<Boolean, ShenyuTrieNode> filterTrieNode(final ShenyuTrieNode 
node, final String selectorId,
-                                                         final boolean 
endOfPath, final String lastSegment) {
-        Map<String, ShenyuTrieNode> currentMap = node.getChildren();
-        List<ShenyuTrieNode> filterTrieNodes = currentMap.values().stream()
-                .filter(currentNode -> currentNode.getEndOfPath() && 
selectorId.equals(currentNode.getSelectorId())
-                        && (isMatchAllOrWildcard(currentNode.getMatchStr()) || 
(endOfPath && lastSegment.equals(currentNode.getMatchStr()))))
-                .collect(Collectors.toList());
-        if (filterTrieNodes.size() != 1) {
-            return Pair.of(Boolean.FALSE, null);
-        } else {
-            return Pair.of(Boolean.TRUE, 
filterTrieNodes.stream().findFirst().orElse(null));
+    /**
+     * check legal path.
+     *
+     * @param pathParts path array
+     */
+    private void checkLegalPath(final String uriPath, final String[] 
pathParts) {
+        //int position = Arrays.binarySearch(pathParts, 0, pathParts.length, 
MATCH_ALL);
+        for (int i = 0; i < pathParts.length; i++) {
+            if (!judgeEqual(i, pathParts.length - 1) && 
isMatchAll(pathParts[i])) {
+                LOG.error("error path:{}, error position:{}", uriPath, i);
+                throw new ShenyuException("No more pattern data allowed after 
** pattern element");
+            }
         }
     }
-
+    
     /**
-     * get node.
+     * put node to trie.
      *
-     * @param node      node
-     * @param pathParts path parts
+     * @param segment current string
+     * @param shenyuTrieNode current trie node
+     * @param pathEnd end path
      * @return {@linkplain ShenyuTrieNode}
      */
-    private ShenyuTrieNode getNode0(final ShenyuTrieNode node, final String[] 
pathParts) {
-        // get key in path part arrays
-        String key = pathParts[0];
-        String[] slice = Arrays.copyOfRange(pathParts, 1, pathParts.length);
-        // if exist one path
-        if (slice.length == 0) {
-            if (isMatchAllOrWildcard(key)) {
-                return getVal(node.getChildren(), key);
-            } else if (isPathVariable(key)) {
-                if (Objects.nonNull(node) && 
node.getPathVariableNode().getEndOfPath()) {
-                    return node.getPathVariableNode();
-                }
+    private ShenyuTrieNode putNode0(final String segment, final ShenyuTrieNode 
shenyuTrieNode, final boolean pathEnd) {
+        // if match mode is path pattern, when segment is * and **, return 
current node
+        if (TrieMatchModeEnum.PATH_PATTERN.getMatchMode().equals(matchMode)) {
+            if (isMatchAll(segment)) {
+                // put node, and return node
+                return this.put(segment, shenyuTrieNode, pathEnd);
+            }
+            if (isMatchWildcard(segment)) {
+                ShenyuTrieNode wildcardNode = this.put(segment, 
shenyuTrieNode, pathEnd);
+                wildcardNode.setWildcard(true);
+                return wildcardNode;
+            }
+        }
+        if (TrieMatchModeEnum.ANT_PATH_MATCH.getMatchMode().equals(matchMode)) 
{
+            if (isMatchAll(segment) && pathEnd) {
+                return this.put(segment, shenyuTrieNode, true);
+            }
+            if (isMatchWildcard(segment) && pathEnd) {
+                ShenyuTrieNode wildcardNode = this.put(segment, 
shenyuTrieNode, true);
+                wildcardNode.setWildcard(true);
+                return wildcardNode;
+            }
+        }
+        // dynamic route
+        if (isPathVariable(segment)) {
+            ShenyuTrieNode childNode;
+            // contains key, get current pathVariable node
+            if (containsKey(shenyuTrieNode.getPathVariablesSet(), segment)) {
+                childNode = getVal(shenyuTrieNode.getPathVariablesSet(), 
segment);
             } else {
-                if (Objects.nonNull(node) && checkChildrenNotNull(node)) {
-                    return getVal(node.getChildren(), key);
+                childNode = new ShenyuTrieNode();
+                childNode.setMatchStr(segment);
+                childNode.setEndOfPath(pathEnd);
+                if (Objects.isNull(shenyuTrieNode.getPathVariablesSet())) {
+                    shenyuTrieNode.setPathVariablesSet(new 
WindowTinyLFUMap<>(pathVariableSize));
                 }
+                shenyuTrieNode.getPathVariablesSet().put(segment, childNode);
+                shenyuTrieNode.setPathVariableNode(childNode);
             }
-            return null;
+            return childNode;
+        }
+        return this.put(segment, shenyuTrieNode, pathEnd);
+    }
+    
+    /**
+     * put node.
+     *
+     * @param segment segment
+     * @param shenyuTrieNode shenyu trie node
+     * @param pathEnd end of path
+     * @return ShenyuTrieNode
+     */
+    private ShenyuTrieNode put(final String segment, final ShenyuTrieNode 
shenyuTrieNode, final boolean pathEnd) {
+        if (Objects.isNull(shenyuTrieNode.getChildren())) {
+            shenyuTrieNode.setChildren(new WindowTinyLFUMap<>(childrenSize));
+        }
+        ShenyuTrieNode childrenNode;
+        if (containsKey(shenyuTrieNode.getChildren(), segment)) {
+            childrenNode = getVal(shenyuTrieNode.getChildren(), segment);
         } else {
-            if (isPathVariable(key)) {
-                if (Objects.isNull(node.getPathVariableNode())) {
-                    return null;
-                }
-                return this.getNode0(node.getPathVariableNode(), slice);
-            } else {
-                if (Objects.isNull(node) || Objects.isNull(node.getChildren()) 
|| Objects.isNull(getVal(node.getChildren(), key))) {
-                    return null;
-                } else {
-                    return this.getNode0(getVal(node.getChildren(), key), 
slice);
-                }
+            childrenNode = new ShenyuTrieNode();
+            childrenNode.setMatchStr(segment);
+            childrenNode.setEndOfPath(pathEnd);
+            shenyuTrieNode.getChildren().put(segment, childrenNode);
+        }
+        return childrenNode;
+    }
+    
+    private void checkAccess(final int[] arr, final ShenyuTrieNode node, final 
int startIndex, final String key) {
+        if (WILDCARD.equals(key)) {
+            if (arr[startIndex] == 0 && containsKey(node.getChildren(), 
WILDCARD)) {
+                arr[startIndex] = 1;
+            }
+        }
+        if (MATCH_ALL.equals(key)) {
+            if (arr[startIndex] == 0 && containsKey(node.getChildren(), 
MATCH_ALL)) {
+                arr[startIndex] = 1;
             }
         }
     }
+    
+    private boolean checkNode(final boolean endPath, final ShenyuTrieNode 
currentNode, final String selectorId) {
+        return endPath && Objects.nonNull(currentNode) && 
currentNode.getEndOfPath()
+                && selectorId.equals(currentNode.getSelectorId()) && 
Objects.nonNull(currentNode.getPathRuleCache())
+                && 
CollectionUtils.isNotEmpty(currentNode.getPathRuleCache().get(selectorId));
+    }
+    
+    private Pair<Integer, ShenyuTrieNode> resolveConflict(final int[] 
wildcard, final int[] matchAll, final int[] pathVariable) {
+        BitSet wildcardSet = ArrayUtils.indexesOf(wildcard, 1);
+        BitSet matchAllSet = ArrayUtils.indexesOf(matchAll, 1);
+        BitSet pathVariableSet = ArrayUtils.indexesOf(pathVariable, 1);
+        if (!wildcardSet.isEmpty()) {
+            wildcard[wildcardSet.nextSetBit(0)] = -1;
+            return Pair.of(0, root);
+        } else if (!matchAllSet.isEmpty()) {
+            matchAll[matchAllSet.nextSetBit(0)] = -1;
+            return Pair.of(0, root);
+        } else if (!pathVariableSet.isEmpty()) {
+            pathVariable[pathVariableSet.nextSetBit(0)] = -1;
+            return Pair.of(0, root);
+        } else {
+            return null;
+        }
+    }
 
     /**
      * get current node biz info.
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
index c2b450713..c96581a89 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/AbstractShenyuPluginTest.java
@@ -23,7 +23,7 @@ import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.enums.SelectorTypeEnum;
-import org.apache.shenyu.common.enums.TrieMatchModeEvent;
+import org.apache.shenyu.common.enums.TrieMatchModeEnum;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.base.cache.BaseDataCache;
@@ -247,7 +247,7 @@ public final class AbstractShenyuPluginTest {
     private void mockShenyuConfig() {
         ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
         when(context.getBean(ShenyuConfig.class)).thenReturn(new 
ShenyuConfig());
-        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEvent.ANT_PATH_MATCH.getMatchMode()));
+        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEnum.ANT_PATH_MATCH.getMatchMode()));
         SpringBeanUtils.getInstance().setApplicationContext(context);
     }
 
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriberTest.java
 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriberTest.java
index 986966358..88b80bbd3 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriberTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/CommonPluginDataSubscriberTest.java
@@ -18,10 +18,11 @@
 package org.apache.shenyu.plugin.base.cache;
 
 import com.google.common.collect.Lists;
+import org.apache.shenyu.common.config.ShenyuConfig.ShenyuTrieConfig;
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
-import org.apache.shenyu.common.enums.TrieMatchModeEvent;
+import org.apache.shenyu.common.enums.TrieMatchModeEnum;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
 import org.apache.shenyu.plugin.base.trie.ShenyuTrie;
@@ -74,7 +75,7 @@ public final class CommonPluginDataSubscriberTest {
     public void setup() {
         this.mockShenyuTrieConfig();
         ArrayList<PluginDataHandler> pluginDataHandlerList = 
Lists.newArrayList();
-        commonPluginDataSubscriber = new 
CommonPluginDataSubscriber(pluginDataHandlerList, eventPublisher);
+        commonPluginDataSubscriber = new 
CommonPluginDataSubscriber(pluginDataHandlerList, eventPublisher, new 
ShenyuTrieConfig());
         baseDataCache = BaseDataCache.getInstance();
     }
 
@@ -233,7 +234,7 @@ public final class CommonPluginDataSubscriberTest {
 
     private void mockShenyuTrieConfig() {
         ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
-        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEvent.ANT_PATH_MATCH.getMatchMode()));
+        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEnum.ANT_PATH_MATCH.getMatchMode()));
         SpringBeanUtils.getInstance().setApplicationContext(context);
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/trie/ShenyuTrieTest.java
 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/trie/ShenyuTrieTest.java
index a64c53fbf..da4dab19c 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/trie/ShenyuTrieTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/trie/ShenyuTrieTest.java
@@ -21,9 +21,9 @@ import org.apache.shenyu.common.dto.ConditionData;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.enums.OperatorEnum;
 import org.apache.shenyu.common.enums.ParamTypeEnum;
-import org.apache.shenyu.common.enums.TrieMatchModeEvent;
+import org.apache.shenyu.common.enums.TrieMatchModeEnum;
+import org.apache.shenyu.common.exception.ShenyuException;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
-import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -35,27 +35,35 @@ import java.util.Collections;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-class ShenyuTrieTest {
+public class ShenyuTrieTest {
     
-    private ShenyuTrie shenyuTrie;
+    private ShenyuTrie shenyuAntPathTrie;
+    
+    private ShenyuTrie shenyuPathPatternTrie;
 
     @BeforeEach
     public void mockAntPathShenyuTrie() {
         ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
-        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEvent.ANT_PATH_MATCH.getMatchMode()));
+        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEnum.ANT_PATH_MATCH.getMatchMode()));
+        SpringBeanUtils.getInstance().setApplicationContext(context);
+        shenyuAntPathTrie = 
SpringBeanUtils.getInstance().getBean(ShenyuTrie.class);
+        
+        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEnum.PATH_PATTERN.getMatchMode()));
         SpringBeanUtils.getInstance().setApplicationContext(context);
-        shenyuTrie = SpringBeanUtils.getInstance().getBean(ShenyuTrie.class);
+        shenyuPathPatternTrie = 
SpringBeanUtils.getInstance().getBean(ShenyuTrie.class);
     }
     
-    @AfterEach
+    @Test
     public void clear() {
-        shenyuTrie.clear();
-        Assertions.assertTrue(shenyuTrie.isEmpty());
+        shenyuAntPathTrie.clear();
+        shenyuPathPatternTrie.clear();
+        Assertions.assertTrue(shenyuAntPathTrie.isEmpty());
+        Assertions.assertTrue(shenyuPathPatternTrie.isEmpty());
     }
     
     @Test
     public void putNode() {
-        final String uri = "/a/b/c/**";
+        final String uri = "/a/b/c/**/*/cc";
         ConditionData conditionData = new ConditionData();
         conditionData.setParamType(ParamTypeEnum.URI.getName());
         conditionData.setOperator(OperatorEnum.MATCH.getAlias());
@@ -69,8 +77,35 @@ class ShenyuTrieTest {
                 .enabled(true)
                 .conditionDataList(Collections.singletonList(conditionData))
                 .build();
-        shenyuTrie.putNode(uri, ruleData, null);
-        Assertions.assertNotNull(shenyuTrie.getNode(uri));
+        shenyuAntPathTrie.putNode(uri, ruleData, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.getNode(uri));
+        Assertions.assertThrows(ShenyuException.class, () -> 
shenyuPathPatternTrie.putNode("/aa/bb/**/cc", ruleData, null));
+        shenyuPathPatternTrie.putNode("/aa/bb/cc/*/*/ee", ruleData, null);
+        
Assertions.assertNotNull(shenyuPathPatternTrie.getNode("/aa/bb/cc/*/*/ee"));
+    }
+    
+    @Test
+    public void pathPatternMatch() {
+        ConditionData conditionData = new ConditionData();
+        conditionData.setParamType(ParamTypeEnum.URI.getName());
+        conditionData.setOperator(OperatorEnum.MATCH.getAlias());
+        conditionData.setParamName("/");
+        conditionData.setParamValue("/a/b/c/**");
+        RuleData ruleData = RuleData.builder()
+                .id("1")
+                .pluginName("test")
+                .selectorId("1")
+                .name("test-plugin-rule")
+                .enabled(true)
+                .conditionDataList(Collections.singletonList(conditionData))
+                .build();
+        shenyuPathPatternTrie.putNode("/aa/bb/cc/{name}/{age}/tt", ruleData, 
null);
+        shenyuPathPatternTrie.putNode("/aa/bb/cc/*/*/ii", ruleData, null);
+        shenyuPathPatternTrie.putNode("/aa/bb/cc/**", ruleData, null);
+        
Assertions.assertNotNull(shenyuPathPatternTrie.match("/aa/bb/cc/hh/dd/ee/hh", 
"1"));
+        
Assertions.assertNotNull(shenyuPathPatternTrie.match("/aa/bb/cc/hh/dd/ee/tt", 
"1"));
+        
Assertions.assertNotNull(shenyuPathPatternTrie.match("/aa/bb/cc/xx/yy/ii", 
"1"));
+        
Assertions.assertNull(shenyuPathPatternTrie.match("/aa/bb/mm/yyy/hhhl", "1"));
     }
     
     @Test
@@ -88,8 +123,12 @@ class ShenyuTrieTest {
                 .enabled(true)
                 .conditionDataList(Collections.singletonList(conditionData))
                 .build();
-        shenyuTrie.putNode("/a/b/c/**", ruleData, null);
-        Assertions.assertNotNull(shenyuTrie.match("/a/b/c/d/e/f", "1"));
+        
+        shenyuAntPathTrie.putNode("/aa/**/*.html", ruleData, null);
+        shenyuAntPathTrie.putNode("/a/b/c/**", ruleData, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.match("/a/b/c/d/e/f", "1"));
+
+        shenyuAntPathTrie.putNode("/a/b/**/c", ruleData, null);
     
         RuleData ruleData2 = RuleData.builder()
                 .id("2")
@@ -99,17 +138,26 @@ class ShenyuTrieTest {
                 .enabled(true)
                 .conditionDataList(Collections.singletonList(conditionData))
                 .build();
-        shenyuTrie.putNode("/a/*/b/c", ruleData2, null);
-        Assertions.assertNull(shenyuTrie.match("/a/m/b/c", "1"));
-        Assertions.assertNotNull(shenyuTrie.match("/a/m/b/c", "2"));
+        shenyuAntPathTrie.putNode("/a/*/b/c", ruleData2, null);
+        Assertions.assertNull(shenyuAntPathTrie.match("/a/m/b/c", "1"));
+        Assertions.assertNotNull(shenyuAntPathTrie.match("/a/m/b/c", "2"));
+        
+        shenyuAntPathTrie.putNode("/path1/{name}/{age}", ruleData, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.match("/path1/111/222", 
"1").getFullPath(), "/path1/{name}/{age}");
+        Assertions.assertNull(shenyuAntPathTrie.match("/path1/111/222/333", 
"1"));
         
-        shenyuTrie.putNode("/path1/{name}/{age}", ruleData, null);
-        Assertions.assertNotNull(shenyuTrie.match("/path1/111/222", 
"1").getFullPath(), "/path1/{name}/{age}");
-        Assertions.assertNull(shenyuTrie.match("/path1/111/222/333", "1"));
+        shenyuAntPathTrie.putNode("path1/name/age", ruleData, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.match("path1/name/age", 
"1"));
+        Assertions.assertEquals(shenyuAntPathTrie.match("path1/name/age", 
"1").getFullPath(), "path1/name/age");
         
-        shenyuTrie.putNode("path1/name/age", ruleData, null);
-        Assertions.assertNotNull(shenyuTrie.match("path1/name/age", "1"));
-        Assertions.assertEquals(shenyuTrie.match("path1/name/age", 
"1").getFullPath(), "path1/name/age");
+        shenyuAntPathTrie.putNode("/aa/bb/cc/{name}/{age}/tt", ruleData, null);
+        shenyuAntPathTrie.putNode("/aa/bb/cc/*/*/ii", ruleData, null);
+        shenyuAntPathTrie.putNode("/aa/bb/cc/**/hh", ruleData, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.match("/aa/bb/cc/dd/ee/tt", 
"1"));
+        Assertions.assertNotNull(shenyuAntPathTrie.match("/aa/bb/cc/dd/ee/hh", 
"1"));
+        Assertions.assertNotNull(shenyuAntPathTrie.match("/aa/bb/cc/dd/ee/ii", 
"1"));
+        
Assertions.assertNotNull(shenyuAntPathTrie.match("/aa/bb/cc/dd/rr/mm/ee/hh", 
"1"));
+        
Assertions.assertNull(shenyuAntPathTrie.match("/aa/bb/cc/dd/rr/mm/ee/yy", "1"));
     }
 
     @Test
@@ -150,13 +198,13 @@ class ShenyuTrieTest {
                 .enabled(true)
                 .conditionDataList(Arrays.asList(conditionData, 
conditionData1, conditionData2, conditionData3))
                 .build();
-        shenyuTrie.putNode(Arrays.asList(uriPath, uriPath1, uriPath2, 
uriPath3), ruleData, null);
+        shenyuAntPathTrie.putNode(Arrays.asList(uriPath, uriPath1, uriPath2, 
uriPath3), ruleData, null);
         
-        Assertions.assertEquals(shenyuTrie.match("/a/b/c/d/e/f", 
"1").getFullPath(), uriPath);
-        Assertions.assertEquals(shenyuTrie.match("/a/g/c/e/ef/hi", 
"1").getFullPath(), uriPath1);
-        Assertions.assertEquals(shenyuTrie.match("/a/g/hi/def", 
"1").getFullPath(), uriPath2);
-        Assertions.assertEquals(shenyuTrie.match("/a/gh/ij/klm", 
"1").getFullPath(), uriPath2);
-        Assertions.assertNotEquals(shenyuTrie.match("/a/egh/fij/klm", 
"1").getFullPath(), uriPath3);
+        Assertions.assertEquals(shenyuAntPathTrie.match("/a/b/c/d/e/f", 
"1").getFullPath(), uriPath);
+        Assertions.assertEquals(shenyuAntPathTrie.match("/a/g/c/e/ef/hi", 
"1").getFullPath(), uriPath1);
+        Assertions.assertEquals(shenyuAntPathTrie.match("/a/g/hi/def", 
"1").getFullPath(), uriPath2);
+        Assertions.assertEquals(shenyuAntPathTrie.match("/a/gh/ij/klm", 
"1").getFullPath(), uriPath2);
+        Assertions.assertNotEquals(shenyuAntPathTrie.match("/a/egh/fij/klm", 
"1").getFullPath(), uriPath3);
     }
     
     @Test
@@ -184,10 +232,12 @@ class ShenyuTrieTest {
                 .sort(2)
                 .conditionDataList(Collections.singletonList(conditionData))
                 .build();
-        shenyuTrie.putNode("/a/b/c/**", ruleData, null);
-        shenyuTrie.putNode("/a/b/c/**", ruleData2, null);
-        shenyuTrie.remove("/a/b/c/**", ruleData2);
-        Assertions.assertNotNull(shenyuTrie.getNode("/a/b/c/**"));
+        shenyuAntPathTrie.putNode("/a/b/c/**", ruleData, null);
+        shenyuAntPathTrie.putNode("/a/b/c/**", ruleData2, null);
+        shenyuAntPathTrie.remove("/a/b/c/**", ruleData2);
+        Assertions.assertNotNull(shenyuAntPathTrie.getNode("/a/b/c/**"));
+        shenyuAntPathTrie.remove("/a/b/c/**", ruleData);
+        Assertions.assertNull(shenyuAntPathTrie.getNode("/a/b/c/**"));
     
         RuleData ruleData3 = RuleData.builder()
                 .id("3")
@@ -198,9 +248,9 @@ class ShenyuTrieTest {
                 .sort(2)
                 .conditionDataList(Collections.singletonList(conditionData))
                 .build();
-        shenyuTrie.putNode("/path1/path2", ruleData3, null);
-        shenyuTrie.remove("/path1/path2", ruleData3);
-        Assertions.assertNull(shenyuTrie.getNode("/path1/path2"));
+        shenyuAntPathTrie.putNode("/path1/path2", ruleData3, null);
+        shenyuAntPathTrie.remove("/path1/path2", ruleData3);
+        Assertions.assertNull(shenyuAntPathTrie.getNode("/path1/path2"));
     }
     
     @Test
@@ -228,15 +278,18 @@ class ShenyuTrieTest {
                 .sort(2)
                 .conditionDataList(Collections.singletonList(conditionData))
                 .build();
-        shenyuTrie.putNode("/a/b/c/**", ruleData, null);
-        shenyuTrie.putNode("/a/b/c/**", ruleData2, null);
-        Assertions.assertNotNull(shenyuTrie.getNode("/a/b/c/**"));
-        shenyuTrie.putNode("/path1/{age}/{name}", ruleData2, null);
-        Assertions.assertNotNull(shenyuTrie.getNode("/path1/{age}/{name}"));
-        shenyuTrie.putNode("/aaa/bbb/ccc", ruleData2, null);
-        Assertions.assertNotNull(shenyuTrie.getNode("/aaa/bbb/ccc"));
-        shenyuTrie.putNode("/aa/*/cc", ruleData2, null);
-        Assertions.assertNotNull(shenyuTrie.getNode("/aa/*/cc"));
+        shenyuAntPathTrie.putNode("/a/b/c/**", ruleData, null);
+        shenyuAntPathTrie.putNode("/a/b/c/**", ruleData2, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.getNode("/a/b/c/**"));
+        shenyuAntPathTrie.putNode("/path1/{age}/{name}", ruleData2, null);
+        
Assertions.assertNotNull(shenyuAntPathTrie.getNode("/path1/{age}/{name}"));
+        shenyuAntPathTrie.putNode("/aaa/bbb/ccc", ruleData2, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.getNode("/aaa/bbb/ccc"));
+        shenyuAntPathTrie.putNode("/aa/*/cc", ruleData2, null);
+        Assertions.assertNotNull(shenyuAntPathTrie.getNode("/aa/*/cc"));
+        shenyuAntPathTrie.putNode("/a/x/{name}/{age}/b", ruleData2, null);
+        shenyuAntPathTrie.putNode("/a/x/{name}/{sex}/c", ruleData2, null);
+        
Assertions.assertNotNull(shenyuAntPathTrie.getNode("/a/x/{name}/{age}/b"));
     }
     
 }
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
index 661da790f..89bd4920e 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-gateway/src/main/java/org/apache/shenyu/springboot/starter/gateway/ShenyuConfiguration.java
@@ -121,12 +121,15 @@ public class ShenyuConfiguration {
      *
      * @param pluginDataHandlerList the plugin data handler list
      * @param eventPublisher event publisher
+     * @param shenyuConfig shenyu config
      * @return the plugin data subscriber
      */
     @Bean
     public PluginDataSubscriber pluginDataSubscriber(final 
ObjectProvider<List<PluginDataHandler>> pluginDataHandlerList,
-                                                     final 
ObjectProvider<ApplicationEventPublisher> eventPublisher) {
-        return new 
CommonPluginDataSubscriber(pluginDataHandlerList.getIfAvailable(Collections::emptyList),
 eventPublisher.getIfAvailable());
+                                                     final 
ObjectProvider<ApplicationEventPublisher> eventPublisher,
+                                                     final ShenyuConfig 
shenyuConfig) {
+        return new 
CommonPluginDataSubscriber(pluginDataHandlerList.getIfAvailable(Collections::emptyList),
+                eventPublisher.getIfAvailable(), shenyuConfig.getTrie());
     }
 
     /**
diff --git 
a/shenyu-web/src/test/java/org/apache/shenyu/web/controller/LocalPluginControllerTest.java
 
b/shenyu-web/src/test/java/org/apache/shenyu/web/controller/LocalPluginControllerTest.java
index 3c5cbc01a..11e9de9b0 100644
--- 
a/shenyu-web/src/test/java/org/apache/shenyu/web/controller/LocalPluginControllerTest.java
+++ 
b/shenyu-web/src/test/java/org/apache/shenyu/web/controller/LocalPluginControllerTest.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.web.controller;
 
 import com.google.common.collect.Lists;
 import com.google.common.reflect.TypeToken;
+import org.apache.shenyu.common.config.ShenyuConfig.ShenyuTrieConfig;
 import org.apache.shenyu.common.dto.ConditionData;
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
@@ -29,7 +30,7 @@ import org.apache.shenyu.common.enums.LoadBalanceEnum;
 import org.apache.shenyu.common.enums.OperatorEnum;
 import org.apache.shenyu.common.enums.ParamTypeEnum;
 import org.apache.shenyu.common.enums.PluginEnum;
-import org.apache.shenyu.common.enums.TrieMatchModeEvent;
+import org.apache.shenyu.common.enums.TrieMatchModeEnum;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.common.utils.JsonUtils;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
@@ -91,7 +92,7 @@ public final class LocalPluginControllerTest {
     public void setup() {
         this.mockShenyuTrieConfig();
         ArrayList<PluginDataHandler> pluginDataHandlerList = 
Lists.newArrayList();
-        subscriber = new CommonPluginDataSubscriber(pluginDataHandlerList, 
eventPublisher);
+        subscriber = new CommonPluginDataSubscriber(pluginDataHandlerList, 
eventPublisher, new ShenyuTrieConfig());
         mockMvc = MockMvcBuilders.standaloneSetup(new 
LocalPluginController(subscriber))
                 .build();
         baseDataCache = BaseDataCache.getInstance();
@@ -491,7 +492,7 @@ public final class LocalPluginControllerTest {
 
     private void mockShenyuTrieConfig() {
         ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
-        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEvent.ANT_PATH_MATCH.getMatchMode()));
+        when(context.getBean(ShenyuTrie.class)).thenReturn(new 
ShenyuTrie(100L, 100L, 100L, TrieMatchModeEnum.ANT_PATH_MATCH.getMatchMode()));
         SpringBeanUtils.getInstance().setApplicationContext(context);
     }
 }

Reply via email to