You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by he...@apache.org on 2023/06/02 13:17:30 UTC

[shenyu] branch master updated: [type: feature] add websocket synchronization method for e2e-springcloud-case (#4698)

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

hefengen 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 f6c5d8053 [type: feature] add websocket synchronization method for e2e-springcloud-case  (#4698)
f6c5d8053 is described below

commit f6c5d8053db7e11b3031b93fec858182e8b27337
Author: SeaChess <80...@users.noreply.github.com>
AuthorDate: Fri Jun 2 21:17:20 2023 +0800

    [type: feature] add websocket synchronization method for e2e-springcloud-case  (#4698)
    
    * add springcloud-case v1-1
    
    * add springcloud-case v1-2
    
    * add springcloud-case v1-3
    
    ---------
    
    Co-authored-by: xiaoyu <xi...@apache.org>
---
 .github/workflows/e2e.yaml                         |   2 +-
 shenyu-e2e/shenyu-e2e-case/pom.xml                 |  12 +-
 .../shenyu-e2e-case-http}/pom.xml                  |  10 +-
 .../e2e/testcase/divide/DividePluginCases.java     | 353 ++++++++++++
 .../e2e/testcase/divide/DividePluginTest.java}     |  12 +-
 .../src/test/resources/docker-compose.h2.yml       |   0
 .../src/test/resources/docker-compose.mysql.yml    |   0
 .../src/test/resources/docker-compose.postgres.yml |   0
 .../src/test/resources/docker-compose.test.yml     |   0
 .../src/test/resources/log4j2.xml                  |   0
 .../{ => shenyu-e2e-case-spring-cloud}/pom.xml     |  24 +-
 .../testcase/springcloud/DataSynApolloTest.java}   |   7 +-
 .../e2e/testcase/springcloud/DataSynHttpTest.java} |   7 +-
 .../testcase/springcloud/DataSynNacosTest.java}    |   7 +-
 .../testcase/springcloud/DataSynZookeeperTest.java |  76 +++
 .../springcloud/SpringCloudPluginCases.java}       | 323 ++++++-----
 .../springcloud/SpringCloudPluginTest.java         | 162 ++++++
 .../src/test/resources/docker-compose.h2.yml       |  73 +++
 .../src/test/resources/log4j2.xml                  |   0
 .../shenyu/e2e/client/admin/AdminClient.java       |  81 ++-
 .../shenyu/e2e/client/gateway/GatewayClient.java   |  60 +-
 .../org/apache/shenyu/e2e/matcher/RuleMatcher.java |   4 +-
 .../apache/shenyu/e2e/matcher/SelectorMatcher.java |   4 +-
 .../shenyu/e2e/client/admin/AdminClientTest.java   |  28 +-
 shenyu-e2e/shenyu-e2e-common/pom.xml               |  17 +
 .../org/apache/shenyu/e2e}/model/MatchMode.java    |   2 +-
 .../java/org/apache/shenyu/e2e}/model/Plugin.java  |   4 +-
 .../apache/shenyu/e2e}/model/ResourcesData.java    |   6 +-
 .../org/apache/shenyu/e2e}/model/SelectorType.java |   2 +-
 .../org/apache/shenyu/e2e}/model/ShenYuResult.java |   2 +-
 .../apache/shenyu/e2e}/model/data/Condition.java   |   2 +-
 .../shenyu/e2e/model/data/ConditionData.java       | 156 ++++++
 .../org/apache/shenyu/e2e/model/data/MetaData.java | 532 ++++++++++++++++++
 .../apache/shenyu/e2e}/model/data/PluginData.java  |   2 +-
 .../shenyu/e2e}/model/data/QueryCondition.java     |   2 +-
 .../shenyu/e2e}/model/data/ResourceData.java       |   2 +-
 .../shenyu/e2e/model/data/RuleCacheData.java       | 572 +++++++++++++++++++
 .../apache/shenyu/e2e}/model/data/RuleData.java    |  11 +-
 .../shenyu/e2e}/model/data/RuleQueryCondition.java |   2 +-
 .../shenyu/e2e}/model/data/SearchCondition.java    |   2 +-
 .../shenyu/e2e/model/data/SelectorCacheData.java   | 623 +++++++++++++++++++++
 .../shenyu/e2e}/model/data/SelectorData.java       |  10 +-
 .../e2e}/model/data/SelectorQueryCondition.java    |   2 +-
 .../shenyu/e2e}/model/handle/DivideRuleHandle.java |   2 +-
 .../shenyu/e2e/model/handle/DivideUpstream.java    | 308 ++++++++++
 .../shenyu/e2e}/model/handle/PluginHandle.java     |   2 +-
 .../shenyu/e2e}/model/handle/RuleHandle.java       |   2 +-
 .../e2e/model/handle/SpringCloudRuleHandle.java    | 155 +++++
 .../model/handle/SpringCloudSelectorHandle.java    | 189 +++++++
 .../apache/shenyu/e2e}/model/handle/Upstreams.java |   4 +-
 .../shenyu/e2e}/model/request/RequestVO.java       |   2 +-
 .../e2e}/model/response/FakeResourceDTO.java       |   2 +-
 .../shenyu/e2e}/model/response/LoginInfo.java      |   2 +-
 .../shenyu/e2e/model/response/MetaDataDTO.java     | 324 +++++++++++
 .../e2e}/model/response/PaginatedResources.java    |   2 +-
 .../shenyu/e2e}/model/response/Pagination.java     |   2 +-
 .../shenyu/e2e}/model/response/PluginDTO.java      |   2 +-
 .../shenyu/e2e}/model/response/ResourceDTO.java    |   2 +-
 .../apache/shenyu/e2e}/model/response/RuleDTO.java | 123 +++-
 .../e2e}/model/response/SearchedResources.java     |   2 +-
 .../shenyu/e2e}/model/response/SelectorDTO.java    | 150 ++++-
 .../shenyu/e2e/template}/ResourceDataTemplate.java |  35 +-
 shenyu-e2e/shenyu-e2e-engine/pom.xml               |   7 +
 .../e2e/engine/handler/AdminDataSynHandler.java    |  79 +++
 .../e2e/engine/handler/GatewayDataSynHandler.java  |  78 +++
 .../e2e/engine/scenario}/function/HttpChecker.java |   3 +-
 .../engine/scenario}/function/HttpCheckers.java    |   2 +-
 .../engine/scenario}/function/HttpVerifier.java    |   2 +-
 .../e2e/engine/scenario}/function/HttpWaiting.java |   2 +-
 .../engine/scenario}/function/WaitForHelper.java   |   2 +-
 .../scenario/specification/BeforeEachSpec.java     |   2 +-
 .../specification/ScenarioSpecLogProxy.java        |   2 +-
 .../specification/ShenYuAfterEachSpec.java         |   3 +-
 .../specification/ShenYuBeforeEachSpec.java        |  17 +-
 .../scenario}/specification/ShenYuCaseSpec.java    |   8 +-
 .../specification/ShenYuScenarioSpec.java          |   6 +-
 .../e2e/engine/service/DockerServiceCompose.java   |  98 +++-
 .../apache/shenyu/e2e/engine/ShenYuEngineTest.java |   6 +-
 .../e2e/engine}/function/WaitForHelperTest.java    |   4 +-
 79 files changed, 4517 insertions(+), 310 deletions(-)

diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml
index 36dcd068a..e30d62f70 100644
--- a/.github/workflows/e2e.yaml
+++ b/.github/workflows/e2e.yaml
@@ -140,7 +140,7 @@ jobs:
           storage: ${{ matrix.storage }}
         run: |
           bash ./shenyu-e2e/script/storage_init.sh
-          ./mvnw -B -f ./shenyu-e2e/pom.xml -pl shenyu-e2e-case -Dstorage=${{ matrix.storage }} test
+          ./mvnw -B -f ./shenyu-e2e/pom.xml -pl shenyu-e2e-case/shenyu-e2e-case-http -Dstorage=${{ matrix.storage }} test
 
   requirement:
     name: e2e
diff --git a/shenyu-e2e/shenyu-e2e-case/pom.xml b/shenyu-e2e/shenyu-e2e-case/pom.xml
index f3015d251..31b03e7a5 100644
--- a/shenyu-e2e/shenyu-e2e-case/pom.xml
+++ b/shenyu-e2e/shenyu-e2e-case/pom.xml
@@ -16,15 +16,23 @@
   ~ limitations under the License.
   -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+         xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.shenyu</groupId>
         <artifactId>shenyu-e2e</artifactId>
         <version>0.0.1-SNAPSHOT</version>
     </parent>
+
     <artifactId>shenyu-e2e-case</artifactId>
 
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>shenyu-e2e-case-http</module>
+        <module>shenyu-e2e-case-spring-cloud</module>
+    </modules>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.shenyu</groupId>
@@ -38,4 +46,4 @@
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
     </dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/shenyu-e2e/shenyu-e2e-common/pom.xml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/pom.xml
similarity index 91%
copy from shenyu-e2e/shenyu-e2e-common/pom.xml
copy to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/pom.xml
index 8b80a5a50..911ac61b8 100644
--- a/shenyu-e2e/shenyu-e2e-common/pom.xml
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/pom.xml
@@ -18,11 +18,13 @@
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
+
     <parent>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu-e2e</artifactId>
+        <artifactId>shenyu-e2e-case</artifactId>
         <version>0.0.1-SNAPSHOT</version>
     </parent>
-    <artifactId>shenyu-e2e-common</artifactId>
-    
-</project>
\ No newline at end of file
+
+    <artifactId>shenyu-e2e-case-http</artifactId>
+
+</project>
diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/divide/DividePluginCases.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/divide/DividePluginCases.java
new file mode 100644
index 000000000..fd242af94
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/divide/DividePluginCases.java
@@ -0,0 +1,353 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.testcase.divide;
+
+import com.google.common.collect.Lists;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuAfterEachSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuBeforeEachSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuCaseSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuScenarioSpec;
+import io.restassured.http.Method;
+import org.apache.shenyu.e2e.model.Plugin;
+import org.apache.shenyu.e2e.model.data.Condition.Operator;
+import org.apache.shenyu.e2e.model.data.Condition.ParamType;
+import org.apache.shenyu.e2e.engine.scenario.ShenYuScenarioProvider;
+import org.apache.shenyu.e2e.engine.scenario.specification.ScenarioSpec;
+
+import java.util.List;
+
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newCondition;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newConditions;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newDivideRuleHandle;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newRuleBuilder;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newSelectorBuilder;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newUpstreamsBuilder;
+import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.exists;
+import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.notExists;
+import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString;
+
+public class DividePluginCases implements ShenYuScenarioProvider {
+    private static final String ANYTHING = "/anything";
+
+    @Override
+    public List<ScenarioSpec> get() {
+        return Lists.newArrayList(
+                testDivideWithUriEquals(),
+                testDivideWithUriPathPattern(),
+                testDivideWithUriStartWith(),
+                testDivideWithEndWith(),
+                testDivideWithMethodGet(),
+                testDivideWithMethodPost(),
+                testDivideWithMethodPut(),
+                testDivideWithMethodDelete()
+        );
+    }
+
+    private ShenYuScenarioSpec testDivideWithUriEquals() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide uri =]")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(newConditions(ParamType.URI, Operator.EQUAL, ANYTHING))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(newConditions(ParamType.URI, Operator.EQUAL, ANYTHING))
+                                                .build()
+                                )
+                                .checker(notExists(ANYTHING))
+                                .waiting(exists(ANYTHING))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(ANYTHING)
+                                .addNotExists("/anythin")
+                                .addNotExists(ANYTHING + "/x")
+                                .addNotExists("/get")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithUriPathPattern() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide uri path_pattern]")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(newConditions(ParamType.URI, Operator.PATH_PATTERN, "/anything/xx/**"))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(newConditions(ParamType.URI, Operator.PATH_PATTERN, "/anything/xx/**"))
+                                                .build()
+                                )
+                                .checker(notExists(ANYTHING + "/xx/yyy"))
+                                .waiting(exists(ANYTHING + "/xx/yyy"))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(ANYTHING + "/xx")
+                                .addExists(ANYTHING + "/xx/yy")
+                                .addNotExists(ANYTHING + "/x")
+                                .addNotExists(ANYTHING + "/x")
+                                .addExists(Method.POST, ANYTHING + "/xx/yy")
+                                .addExists(Method.PUT, ANYTHING + "/xx/yy")
+                                .addExists(Method.DELETE, ANYTHING + "/xx/yy")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithUriStartWith() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide uri starts_with]")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(newConditions(ParamType.URI, Operator.STARTS_WITH, ANYTHING + "/xx"))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(newConditions(ParamType.URI, Operator.STARTS_WITH, ANYTHING + "/xx"))
+                                                .build()
+                                )
+                                .checker(notExists(ANYTHING + "/xx"))
+                                .waiting(exists(ANYTHING + "/xx"))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(ANYTHING + "/xx/yy")
+                                .addExists(ANYTHING + "/xxx")
+                                .addNotExists(ANYTHING + "/x")
+                                .addExists(Method.POST, ANYTHING + "/xx/yy")
+                                .addExists(Method.PUT, ANYTHING + "/xx/yy")
+                                .addExists(Method.DELETE, ANYTHING + "/xx/yy")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithEndWith() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide uri ends_with]")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(newConditions(ParamType.URI, Operator.ENDS_WITH, "/200"))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(newConditions(ParamType.URI, Operator.ENDS_WITH, "/200"))
+                                                .build()
+                                )
+                                .checker(notExists(ANYTHING + "/200"))
+                                .waiting(exists(ANYTHING + "/200"))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addVerifier("/status/200", isEmptyOrNullString())
+                                .addExists("/anything/200")
+                                .addNotExists(ANYTHING)
+                                .addNotExists("/status/300")
+                                .addNotExists("/anything/300")
+                                .addVerifier(Method.PUT, "/status/200", isEmptyOrNullString())
+                                .addVerifier(Method.POST, "/status/200", isEmptyOrNullString())
+                                .addVerifier(Method.DELETE, "/status/200", isEmptyOrNullString())
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithMethodGet() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide method GET")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "GET"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "GET"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build()
+                                )
+                                .checker(notExists(Method.GET, ANYTHING))
+                                .waiting(exists(Method.GET, ANYTHING))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(Method.GET, ANYTHING)
+                                .addNotExists(Method.POST, ANYTHING)
+                                .addNotExists(Method.PUT, ANYTHING)
+                                .addNotExists(Method.DELETE, ANYTHING)
+                                .addNotExists(Method.GET, "/anythin")
+                                .addNotExists(Method.GET, ANYTHING + "/x")
+                                .addNotExists(Method.GET, "/get")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithMethodPost() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide method POST")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "POST"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "POST"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build()
+                                )
+                                .checker(notExists(Method.POST, ANYTHING))
+                                .waiting(exists(Method.POST, ANYTHING))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(Method.POST, ANYTHING)
+                                .addNotExists(Method.GET, ANYTHING)
+                                .addNotExists(Method.PUT, ANYTHING)
+                                .addNotExists(Method.DELETE, ANYTHING)
+                                .addNotExists(Method.POST, "/anythin")
+                                .addNotExists(Method.POST, ANYTHING + "/x")
+                                .addNotExists(Method.POST, "/get")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithMethodPut() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide method PUT")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "PUT"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "PUT"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build()
+                                )
+                                .checker(notExists(Method.PUT, ANYTHING))
+                                .waiting(exists(Method.PUT, ANYTHING))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(Method.PUT, ANYTHING)
+                                .addNotExists(Method.GET, ANYTHING)
+                                .addNotExists(Method.POST, ANYTHING)
+                                .addNotExists(Method.DELETE, ANYTHING)
+                                .addNotExists(Method.PUT, "/anythin")
+                                .addNotExists(Method.PUT, ANYTHING + "/x")
+                                .addNotExists(Method.PUT, "/get")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+
+    public ShenYuScenarioSpec testDivideWithMethodDelete() {
+        return ShenYuScenarioSpec.builder()
+                .name("single-divide method DELETE")
+                .beforeEachSpec(
+                        ShenYuBeforeEachSpec.builder()
+                                .addSelectorAndRule(
+                                        newSelectorBuilder("httpbin", Plugin.DIVIDE)
+                                                .handle(newUpstreamsBuilder("httpbin:80"))
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "DELETE"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build(),
+                                        newRuleBuilder("rule")
+                                                .handle(newDivideRuleHandle())
+                                                .conditionList(Lists.newArrayList(
+                                                        newCondition(ParamType.METHOD, Operator.EQUAL, "DELETE"),
+                                                        newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                ))
+                                                .build()
+                                )
+                                .checker(notExists(Method.DELETE, ANYTHING))
+                                .waiting(exists(Method.DELETE, ANYTHING))
+                                .build()
+                )
+                .caseSpec(
+                        ShenYuCaseSpec.builder()
+                                .addExists(Method.DELETE, ANYTHING)
+                                .addNotExists(Method.GET, ANYTHING)
+                                .addNotExists(Method.PUT, ANYTHING)
+                                .addNotExists(Method.POST, ANYTHING)
+                                .addNotExists(Method.DELETE, "/anythin")
+                                .addNotExists(Method.DELETE, ANYTHING + "/x")
+                                .addNotExists(Method.DELETE, "/get")
+                                .build()
+                )
+                .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
+                .build();
+    }
+}
\ No newline at end of file
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/plugin/PluginsTest.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/divide/DividePluginTest.java
similarity index 92%
rename from shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/plugin/PluginsTest.java
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/divide/DividePluginTest.java
index b594996e0..f2301d828 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/plugin/PluginsTest.java
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/java/org/apache/shenyu/e2e/testcase/divide/DividePluginTest.java
@@ -15,12 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.plugin;
+package org.apache.shenyu.e2e.testcase.divide;
 
 import org.apache.shenyu.e2e.client.admin.AdminClient;
-import org.apache.shenyu.e2e.client.admin.model.ResourcesData;
-import org.apache.shenyu.e2e.client.admin.model.ResourcesData.Resource;
-import org.apache.shenyu.e2e.client.admin.model.response.SelectorDTO;
 import org.apache.shenyu.e2e.client.gateway.GatewayClient;
 import org.apache.shenyu.e2e.engine.annotation.ShenYuScenario;
 import org.apache.shenyu.e2e.engine.annotation.ShenYuTest;
@@ -31,6 +28,9 @@ import org.apache.shenyu.e2e.engine.config.ShenYuEngineConfigure.ServiceType;
 import org.apache.shenyu.e2e.engine.scenario.specification.AfterEachSpec;
 import org.apache.shenyu.e2e.engine.scenario.specification.BeforeEachSpec;
 import org.apache.shenyu.e2e.engine.scenario.specification.CaseSpec;
+import org.apache.shenyu.e2e.model.ResourcesData;
+import org.apache.shenyu.e2e.model.ResourcesData.Resource;
+import org.apache.shenyu.e2e.model.response.SelectorDTO;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
@@ -60,7 +60,7 @@ import java.util.List;
         },
         dockerComposeFile = "classpath:./docker-compose.{storage:h2}.yml"
 )
-public class PluginsTest {
+public class DividePluginTest {
     List<String> selectorIds = Lists.newArrayList();
     
     @BeforeAll
@@ -87,7 +87,7 @@ public class PluginsTest {
         spec.getWaiting().waitFor(gateway);
     }
     
-    @ShenYuScenario(provider = DividePluginCases.class)
+    @ShenYuScenario(provider = org.apache.shenyu.e2e.testcase.divide.DividePluginCases.class)
     void testDivide(GatewayClient gateway, CaseSpec spec) {
         spec.getVerifiers().forEach(verifier -> verifier.verify(gateway.getHttpRequesterSupplier().get()));
     }
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.h2.yml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.h2.yml
similarity index 100%
rename from shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.h2.yml
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.h2.yml
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.mysql.yml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.mysql.yml
similarity index 100%
rename from shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.mysql.yml
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.mysql.yml
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.postgres.yml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.postgres.yml
similarity index 100%
rename from shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.postgres.yml
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.postgres.yml
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.test.yml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.test.yml
similarity index 100%
rename from shenyu-e2e/shenyu-e2e-case/src/test/resources/docker-compose.test.yml
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/docker-compose.test.yml
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/resources/log4j2.xml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/log4j2.xml
similarity index 100%
copy from shenyu-e2e/shenyu-e2e-case/src/test/resources/log4j2.xml
copy to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-http/src/test/resources/log4j2.xml
diff --git a/shenyu-e2e/shenyu-e2e-case/pom.xml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/pom.xml
similarity index 68%
copy from shenyu-e2e/shenyu-e2e-case/pom.xml
copy to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/pom.xml
index f3015d251..7610e6ff1 100644
--- a/shenyu-e2e/shenyu-e2e-case/pom.xml
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/pom.xml
@@ -15,27 +15,25 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
+
     <parent>
         <groupId>org.apache.shenyu</groupId>
-        <artifactId>shenyu-e2e</artifactId>
+        <artifactId>shenyu-e2e-case</artifactId>
         <version>0.0.1-SNAPSHOT</version>
     </parent>
-    <artifactId>shenyu-e2e-case</artifactId>
 
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.shenyu</groupId>
-            <artifactId>shenyu-e2e-engine</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
-        </dependency>
+    <artifactId>shenyu-e2e-case-spring-cloud</artifactId>
 
+    <dependencies>
         <dependency>
             <groupId>org.apache.shenyu</groupId>
-            <artifactId>shenyu-e2e-client</artifactId>
-            <version>0.0.1-SNAPSHOT</version>
+            <artifactId>shenyu-plugin-base</artifactId>
+            <version>2.6.0-SNAPSHOT</version>
+            <scope>test</scope>
         </dependency>
     </dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynApolloTest.java
similarity index 83%
copy from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
copy to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynApolloTest.java
index 2d0522be5..31c857315 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynApolloTest.java
@@ -15,7 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.testcase.springcloud;
 
-public interface PluginHandle {
+/**
+ * Testing the correctness of Apollo data synchronization method.
+ */
+public class DataSynApolloTest {
 }
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynHttpTest.java
similarity index 83%
copy from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
copy to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynHttpTest.java
index 2d0522be5..ecbc32d79 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynHttpTest.java
@@ -15,7 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.testcase.springcloud;
 
-public interface PluginHandle {
+/**
+ * Testing the correctness of Http data synchronization method.
+ */
+public class DataSynHttpTest {
 }
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynNacosTest.java
similarity index 83%
copy from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
copy to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynNacosTest.java
index 2d0522be5..3f1e32acc 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynNacosTest.java
@@ -15,7 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.testcase.springcloud;
 
-public interface PluginHandle {
+/**
+ * Testing the correctness of Nacos data synchronization method.
+ */
+public class DataSynNacosTest {
 }
diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynZookeeperTest.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynZookeeperTest.java
new file mode 100644
index 000000000..a3d6ab603
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/DataSynZookeeperTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.testcase.springcloud;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.shenyu.e2e.client.admin.AdminClient;
+import org.apache.shenyu.e2e.client.gateway.GatewayClient;
+import org.apache.shenyu.e2e.engine.annotation.ShenYuTest;
+import org.apache.shenyu.e2e.engine.config.ShenYuEngineConfigure;
+import org.apache.shenyu.e2e.model.data.MetaData;
+import org.apache.shenyu.e2e.model.data.RuleCacheData;
+import org.apache.shenyu.e2e.model.data.SelectorCacheData;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+@ShenYuTest(
+        mode = ShenYuEngineConfigure.Mode.HOST,
+        services = {
+                @ShenYuTest.ServiceConfigure(
+                        serviceName = "admin",
+                        port = 9095,
+                        baseUrl = "http://{hostname:localhost}:9095",
+                        parameters = {
+                                @ShenYuTest.Parameter(key = "username", value = "admin"),
+                                @ShenYuTest.Parameter(key = "password", value = "123456"),
+                                @ShenYuTest.Parameter(key = "dataSyn", value = "zookeeper")
+                        }
+                ),
+                @ShenYuTest.ServiceConfigure(
+                        serviceName = "gateway",
+                        port = 9195,
+                        baseUrl = "http://{hostname:localhost}:9195",
+                        type = ShenYuEngineConfigure.ServiceType.SHENYU_GATEWAY,
+                        parameters = {
+                                @ShenYuTest.Parameter(key = "application", value = "spring.cloud.discovery.enabled:true,eureka.client.enabled:true"),
+                                @ShenYuTest.Parameter(key = "dataSyn", value = "zookeeper")
+                        }
+                )
+        },
+        dockerComposeFile = "classpath:./docker-compose.{storage:h2}.yml"
+)
+/**
+ * Testing the correctness of Apollo data synchronization method.
+ */
+public class DataSynZookeeperTest {
+
+    @Test
+    void setup(AdminClient adminClient, GatewayClient gatewayClient) throws InterruptedException, JsonProcessingException {
+        adminClient.login();
+        Thread.sleep(3000);
+        List<MetaData> metaDataCacheList = gatewayClient.getMetaDataCache();
+        List<SelectorCacheData> selectorCacheList = gatewayClient.getSelectorCache();
+        List<RuleCacheData> ruleCacheList = gatewayClient.getRuleCache();
+        Assertions.assertEquals(2, selectorCacheList.size());
+        Assertions.assertEquals(13, metaDataCacheList.size());
+        Assertions.assertEquals(14, ruleCacheList.size());
+    }
+
+}
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/plugin/DividePluginCases.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/SpringCloudPluginCases.java
similarity index 56%
rename from shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/plugin/DividePluginCases.java
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/SpringCloudPluginCases.java
index 80707afb2..3e17b0c68 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/plugin/DividePluginCases.java
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/SpringCloudPluginCases.java
@@ -15,266 +15,291 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.plugin;
+package org.apache.shenyu.e2e.testcase.springcloud;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.Lists;
 import io.restassured.http.Method;
-import org.apache.shenyu.e2e.client.admin.model.Plugin;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition.Operator;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition.ParamType;
+import org.apache.shenyu.e2e.model.Plugin;
+import org.apache.shenyu.e2e.model.data.Condition;
+import org.apache.shenyu.e2e.model.handle.DivideUpstream;
+import org.apache.shenyu.e2e.model.handle.SpringCloudRuleHandle;
+import org.apache.shenyu.e2e.model.handle.SpringCloudSelectorHandle;
 import org.apache.shenyu.e2e.engine.scenario.ShenYuScenarioProvider;
 import org.apache.shenyu.e2e.engine.scenario.specification.ScenarioSpec;
-import org.apache.shenyu.e2e.testcase.common.specification.ShenYuAfterEachSpec;
-import org.apache.shenyu.e2e.testcase.common.specification.ShenYuBeforeEachSpec;
-import org.apache.shenyu.e2e.testcase.common.specification.ShenYuCaseSpec;
-import org.apache.shenyu.e2e.testcase.common.specification.ShenYuScenarioSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuAfterEachSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuBeforeEachSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuCaseSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.ShenYuScenarioSpec;
+import org.junit.jupiter.api.Assertions;
 
 import java.util.List;
 
-import static org.apache.shenyu.e2e.testcase.common.ResourceDataTemplate.newCondition;
-import static org.apache.shenyu.e2e.testcase.common.ResourceDataTemplate.newConditions;
-import static org.apache.shenyu.e2e.testcase.common.ResourceDataTemplate.newDivideRuleHandle;
-import static org.apache.shenyu.e2e.testcase.common.ResourceDataTemplate.newRuleBuilder;
-import static org.apache.shenyu.e2e.testcase.common.ResourceDataTemplate.newSelectorBuilder;
-import static org.apache.shenyu.e2e.testcase.common.ResourceDataTemplate.newUpstreamsBuilder;
-import static org.apache.shenyu.e2e.testcase.common.function.HttpCheckers.exists;
-import static org.apache.shenyu.e2e.testcase.common.function.HttpCheckers.notExists;
-import static org.hamcrest.text.IsEmptyString.isEmptyOrNullString;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newCondition;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newConditions;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newRuleBuilder;
+import static org.apache.shenyu.e2e.template.ResourceDataTemplate.newSelectorBuilder;
+import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.exists;
+import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.notExists;
+
+public class SpringCloudPluginCases implements ShenYuScenarioProvider {
+
+    private static final String TEST = "/springboot/test";
+
+    private static final ObjectMapper mapper = new ObjectMapper();
 
-public class DividePluginCases implements ShenYuScenarioProvider {
-    private static final String ANYTHING = "/anything";
-    
     @Override
     public List<ScenarioSpec> get() {
+        List<DivideUpstream> divideUpstreams = Lists.newArrayList();
+        divideUpstreams.add(DivideUpstream.builder().protocol("http://")
+                .upstreamUrl("springcloud:8884").status(true).timestamp(System.currentTimeMillis())
+                .weight(50).warmup(10).build());
         return Lists.newArrayList(
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide uri =]")
+                        .name("single-spring-cloud uri =]")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
-                                                        .conditionList(newConditions(ParamType.URI, Operator.EQUAL, ANYTHING))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test"))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
-                                                        .conditionList(newConditions(ParamType.URI, Operator.EQUAL, ANYTHING))
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test"))
                                                         .build()
                                         )
-                                        .checker(notExists(ANYTHING))
-                                        .waiting(exists(ANYTHING))
+                                        .checker(notExists("/springcloud/test"))
+                                        .waiting(exists("/springcloud/test"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(ANYTHING)
-                                        .addNotExists("/anythin")
-                                        .addNotExists(ANYTHING + "/x")
+                                        .addExists("/springcloud/test")
+                                        .addNotExists("/springcloud/te")
+                                        .addNotExists( "/put")
                                         .addNotExists("/get")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build(),
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide uri path_pattern]")
+                        .name("single-spring-cloud uri path_pattern]")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
-                                                        .conditionList(newConditions(ParamType.URI, Operator.PATH_PATTERN, "/anything/xx/**"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.PATH_PATTERN, "/springcloud/test/**"))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
-                                                        .conditionList(newConditions(ParamType.URI, Operator.PATH_PATTERN, "/anything/xx/**"))
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.PATH_PATTERN, "/springcloud/test/**"))
                                                         .build()
                                         )
-                                        .checker(notExists(ANYTHING + "/xx/yyy"))
-                                        .waiting(exists(ANYTHING + "/xx/yyy"))
+                                        .checker(notExists("/springcloud/test/xx"))
+                                        .waiting(exists("/springcloud/test/xx"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(ANYTHING + "/xx")
-                                        .addExists(ANYTHING + "/xx/yy")
-                                        .addNotExists(ANYTHING + "/x")
-                                        .addNotExists(ANYTHING + "/x")
-                                        .addExists(Method.POST, ANYTHING + "/xx/yy")
-                                        .addExists(Method.PUT, ANYTHING + "/xx/yy")
-                                        .addExists(Method.DELETE, ANYTHING + "/xx/yy")
+                                        .addExists("/springcloud/test/xx")
+                                        .addExists("/springcloud/test/yy")
+                                        .addNotExists("/springcloud/te")
+                                        .addNotExists("/springcloud/td")
+                                        .addExists(Method.POST, "/springcloud/test/xx")
+                                        .addExists(Method.PUT, "/springcloud/test/xx")
+                                        .addExists(Method.DELETE, "/springcloud/test/xx")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build(),
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide uri starts_with]")
+                        .name("single-spring-cloud uri starts_with]")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
-                                                        .conditionList(newConditions(ParamType.URI, Operator.STARTS_WITH, ANYTHING + "/xx"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.STARTS_WITH, "/springcloud/test"))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
-                                                        .conditionList(newConditions(ParamType.URI, Operator.STARTS_WITH, ANYTHING + "/xx"))
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.STARTS_WITH, "/springcloud/test"))
                                                         .build()
                                         )
-                                        .checker(notExists(ANYTHING + "/xx"))
-                                        .waiting(exists(ANYTHING + "/xx"))
+                                        .checker(notExists("/springcloud/test"))
+                                        .waiting(exists("/springcloud/test"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(ANYTHING + "/xx/yy")
-                                        .addExists(ANYTHING + "/xxx")
-                                        .addNotExists(ANYTHING + "/x")
-                                        .addExists(Method.POST, ANYTHING + "/xx/yy")
-                                        .addExists(Method.PUT, ANYTHING + "/xx/yy")
-                                        .addExists(Method.DELETE, ANYTHING + "/xx/yy")
+                                        .addExists("/springcloud/test/xx")
+                                        .addNotExists("/springcloud/testt")
+                                        .addNotExists("/springcloud/tes")
+                                        .addExists(Method.POST, "/springcloud/test/xx")
+                                        .addExists(Method.PUT, "/springcloud/test/xx")
+                                        .addExists(Method.DELETE, "/springcloud/test/xx")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build(),
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide uri ends_with]")
+                        .name("single-spring-cloud uri ends_with]")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
-                                                        .conditionList(newConditions(ParamType.URI, Operator.ENDS_WITH, "/200"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.ENDS_WITH, "/test"))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
-                                                        .conditionList(newConditions(ParamType.URI, Operator.ENDS_WITH, "/200"))
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
+                                                        .conditionList(newConditions(Condition.ParamType.URI, Condition.Operator.ENDS_WITH, "/test"))
                                                         .build()
                                         )
-                                        .checker(notExists(ANYTHING + "/200"))
-                                        .waiting(exists(ANYTHING + "/200"))
+                                        .checker(notExists("/springcloud/test"))
+                                        .waiting(exists("/spring/test"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addVerifier("/status/200", isEmptyOrNullString())
-                                        .addExists("/anything/200")
-                                        .addNotExists(ANYTHING)
-                                        .addNotExists("/status/300")
-                                        .addNotExists("/anything/300")
-                                        .addVerifier(Method.PUT, "/status/200", isEmptyOrNullString())
-                                        .addVerifier(Method.POST, "/status/200", isEmptyOrNullString())
-                                        .addVerifier(Method.DELETE, "/status/200", isEmptyOrNullString())
+                                        .addExists("/springcloud/test")
+                                        .addNotExists("/springcloud")
+                                        .addNotExists("/springcloud/tested")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build(),
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide method GET")
+                        .name("single-spring-cloud method GET")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "GET"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "GET"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "GET"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "GET"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build()
                                         )
-                                        .checker(notExists(Method.GET, ANYTHING))
-                                        .waiting(exists(Method.GET, ANYTHING))
+                                        .checker(notExists(Method.GET, "/springcloud/test"))
+                                        .waiting(exists(Method.GET, "/springcloud/test"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(Method.GET, ANYTHING)
-                                        .addNotExists(Method.POST, ANYTHING)
-                                        .addNotExists(Method.PUT, ANYTHING)
-                                        .addNotExists(Method.DELETE, ANYTHING)
-                                        .addNotExists(Method.GET, "/anythin")
-                                        .addNotExists(Method.GET, ANYTHING + "/x")
+                                        .addExists(Method.GET, "/springcloud/test")
+                                        .addNotExists(Method.POST, "/springcloud/test")
+                                        .addNotExists(Method.PUT, "/springcloud/test")
+                                        .addNotExists(Method.DELETE, "/springcloud/test")
+                                        .addNotExists(Method.GET, "/springcloud/tes")
+                                        .addNotExists(Method.GET, "/springcloud/tests")
                                         .addNotExists(Method.GET, "/get")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build(),
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide method POST")
+                        .name("single-spring-cloud method POST")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "POST"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "POST"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "POST"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "POST"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build()
                                         )
-                                        .checker(notExists(Method.POST, ANYTHING))
-                                        .waiting(exists(Method.POST, ANYTHING))
+                                        .checker(notExists(Method.POST, TEST))
+                                        .waiting(exists(Method.POST, TEST))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(Method.POST, ANYTHING)
-                                        .addNotExists(Method.GET, ANYTHING)
-                                        .addNotExists(Method.PUT, ANYTHING)
-                                        .addNotExists(Method.DELETE, ANYTHING)
-                                        .addNotExists(Method.POST, "/anythin")
-                                        .addNotExists(Method.POST, ANYTHING + "/x")
-                                        .addNotExists(Method.POST, "/get")
+                                        .addExists(Method.POST, "/springcloud/test")
+                                        .addNotExists(Method.GET, "/springcloud/test")
+                                        .addNotExists(Method.PUT, "/springcloud/test")
+                                        .addNotExists(Method.DELETE, "/springcloud/test")
+                                        .addNotExists(Method.POST, "/springcloud/tes")
+                                        .addNotExists(Method.POST, "/springcloud/testx")
+                                        .addNotExists(Method.POST, "/post")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build(),
                 ShenYuScenarioSpec.builder()
-                        .name("single-divide method PUT")
+                        .name("single-spring-cloud method PUT")
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "PUT"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "PUT"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "PUT"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "PUT"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build()
                                         )
-                                        .checker(notExists(Method.PUT, ANYTHING))
-                                        .waiting(exists(Method.PUT, ANYTHING))
+                                        .checker(notExists(Method.PUT, "/springcloud/test"))
+                                        .waiting(exists(Method.PUT, "/springcloud/test"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(Method.PUT, ANYTHING)
-                                        .addNotExists(Method.GET, ANYTHING)
-                                        .addNotExists(Method.POST, ANYTHING)
-                                        .addNotExists(Method.DELETE, ANYTHING)
-                                        .addNotExists(Method.PUT, "/anythin")
-                                        .addNotExists(Method.PUT, ANYTHING + "/x")
-                                        .addNotExists(Method.PUT, "/get")
+                                        .addExists(Method.PUT, "/springcloud/test")
+                                        .addNotExists(Method.GET, "/springcloud/test")
+                                        .addNotExists(Method.POST, "/springcloud/test")
+                                        .addNotExists(Method.DELETE, "/springcloud/test")
+                                        .addNotExists(Method.PUT, "/springcloud/tes")
+                                        .addNotExists(Method.PUT, "/springcloud/testt")
+                                        .addNotExists(Method.PUT, "/put")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
@@ -284,38 +309,52 @@ public class DividePluginCases implements ShenYuScenarioProvider {
                         .beforeEachSpec(
                                 ShenYuBeforeEachSpec.builder()
                                         .addSelectorAndRule(
-                                                newSelectorBuilder("httpbin", Plugin.DIVIDE)
-                                                        .handle(newUpstreamsBuilder("httpbin:80"))
+                                                newSelectorBuilder("selector", Plugin.SPRING_CLOUD)
+                                                        .handle(SpringCloudSelectorHandle.builder().serviceId("springCloud-test")
+                                                                .gray(true)
+                                                                .divideUpstreams(divideUpstreams)
+                                                                .build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "DELETE"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "DELETE"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build(),
                                                 newRuleBuilder("rule")
-                                                        .handle(newDivideRuleHandle())
+                                                        .handle(SpringCloudRuleHandle.builder().loadBalance("hash").timeout(3000).build())
                                                         .conditionList(Lists.newArrayList(
-                                                                newCondition(ParamType.METHOD, Operator.EQUAL, "DELETE"),
-                                                                newCondition(ParamType.URI, Operator.EQUAL, ANYTHING)
+                                                                newCondition(Condition.ParamType.METHOD, Condition.Operator.EQUAL, "DELETE"),
+                                                                newCondition(Condition.ParamType.URI, Condition.Operator.EQUAL, "/springcloud/test")
                                                         ))
                                                         .build()
                                         )
-                                        .checker(notExists(Method.DELETE, ANYTHING))
-                                        .waiting(exists(Method.DELETE, ANYTHING))
+                                        .checker(notExists(Method.DELETE, "/springcloud/test"))
+                                        .waiting(exists(Method.DELETE, "/springcloud/test"))
                                         .build()
                         )
                         .caseSpec(
                                 ShenYuCaseSpec.builder()
-                                        .addExists(Method.DELETE, ANYTHING)
-                                        .addNotExists(Method.GET, ANYTHING)
-                                        .addNotExists(Method.PUT, ANYTHING)
-                                        .addNotExists(Method.POST, ANYTHING)
-                                        .addNotExists(Method.DELETE, "/anythin")
-                                        .addNotExists(Method.DELETE, ANYTHING + "/x")
-                                        .addNotExists(Method.DELETE, "/get")
+                                        .addExists(Method.DELETE, "/springcloud/test")
+                                        .addNotExists(Method.GET, "/springcloud/test")
+                                        .addNotExists(Method.PUT, "/springcloud/test")
+                                        .addNotExists(Method.POST, "/springcloud/test")
+                                        .addNotExists(Method.DELETE, "/springcloud/tes")
+                                        .addNotExists(Method.DELETE, "/springcloud/testt")
+                                        .addNotExists(Method.DELETE, "/delete")
                                         .build()
                         )
                         .afterEachSpec(ShenYuAfterEachSpec.DEFAULT)
                         .build()
         );
     }
+
+    public static void verifierUri(String handle) throws JsonProcessingException {
+        SpringCloudSelectorHandle springCloudSelectorHandle = mapper.readValue(handle, SpringCloudSelectorHandle.class);
+        Assertions.assertEquals("springCloud-test", springCloudSelectorHandle.getServiceId());
+        Assertions.assertEquals(false, springCloudSelectorHandle.getGray());
+        DivideUpstream divideUpstream = springCloudSelectorHandle.getDivideUpstreams().get(0);
+        Assertions.assertEquals(50, divideUpstream.getWeight());
+        Assertions.assertEquals(600000, divideUpstream.getWarmup());
+        Assertions.assertEquals("http://", divideUpstream.getProtocol());
+        Assertions.assertEquals(true, divideUpstream.isStatus());
+    }
 }
diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/SpringCloudPluginTest.java b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/SpringCloudPluginTest.java
new file mode 100644
index 000000000..646a88847
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/java/org/apache/shenyu/e2e/testcase/springcloud/SpringCloudPluginTest.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.testcase.springcloud;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.shenyu.e2e.client.admin.AdminClient;
+import org.apache.shenyu.e2e.client.gateway.GatewayClient;
+import org.apache.shenyu.e2e.engine.annotation.ShenYuScenario;
+import org.apache.shenyu.e2e.engine.annotation.ShenYuTest;
+import org.apache.shenyu.e2e.engine.config.ShenYuEngineConfigure;
+import org.apache.shenyu.e2e.engine.scenario.specification.AfterEachSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.BeforeEachSpec;
+import org.apache.shenyu.e2e.engine.scenario.specification.CaseSpec;
+import org.apache.shenyu.e2e.model.ResourcesData;
+import org.apache.shenyu.e2e.model.data.MetaData;
+import org.apache.shenyu.e2e.model.data.RuleCacheData;
+import org.apache.shenyu.e2e.model.data.SelectorCacheData;
+import org.apache.shenyu.e2e.model.response.MetaDataDTO;
+import org.apache.shenyu.e2e.model.response.RuleDTO;
+import org.apache.shenyu.e2e.model.response.SelectorDTO;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.testcontainers.shaded.com.google.common.collect.Lists;
+
+import java.util.List;
+
+@ShenYuTest(
+        mode = ShenYuEngineConfigure.Mode.DOCKER,
+        services = {
+                @ShenYuTest.ServiceConfigure(
+                        serviceName = "admin",
+                        port = 9095,
+                        baseUrl = "http://{hostname:localhost}:9095",
+                        parameters = {
+                                @ShenYuTest.Parameter(key = "username", value = "admin"),
+                                @ShenYuTest.Parameter(key = "password", value = "123456"),
+                        }
+                ),
+                @ShenYuTest.ServiceConfigure(
+                        serviceName = "gateway",
+                        port = 9195,
+                        baseUrl = "http://{hostname:localhost}:9195",
+                        type = ShenYuEngineConfigure.ServiceType.SHENYU_GATEWAY,
+                        parameters = {
+                                @ShenYuTest.Parameter(key = "application", value = "spring.cloud.discovery.enabled:true,eureka.client.enabled:true"),
+                                @ShenYuTest.Parameter(key = "dataSyn", value = "websocket")
+                        }
+                )
+        },
+        dockerComposeFile = "classpath:./docker-compose.{storage:h2}.yml"
+)
+/**
+ * Testing spring-cloud plugin.
+ */
+public class SpringCloudPluginTest {
+    List<String> selectorIds = Lists.newArrayList();
+
+    @BeforeAll
+    static void setup(AdminClient adminClient, GatewayClient gatewayClient) throws InterruptedException, JsonProcessingException {
+        adminClient.login();
+        Thread.sleep(10000);
+        List<SelectorDTO> selectorDTOList = adminClient.listAllSelectors();
+        List<MetaDataDTO> metaDataDTOList = adminClient.listAllMetaData();
+        List<RuleDTO> ruleDTOList = adminClient.listAllRules();
+        Assertions.assertEquals(2, selectorDTOList.size());
+        Assertions.assertEquals(13, metaDataDTOList.size());
+        Assertions.assertEquals(14, ruleDTOList.size());
+
+        for (SelectorDTO selectorDTO :selectorDTOList) {
+            if (selectorDTO.getHandle() != null && selectorDTO.getHandle() != "") {
+                SpringCloudPluginCases.verifierUri(selectorDTO.getHandle());
+            }
+        }
+
+        List<MetaData> metaDataCacheList = gatewayClient.getMetaDataCache();
+        List<SelectorCacheData> selectorCacheList = gatewayClient.getSelectorCache();
+        List<RuleCacheData> ruleCacheList = gatewayClient.getRuleCache();
+        Assertions.assertEquals(2, selectorCacheList.size());
+        Assertions.assertEquals(13, metaDataCacheList.size());
+        Assertions.assertEquals(14, ruleCacheList.size());
+
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("id","8");
+        formData.add("name","springCloud");
+        formData.add("enabled","true");
+        formData.add("role","Proxy");
+        formData.add("sort","200");
+        adminClient.startPlugin("8", formData);
+        String id = "";
+        for (int i = 0; i < selectorDTOList.size(); i++) {
+            if (selectorDTOList.get(i).getHandle() != "") {
+                id = selectorDTOList.get(i).getId();
+            }
+        }
+        adminClient.deleteSelectors(id);
+        selectorDTOList = adminClient.listAllSelectors();
+        Assertions.assertEquals(1, selectorDTOList.size());
+    }
+
+    @BeforeEach
+    void before(AdminClient client, GatewayClient gateway, BeforeEachSpec spec) {
+        spec.getChecker().check(gateway);
+
+        ResourcesData resources = spec.getResources();
+        for (ResourcesData.Resource res : resources.getResources()) {
+            SelectorDTO dto = client.create(res.getSelector());
+            selectorIds.add(dto.getId());
+
+            res.getRules().forEach(rule -> {
+                rule.setSelectorId(dto.getId());
+                client.create(rule);
+            });
+        }
+
+        spec.getWaiting().waitFor(gateway);
+    }
+
+    @ShenYuScenario(provider = SpringCloudPluginCases.class)
+    void testSpringCloud(GatewayClient gateway, CaseSpec spec) {
+        spec.getVerifiers().forEach(verifier -> verifier.verify(gateway.getHttpRequesterSupplier().get()));
+    }
+
+    @AfterEach
+    void before(AdminClient client, GatewayClient gateway, AfterEachSpec spec) {
+        spec.getDeleter().delete(client, selectorIds);
+        spec.getPostChecker().check(gateway);
+        selectorIds = Lists.newArrayList();
+    }
+
+    @AfterAll
+    static void teardown(AdminClient client) {
+        client.deleteAllSelectors();
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("id","8");
+        formData.add("name","springCloud");
+        formData.add("enabled","false");
+        formData.add("role","Proxy");
+        formData.add("sort","200");
+        client.startPlugin("8", formData);
+    }
+}
+
diff --git a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/resources/docker-compose.h2.yml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/resources/docker-compose.h2.yml
new file mode 100644
index 000000000..b579b4822
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/resources/docker-compose.h2.yml
@@ -0,0 +1,73 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+version: '2.3'
+
+services:
+  shenyu-zk:
+    image: zookeeper:3.5
+    restart: always
+    ports:
+      - "2182:2182"
+
+  admin:
+    image: apache/shenyu-admin:latest
+    expose:
+      - 9095
+    ports:
+      - "9095:9095"
+    volumes:
+      - ../../../../../shenyu-admin/target/classes/application.yml:/opt/shenyu-admin/conf/application.yml
+
+  eureka:
+    image: shenyu-examples-eureka:latest
+    restart: always
+    expose:
+      - 8761
+    ports:
+      - "8761:8761"
+    depends_on:
+      - admin
+
+  springcloud:
+    image: shenyu-examples-springcloud:latest
+    restart: always
+    environment:
+      - shenyu.register.serverLists=http://admin:9095
+      - eureka.client.serviceUrl.defaultZone=http://eureka:8761/eureka/
+    expose:
+      - 8884
+    ports:
+      - "8884:8884"
+    depends_on:
+      - eureka
+
+  gateway:
+    image: apache/shenyu-bootstrap:latest
+    environment:
+#      - shenyu.sync.websocket.urls=ws://admin:9095/websocket
+      - shenyu.sync.zookeeper.url=localhost:2182
+      - eureka.client.serviceUrl.defaultZone=http://eureka:8761/eureka/
+    expose:
+      - 9095
+    depends_on:
+      - admin
+      - eureka
+      - springcloud
+      - shenyu-zk
+    volumes:
+        - ../../../../../shenyu-bootstrap/target/classes/application.yml:/opt/shenyu-bootstrap/conf/application.yml
\ No newline at end of file
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/resources/log4j2.xml b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/resources/log4j2.xml
similarity index 100%
rename from shenyu-e2e/shenyu-e2e-case/src/test/resources/log4j2.xml
rename to shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-spring-cloud/src/test/resources/log4j2.xml
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java
index 9481b8f9a..a4e0b5043 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java
+++ b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/AdminClient.java
@@ -24,26 +24,27 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import org.apache.shenyu.e2e.annotation.ShenYuAdminClient;
-import org.apache.shenyu.e2e.client.admin.model.Plugin;
-import org.apache.shenyu.e2e.client.admin.model.ShenYuResult;
-import org.apache.shenyu.e2e.client.admin.model.data.QueryCondition;
-import org.apache.shenyu.e2e.client.admin.model.data.ResourceData;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleData;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleQueryCondition;
-import org.apache.shenyu.e2e.client.admin.model.data.SearchCondition;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorData;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorQueryCondition;
-import org.apache.shenyu.e2e.client.admin.model.response.FakeResourceDTO;
-import org.apache.shenyu.e2e.client.admin.model.response.LoginInfo;
-import org.apache.shenyu.e2e.client.admin.model.response.PaginatedResources;
-import org.apache.shenyu.e2e.client.admin.model.response.PluginDTO;
-import org.apache.shenyu.e2e.client.admin.model.response.ResourceDTO;
-import org.apache.shenyu.e2e.client.admin.model.response.RuleDTO;
-import org.apache.shenyu.e2e.client.admin.model.response.SearchedResources;
-import org.apache.shenyu.e2e.client.admin.model.response.SelectorDTO;
 import org.apache.shenyu.e2e.common.IdManagers.Rules;
 import org.apache.shenyu.e2e.common.IdManagers.Selectors;
 import org.apache.shenyu.e2e.common.NameUtils;
+import org.apache.shenyu.e2e.model.Plugin;
+import org.apache.shenyu.e2e.model.ShenYuResult;
+import org.apache.shenyu.e2e.model.data.QueryCondition;
+import org.apache.shenyu.e2e.model.data.ResourceData;
+import org.apache.shenyu.e2e.model.data.RuleData;
+import org.apache.shenyu.e2e.model.data.RuleQueryCondition;
+import org.apache.shenyu.e2e.model.data.SearchCondition;
+import org.apache.shenyu.e2e.model.data.SelectorData;
+import org.apache.shenyu.e2e.model.data.SelectorQueryCondition;
+import org.apache.shenyu.e2e.model.response.FakeResourceDTO;
+import org.apache.shenyu.e2e.model.response.LoginInfo;
+import org.apache.shenyu.e2e.model.response.MetaDataDTO;
+import org.apache.shenyu.e2e.model.response.PaginatedResources;
+import org.apache.shenyu.e2e.model.response.PluginDTO;
+import org.apache.shenyu.e2e.model.response.ResourceDTO;
+import org.apache.shenyu.e2e.model.response.RuleDTO;
+import org.apache.shenyu.e2e.model.response.SearchedResources;
+import org.apache.shenyu.e2e.model.response.SelectorDTO;
 import org.junit.jupiter.api.Assertions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -60,7 +61,7 @@ import java.util.List;
 import java.util.Properties;
 import java.util.stream.Collectors;
 
-import static org.apache.shenyu.e2e.client.admin.model.data.SearchCondition.QUERY_ALL;
+import static org.apache.shenyu.e2e.model.data.SearchCondition.QUERY_ALL;
 
 /**
  * A client to connect to ShenYu Admin.
@@ -77,7 +78,7 @@ public class AdminClient {
     private final ObjectMapper mapper = new ObjectMapper();
     
     private final String scenarioId;
-    
+
     private final String baseURL;
 
     private final ImmutableMap<String, String> loginInfo;
@@ -92,6 +93,9 @@ public class AdminClient {
 
     private static final TypeReference<SearchedResources<FakeResourceDTO>> FAKE_VALUE_TYPE = new TypeReference<SearchedResources<FakeResourceDTO>>() {
     };
+
+    private static final TypeReference<List<MetaDataDTO>> SEARCHED_METADATAS_TYPE_REFERENCE = new TypeReference<List<MetaDataDTO>>() {
+    };
     
     public AdminClient(String scenarioId, String baseURL, Properties properties) {
         Preconditions.checkArgument(properties.containsKey("username"), "Property username does not exist");
@@ -180,6 +184,10 @@ public class AdminClient {
                 .build();
         return list("/rule/list/search", condition, SEARCHED_RULES_TYPE_REFERENCE, v -> v);
     }
+
+    public List<MetaDataDTO> listAllMetaData() {
+        return getMetaDataList("/meta-data/findAll", SEARCHED_METADATAS_TYPE_REFERENCE, v -> v);
+    }
     
     private <T extends ResourceDTO, OUT> List<OUT> list(String uri, QueryCondition condition, TypeReference<SearchedResources<T>> valueType, Mapper<T, OUT> mapper) {
         List<OUT> result = Lists.newArrayList();
@@ -197,6 +205,15 @@ public class AdminClient {
         
         return result;
     }
+
+    private <T extends ResourceDTO, OUT> List<OUT> getMetaDataList(String uri, TypeReference<List<T>> valueType, Mapper<T, OUT> mapper) {
+        List<OUT> result = Lists.newArrayList();
+        List<T> resources = getSearch(uri, valueType);
+        resources.stream()
+                .map(mapper)
+                .forEach(result::add);
+        return result;
+    }
     
     /**
      * Fetch the selectors by the given conditions.
@@ -260,13 +277,22 @@ public class AdminClient {
         HttpEntity<SearchCondition> entity = new HttpEntity<>(searchCondition, basicAuth);
         ResponseEntity<ShenYuResult> response = template.postForEntity(baseURL + uri, entity, ShenYuResult.class);
         ShenYuResult rst = assertAndGet(response, "query success");
-        
+
         return Assertions.assertDoesNotThrow(
                 () -> mapper.readValue(rst.getData().traverse(), valueType),
                 "checking cast to SearchedResources<T>"
         );
     }
-    
+
+    private <T extends ResourceDTO> List<T> getSearch(String uri, TypeReference<List<T>> valueType) {
+        ResponseEntity<ShenYuResult> response = template.exchange(baseURL + uri, HttpMethod.GET, new HttpEntity<>(basicAuth), ShenYuResult.class);
+        ShenYuResult rst = assertAndGet(response, "query success");
+        return Assertions.assertDoesNotThrow(
+                () -> mapper.readValue(rst.getData().traverse(), valueType),
+                "checking cast to SearchedResources<T>"
+        );
+    }
+
     public SelectorDTO create(SelectorData selector) {
         SelectorDTO dto = create("/selector", selector);
         Selectors.INSTANCE.put(selector.getName(), dto.getId());
@@ -420,6 +446,19 @@ public class AdminClient {
         return rst;
     }
 
+    public void startPlugin(String id, MultiValueMap<String, String> formData) {
+        putResource("/plugin", id, SelectorDTO.class, formData);
+    }
+
+    private <T extends ResourceDTO> T putResource(String uri, String id, Class<T> valueType, MultiValueMap<String, String> formData) {
+        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, basicAuth);
+        ResponseEntity<ShenYuResult> response = template.exchange(baseURL + uri + "/" + id, HttpMethod.PUT, requestEntity, ShenYuResult.class);
+        Assertions.assertEquals(HttpStatus.OK, response.getStatusCode(), "checking http status");
+        ShenYuResult rst = response.getBody();
+        Assertions.assertNotNull(rst, "checking http response body");
+        return Assertions.assertDoesNotThrow(() -> rst.toObject(valueType), "checking cast data to " + valueType.getSimpleName());
+    }
+
     @FunctionalInterface
     interface Mapper<IN, OUT> extends Function<IN, OUT> {
     
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/gateway/GatewayClient.java b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/gateway/GatewayClient.java
index d04bca4ee..ff379bdec 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/gateway/GatewayClient.java
+++ b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/gateway/GatewayClient.java
@@ -17,14 +17,26 @@
 
 package org.apache.shenyu.e2e.client.gateway;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import io.restassured.response.Response;
 import io.restassured.specification.RequestSpecification;
 import org.apache.shenyu.e2e.annotation.ShenYuGatewayClient;
 import org.apache.shenyu.e2e.common.RequestLogConsumer;
+import org.apache.shenyu.e2e.model.data.MetaData;
+import org.apache.shenyu.e2e.model.data.RuleCacheData;
+import org.apache.shenyu.e2e.model.data.SelectorCacheData;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
+import org.springframework.boot.web.client.RestTemplateBuilder;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestTemplate;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.function.Supplier;
 
@@ -44,6 +56,10 @@ public class GatewayClient {
     
     private final Properties properties;
 
+    private static final RestTemplate template = new RestTemplateBuilder().build();
+
+    private static final ObjectMapper mapper = new ObjectMapper();
+
     public GatewayClient(String scenarioId, String baseUrl, Properties properties) {
         this.scenarioId = scenarioId;
         this.baseUrl = baseUrl;
@@ -80,5 +96,47 @@ public class GatewayClient {
                 })
                 .when();
     }
-    
+
+    public List<MetaData> getMetaDataCache() throws JsonProcessingException {
+        ResponseEntity<List> response = template.exchange(baseUrl + "/actuator/metadata", HttpMethod.GET, null, List.class);
+        List body = response.getBody();
+        Map<String, MetaData> s = (Map<String, MetaData>) body.get(0);
+        List<MetaData> metaDataList = new ArrayList<>();
+        for (Map.Entry entry : s.entrySet()) {
+            String json = mapper.writeValueAsString(entry.getValue());
+            MetaData metaData = mapper.readValue(json, MetaData.class);
+            metaDataList.add(metaData);
+        }
+        return metaDataList;
+    }
+
+    public List<SelectorCacheData> getSelectorCache() throws JsonProcessingException {
+        ResponseEntity<List> response = template.exchange(baseUrl + "/actuator/selectorData", HttpMethod.GET, null, List.class);
+        List body = response.getBody();
+        Map<String, SelectorCacheData> s = (Map<String, SelectorCacheData>) body.get(0);
+        List<SelectorCacheData> selectorDataList = new ArrayList<>();
+        for (Map.Entry entry : s.entrySet()) {
+            List list = (List) entry.getValue();
+            String json = mapper.writeValueAsString(list.get(0));
+            SelectorCacheData selectorData = mapper.readValue(json, SelectorCacheData.class);
+            selectorDataList.add(selectorData);
+        }
+        return selectorDataList;
+    }
+
+    public List<RuleCacheData> getRuleCache() throws JsonProcessingException {
+        ResponseEntity<List> response = template.exchange(baseUrl + "/actuator/ruleData", HttpMethod.GET, null, List.class);
+        List body = response.getBody();
+        Map<String, RuleCacheData> s = (Map<String, RuleCacheData>) body.get(0);
+        List<RuleCacheData> ruleDataList = new ArrayList<>();
+        for (Map.Entry entry : s.entrySet()) {
+            List list = (List) entry.getValue();
+            for (int i = 0; i < list.size(); i++) {
+                String json = mapper.writeValueAsString(list.get(i));
+                RuleCacheData ruleData = mapper.readValue(json, RuleCacheData.class);
+                ruleDataList.add(ruleData);
+            }
+        }
+        return ruleDataList;
+    }
 }
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/RuleMatcher.java b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/RuleMatcher.java
index df570d00c..02e0bcda9 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/RuleMatcher.java
+++ b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/RuleMatcher.java
@@ -19,8 +19,8 @@ package org.apache.shenyu.e2e.matcher;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleData;
-import org.apache.shenyu.e2e.client.admin.model.response.RuleDTO;
+import org.apache.shenyu.e2e.model.data.RuleData;
+import org.apache.shenyu.e2e.model.response.RuleDTO;
 import org.json.JSONException;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.skyscreamer.jsonassert.JSONCompareMode;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/SelectorMatcher.java b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/SelectorMatcher.java
index 65f6e5dbd..34af17bb3 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/SelectorMatcher.java
+++ b/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/matcher/SelectorMatcher.java
@@ -19,8 +19,8 @@ package org.apache.shenyu.e2e.matcher;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorData;
-import org.apache.shenyu.e2e.client.admin.model.response.SelectorDTO;
+import org.apache.shenyu.e2e.model.data.SelectorData;
+import org.apache.shenyu.e2e.model.response.SelectorDTO;
 import org.json.JSONException;
 import org.skyscreamer.jsonassert.JSONAssert;
 import org.skyscreamer.jsonassert.JSONCompareMode;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/test/java/org/apache/shenyu/e2e/client/admin/AdminClientTest.java b/shenyu-e2e/shenyu-e2e-client/src/test/java/org/apache/shenyu/e2e/client/admin/AdminClientTest.java
index f75682646..ef0a25977 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/test/java/org/apache/shenyu/e2e/client/admin/AdminClientTest.java
+++ b/shenyu-e2e/shenyu-e2e-client/src/test/java/org/apache/shenyu/e2e/client/admin/AdminClientTest.java
@@ -19,20 +19,20 @@ package org.apache.shenyu.e2e.client.admin;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.google.common.collect.Lists;
-import org.apache.shenyu.e2e.client.admin.model.MatchMode;
-import org.apache.shenyu.e2e.client.admin.model.Plugin;
-import org.apache.shenyu.e2e.client.admin.model.SelectorType;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition.Operator;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition.ParamType;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleData;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorData;
-import org.apache.shenyu.e2e.client.admin.model.handle.DivideRuleHandle;
-import org.apache.shenyu.e2e.client.admin.model.handle.Upstreams;
-import org.apache.shenyu.e2e.client.admin.model.handle.Upstreams.Upstream;
-import org.apache.shenyu.e2e.client.admin.model.response.RuleDTO;
-import org.apache.shenyu.e2e.client.admin.model.response.SearchedResources;
-import org.apache.shenyu.e2e.client.admin.model.response.SelectorDTO;
+import org.apache.shenyu.e2e.model.MatchMode;
+import org.apache.shenyu.e2e.model.Plugin;
+import org.apache.shenyu.e2e.model.SelectorType;
+import org.apache.shenyu.e2e.model.data.Condition;
+import org.apache.shenyu.e2e.model.data.Condition.Operator;
+import org.apache.shenyu.e2e.model.data.Condition.ParamType;
+import org.apache.shenyu.e2e.model.data.RuleData;
+import org.apache.shenyu.e2e.model.data.SelectorData;
+import org.apache.shenyu.e2e.model.handle.DivideRuleHandle;
+import org.apache.shenyu.e2e.model.handle.Upstreams;
+import org.apache.shenyu.e2e.model.handle.Upstreams.Upstream;
+import org.apache.shenyu.e2e.model.response.RuleDTO;
+import org.apache.shenyu.e2e.model.response.SearchedResources;
+import org.apache.shenyu.e2e.model.response.SelectorDTO;
 import org.apache.shenyu.e2e.matcher.RuleMatcher;
 import org.apache.shenyu.e2e.matcher.SelectorMatcher;
 import org.assertj.core.api.Assertions;
diff --git a/shenyu-e2e/shenyu-e2e-common/pom.xml b/shenyu-e2e/shenyu-e2e-common/pom.xml
index 8b80a5a50..db823d2b8 100644
--- a/shenyu-e2e/shenyu-e2e-common/pom.xml
+++ b/shenyu-e2e/shenyu-e2e-common/pom.xml
@@ -24,5 +24,22 @@
         <version>0.0.1-SNAPSHOT</version>
     </parent>
     <artifactId>shenyu-e2e-common</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-annotations</artifactId>
+        </dependency>
+    </dependencies>
     
 </project>
\ No newline at end of file
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/MatchMode.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/MatchMode.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/MatchMode.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/MatchMode.java
index c7231d95e..7ab2bd85d 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/MatchMode.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/MatchMode.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model;
+package org.apache.shenyu.e2e.model;
 
 import com.fasterxml.jackson.annotation.JsonValue;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/Plugin.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/Plugin.java
similarity index 97%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/Plugin.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/Plugin.java
index cac4bb67a..54dd8ad21 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/Plugin.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/Plugin.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model;
+package org.apache.shenyu.e2e.model;
 
 import com.fasterxml.jackson.annotation.JsonValue;
-import org.apache.shenyu.e2e.client.admin.model.response.PluginDTO;
+import org.apache.shenyu.e2e.model.response.PluginDTO;
 import org.junit.jupiter.api.Assertions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/ResourcesData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/ResourcesData.java
similarity index 94%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/ResourcesData.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/ResourcesData.java
index de98f49ad..9af114fcc 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/ResourcesData.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/ResourcesData.java
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model;
+package org.apache.shenyu.e2e.model;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleData;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorData;
+import org.apache.shenyu.e2e.model.data.RuleData;
+import org.apache.shenyu.e2e.model.data.SelectorData;
 
 import java.util.List;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/SelectorType.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/SelectorType.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/SelectorType.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/SelectorType.java
index 9249e4ed1..c53df07fa 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/SelectorType.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/SelectorType.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model;
+package org.apache.shenyu.e2e.model;
 
 import com.fasterxml.jackson.annotation.JsonValue;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/ShenYuResult.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/ShenYuResult.java
similarity index 97%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/ShenYuResult.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/ShenYuResult.java
index d4e830b7e..1458bbf34 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/ShenYuResult.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/ShenYuResult.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model;
+package org.apache.shenyu.e2e.model;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/Condition.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/Condition.java
similarity index 99%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/Condition.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/Condition.java
index 8f214abda..4bb873c88 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/Condition.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/Condition.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.annotation.JsonValue;
 import org.jetbrains.annotations.NotNull;
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/ConditionData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/ConditionData.java
new file mode 100644
index 000000000..03a1c7a3d
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/ConditionData.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.data;
+
+import java.util.Objects;
+
+/**
+ * ConditionDTO.
+ *
+ * @since 2.0.0
+ */
+public class ConditionData {
+
+    /**
+     * {@linkplain org.apache.shenyu.common.enums.ParamTypeEnum}.
+     */
+    private String paramType;
+
+    /**
+     * {@linkplain org.apache.shenyu.common.enums.OperatorEnum}.
+     */
+    private String operator;
+
+    /**
+     * param name.
+     */
+    private String paramName;
+
+    /**
+     * param value.
+     */
+    private String paramValue;
+
+    /**
+     * get paramType.
+     *
+     * @return paramType
+     */
+    public String getParamType() {
+        return paramType;
+    }
+
+    /**
+     * set paramType.
+     *
+     * @param paramType paramType
+     */
+    public void setParamType(final String paramType) {
+        this.paramType = paramType;
+    }
+
+    /**
+     * get operator.
+     *
+     * @return operator
+     */
+    public String getOperator() {
+        return operator;
+    }
+
+    /**
+     * set operator.
+     *
+     * @param operator operator
+     */
+    public void setOperator(final String operator) {
+        this.operator = operator;
+    }
+
+    /**
+     * get paramName.
+     *
+     * @return paramName
+     */
+    public String getParamName() {
+        return paramName;
+    }
+
+    /**
+     * set paramName.
+     *
+     * @param paramName paramName
+     */
+    public void setParamName(final String paramName) {
+        this.paramName = paramName;
+    }
+
+    /**
+     * get paramValue.
+     *
+     * @return paramValue
+     */
+    public String getParamValue() {
+        return paramValue;
+    }
+
+    /**
+     * set paramValue.
+     *
+     * @param paramValue paramValue
+     */
+    public void setParamValue(final String paramValue) {
+        this.paramValue = paramValue;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        ConditionData that = (ConditionData) o;
+        return Objects.equals(paramType, that.paramType) && Objects.equals(operator, that.operator)
+                && Objects.equals(paramName, that.paramName) && Objects.equals(paramValue, that.paramValue);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(paramType, operator, paramName, paramValue);
+    }
+
+    @Override
+    public String toString() {
+        return "ConditionData{"
+                + "paramType='"
+                + paramType
+                + '\''
+                + ", operator='"
+                + operator
+                + '\''
+                + ", paramName='"
+                + paramName
+                + '\''
+                + ", paramValue='"
+                + paramValue
+                + '\''
+                + '}';
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/MetaData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/MetaData.java
new file mode 100644
index 000000000..b9d39da2a
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/MetaData.java
@@ -0,0 +1,532 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.data;
+
+import org.apache.commons.lang3.StringUtils;
+
+import java.util.Objects;
+
+public class MetaData {
+
+    private String id;
+
+    private String appName;
+
+    private String contextPath;
+
+    private String path;
+
+    private String rpcType;
+
+    private String serviceName;
+
+    private String methodName;
+
+    private String parameterTypes;
+
+    private String rpcExt;
+
+    private Boolean enabled;
+
+    /**
+     * no args constructor.
+     */
+    public MetaData() {
+    }
+
+    /**
+     * all args constructor.
+     *
+     * @param id             id
+     * @param appName        appName
+     * @param contextPath    contextPath
+     * @param path           path
+     * @param rpcType        rpcType
+     * @param serviceName    serviceName
+     * @param methodName     methodName
+     * @param parameterTypes parameterTypes
+     * @param rpcExt         rpcExt
+     * @param enabled        enabled
+     */
+    public MetaData(final String id, final String appName, final String contextPath, final String path, final String rpcType, final String serviceName,
+                    final String methodName, final String parameterTypes, final String rpcExt, final Boolean enabled) {
+        this.id = id;
+        this.appName = appName;
+        this.contextPath = contextPath;
+        this.path = path;
+        this.rpcType = rpcType;
+        this.serviceName = serviceName;
+        this.methodName = methodName;
+        this.parameterTypes = parameterTypes;
+        this.rpcExt = rpcExt;
+        this.enabled = enabled;
+    }
+
+    /**
+     * builder constructor.
+     *
+     * @param builder builder
+     */
+    private MetaData(final Builder builder) {
+        this.id = builder.id;
+        this.appName = builder.appName;
+        this.contextPath = builder.contextPath;
+        this.path = builder.path;
+        this.rpcType = builder.rpcType;
+        this.serviceName = builder.serviceName;
+        this.methodName = builder.methodName;
+        this.parameterTypes = builder.parameterTypes;
+        this.rpcExt = builder.rpcExt;
+        this.enabled = builder.enabled;
+    }
+
+    /**
+     * class builder.
+     *
+     * @return Builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get id.
+     *
+     * @return id
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * set id.
+     *
+     * @param id id
+     */
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+    /**
+     * get appName.
+     *
+     * @return appName
+     */
+    public String getAppName() {
+        return appName;
+    }
+
+    /**
+     * set appName.
+     *
+     * @param appName appName
+     */
+    public void setAppName(final String appName) {
+        this.appName = appName;
+    }
+
+    /**
+     * get contextPath.
+     *
+     * @return contextPath
+     */
+    public String getContextPath() {
+        return contextPath;
+    }
+
+    /**
+     * set contextPath.
+     *
+     * @param contextPath contextPath
+     */
+    public void setContextPath(final String contextPath) {
+        this.contextPath = contextPath;
+    }
+
+    /**
+     * get path.
+     *
+     * @return path
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * set path.
+     *
+     * @param path path
+     */
+    public void setPath(final String path) {
+        this.path = path;
+    }
+
+    /**
+     * get rpcType.
+     *
+     * @return rpcType
+     */
+    public String getRpcType() {
+        return rpcType;
+    }
+
+    /**
+     * set rpcType.
+     *
+     * @param rpcType rpcType
+     */
+    public void setRpcType(final String rpcType) {
+        this.rpcType = rpcType;
+    }
+
+    /**
+     * get serviceName.
+     *
+     * @return serviceName
+     */
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    /**
+     * set serviceName.
+     *
+     * @param serviceName serviceName
+     */
+    public void setServiceName(final String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    /**
+     * get methodName.
+     *
+     * @return methodName
+     */
+    public String getMethodName() {
+        return methodName;
+    }
+
+    /**
+     * set methodName.
+     *
+     * @param methodName methodName
+     */
+    public void setMethodName(final String methodName) {
+        this.methodName = methodName;
+    }
+
+    /**
+     * get parameterTypes.
+     *
+     * @return parameterTypes
+     */
+    public String getParameterTypes() {
+        return parameterTypes;
+    }
+
+    /**
+     * set parameterTypes.
+     *
+     * @param parameterTypes parameterTypes
+     */
+    public void setParameterTypes(final String parameterTypes) {
+        this.parameterTypes = parameterTypes;
+    }
+
+    /**
+     * get rpcExt.
+     *
+     * @return rpcExt
+     */
+    public String getRpcExt() {
+        return rpcExt;
+    }
+
+    /**
+     * set rpcExt.
+     *
+     * @param rpcExt rpcExt
+     */
+    public void setRpcExt(final String rpcExt) {
+        this.rpcExt = rpcExt;
+    }
+
+    /**
+     * get enabled.
+     *
+     * @return enabled
+     */
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    /**
+     * set enabled.
+     *
+     * @param enabled enabled
+     */
+    public void setEnabled(final Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        MetaData metaData = (MetaData) o;
+        return Objects.equals(id, metaData.id) && Objects.equals(appName, metaData.appName) && Objects.equals(contextPath, metaData.contextPath)
+                && Objects.equals(path, metaData.path) && Objects.equals(rpcType, metaData.rpcType) && Objects.equals(serviceName, metaData.serviceName)
+                && Objects.equals(methodName, metaData.methodName) && Objects.equals(parameterTypes, metaData.parameterTypes)
+                && Objects.equals(rpcExt, metaData.rpcExt) && Objects.equals(enabled, metaData.enabled);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, appName, contextPath, path, rpcType, serviceName, methodName, parameterTypes, rpcExt, enabled);
+    }
+
+    @Override
+    public String toString() {
+        return "MetaData{"
+                + "id='"
+                + id
+                + '\''
+                + ", appName='"
+                + appName
+                + '\''
+                + ", contextPath='"
+                + contextPath
+                + '\''
+                + ", path='"
+                + path
+                + '\''
+                + ", rpcType='"
+                + rpcType
+                + '\''
+                + ", serviceName='"
+                + serviceName
+                + '\''
+                + ", methodName='"
+                + methodName
+                + '\''
+                + ", parameterTypes='"
+                + parameterTypes
+                + '\''
+                + ", rpcExt='"
+                + rpcExt
+                + '\''
+                + ", enabled="
+                + enabled
+                + '}';
+    }
+
+    /**
+     * update ContextPath.
+     */
+    public void updateContextPath() {
+        if (StringUtils.isNoneBlank(this.path)) {
+            this.contextPath = StringUtils.indexOf(path, "/", 1) > -1
+                    ? this.path.substring(0, StringUtils.indexOf(path, "/", 1)) : path;
+        }
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+
+        /**
+         * id.
+         */
+        private String id;
+
+        /**
+         * appName.
+         */
+        private String appName;
+
+        /**
+         * contextPath.
+         */
+        private String contextPath;
+
+        /**
+         * path.
+         */
+        private String path;
+
+        /**
+         * rpcType.
+         */
+        private String rpcType;
+
+        /**
+         * serviceName.
+         */
+        private String serviceName;
+
+        /**
+         * methodName.
+         */
+        private String methodName;
+
+        /**
+         * parameterTypes.
+         */
+        private String parameterTypes;
+
+        /**
+         * rpcExt.
+         */
+        private String rpcExt;
+
+        /**
+         * enabled.
+         */
+        private Boolean enabled;
+
+        /**
+         * no args constructor.
+         */
+        private Builder() {
+        }
+
+        /**
+         * build new Object.
+         *
+         * @return MetaData
+         */
+        public MetaData build() {
+            return new MetaData(this);
+        }
+
+        /**
+         * build id.
+         *
+         * @param id id
+         * @return this
+         */
+        public Builder id(final String id) {
+            this.id = id;
+            return this;
+        }
+
+        /**
+         * build appName.
+         *
+         * @param appName appName
+         * @return this
+         */
+        public Builder appName(final String appName) {
+            this.appName = appName;
+            return this;
+        }
+
+        /**
+         * build contextPath.
+         *
+         * @param contextPath contextPath
+         * @return this
+         */
+        public Builder contextPath(final String contextPath) {
+            this.contextPath = contextPath;
+            return this;
+        }
+
+        /**
+         * build path.
+         *
+         * @param path path
+         * @return this
+         */
+        public Builder path(final String path) {
+            this.path = path;
+            return this;
+        }
+
+        /**
+         * build rpcType.
+         *
+         * @param rpcType rpcType
+         * @return this
+         */
+        public Builder rpcType(final String rpcType) {
+            this.rpcType = rpcType;
+            return this;
+        }
+
+        /**
+         * build serviceName.
+         *
+         * @param serviceName serviceName
+         * @return this
+         */
+        public Builder serviceName(final String serviceName) {
+            this.serviceName = serviceName;
+            return this;
+        }
+
+        /**
+         * build methodName.
+         *
+         * @param methodName methodName
+         * @return this
+         */
+        public Builder methodName(final String methodName) {
+            this.methodName = methodName;
+            return this;
+        }
+
+        /**
+         * build parameterTypes.
+         *
+         * @param parameterTypes parameterTypes
+         * @return this
+         */
+        public Builder parameterTypes(final String parameterTypes) {
+            this.parameterTypes = parameterTypes;
+            return this;
+        }
+
+        /**
+         * build rpcExt.
+         *
+         * @param rpcExt rpcExt
+         * @return this
+         */
+        public Builder rpcExt(final String rpcExt) {
+            this.rpcExt = rpcExt;
+            return this;
+        }
+
+        /**
+         * build enabled.
+         *
+         * @param enabled enabled
+         * @return this
+         */
+        public Builder enabled(final Boolean enabled) {
+            this.enabled = enabled;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/PluginData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/PluginData.java
similarity index 95%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/PluginData.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/PluginData.java
index 4616591e6..6118c5416 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/PluginData.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/PluginData.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import org.jetbrains.annotations.NotNull;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/QueryCondition.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/QueryCondition.java
similarity index 94%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/QueryCondition.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/QueryCondition.java
index f14f82995..439bd33ac 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/QueryCondition.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/QueryCondition.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 /**
  * the condition of query.
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/ResourceData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/ResourceData.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/ResourceData.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/ResourceData.java
index 15232fa3d..d5be257a8 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/ResourceData.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/ResourceData.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleCacheData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleCacheData.java
new file mode 100644
index 000000000..bd7aabe63
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleCacheData.java
@@ -0,0 +1,572 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.data;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * RuleCacheData.
+ *
+ * @since 2.0.0
+ */
+public class RuleCacheData {
+
+    private String id;
+
+    private String name;
+
+    private String pluginName;
+
+    private String selectorId;
+
+    /**
+     * match way(0 and  1 or).
+     */
+    private Integer matchMode;
+
+    private Integer sort;
+
+    private Boolean enabled;
+
+    private Boolean loged;
+
+    /**
+     * handle message(different plugin have different handle to mark ,json style).
+     */
+    private String handle;
+
+    private List<ConditionData> conditionDataList;
+
+    private List<ConditionData> beforeConditionDataList;
+
+    /**
+     * match restful.
+     */
+    private Boolean matchRestful;
+
+    /**
+     * no args constructor.
+     */
+    public RuleCacheData() {
+    }
+
+    /**
+     * builder constructor.
+     *
+     * @param builder builder
+     */
+    private RuleCacheData(final Builder builder) {
+        this.id = builder.id;
+        this.name = builder.name;
+        this.pluginName = builder.pluginName;
+        this.selectorId = builder.selectorId;
+        this.matchMode = builder.matchMode;
+        this.sort = builder.sort;
+        this.enabled = builder.enabled;
+        this.loged = builder.loged;
+        this.handle = builder.handle;
+        this.conditionDataList = builder.conditionDataList;
+        this.beforeConditionDataList = builder.beforeConditionDataList;
+        this.matchRestful = builder.matchRestful;
+    }
+
+    /**
+     * class builder.
+     *
+     * @return Builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get id.
+     *
+     * @return id
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * set id.
+     *
+     * @param id id
+     * @return this
+     */
+    public RuleCacheData setId(final String id) {
+        this.id = id;
+        return this;
+    }
+
+    /**
+     * get name.
+     *
+     * @return name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * set name.
+     *
+     * @param name name
+     * @return this
+     */
+    public RuleCacheData setName(final String name) {
+        this.name = name;
+        return this;
+    }
+
+    /**
+     * get pluginName.
+     *
+     * @return pluginName
+     */
+    public String getPluginName() {
+        return pluginName;
+    }
+
+    /**
+     * set pluginName.
+     *
+     * @param pluginName pluginName
+     * @return this
+     */
+    public RuleCacheData setPluginName(final String pluginName) {
+        this.pluginName = pluginName;
+        return this;
+    }
+
+    /**
+     * get selectorId.
+     *
+     * @return selectorId
+     */
+    public String getSelectorId() {
+        return selectorId;
+    }
+
+    /**
+     * set selectorId.
+     *
+     * @param selectorId selectorId
+     * @return this
+     */
+    public RuleCacheData setSelectorId(final String selectorId) {
+        this.selectorId = selectorId;
+        return this;
+    }
+
+    /**
+     * get matchMode.
+     *
+     * @return matchMode
+     */
+    public Integer getMatchMode() {
+        return matchMode;
+    }
+
+    /**
+     * set matchMode.
+     *
+     * @param matchMode matchMode
+     * @return this
+     */
+    public RuleCacheData setMatchMode(final Integer matchMode) {
+        this.matchMode = matchMode;
+        return this;
+    }
+
+    /**
+     * get sort.
+     *
+     * @return sort
+     */
+    public Integer getSort() {
+        return sort;
+    }
+
+    /**
+     * set sort.
+     *
+     * @param sort sort
+     * @return this
+     */
+    public RuleCacheData setSort(final Integer sort) {
+        this.sort = sort;
+        return this;
+    }
+
+    /**
+     * get enabled.
+     *
+     * @return enabled
+     */
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    /**
+     * set enabled.
+     *
+     * @param enabled enabled
+     * @return this
+     */
+    public RuleCacheData setEnabled(final Boolean enabled) {
+        this.enabled = enabled;
+        return this;
+    }
+
+    /**
+     * get loged.
+     *
+     * @return loged
+     */
+    public Boolean getLoged() {
+        return loged;
+    }
+
+    /**
+     * set loged.
+     *
+     * @param loged loged
+     * @return this
+     */
+    public RuleCacheData setLoged(final Boolean loged) {
+        this.loged = loged;
+        return this;
+    }
+
+    /**
+     * get handle.
+     *
+     * @return handle
+     */
+    public String getHandle() {
+        return handle;
+    }
+
+    /**
+     * set handle.
+     *
+     * @param handle handle
+     * @return this
+     */
+    public RuleCacheData setHandle(final String handle) {
+        this.handle = handle;
+        return this;
+    }
+
+    /**
+     * get conditionDataList.
+     *
+     * @return conditionDataList
+     */
+    public List<ConditionData> getConditionDataList() {
+        return conditionDataList;
+    }
+
+    /**
+     * set conditionDataList.
+     *
+     * @param conditionDataList conditionDataList
+     * @return this
+     */
+    public RuleCacheData setConditionDataList(final List<ConditionData> conditionDataList) {
+        this.conditionDataList = conditionDataList;
+        return this;
+    }
+
+    /**
+     * get beforeConditionDataList.
+     *
+     * @return beforeConditionDataList
+     */
+    public List<ConditionData> getBeforeConditionDataList() {
+        return beforeConditionDataList;
+    }
+
+    /**
+     * set beforeConditionDataList.
+     *
+     * @param beforeConditionDataList beforeConditionDataList
+     */
+    public void setBeforeConditionDataList(final List<ConditionData> beforeConditionDataList) {
+        this.beforeConditionDataList = beforeConditionDataList;
+    }
+    
+    /**
+     * get match restful.
+     *
+     * @return matchRestful
+     */
+    public Boolean getMatchRestful() {
+        return matchRestful;
+    }
+    
+    /**
+     * set match restful.
+     *
+     * @param matchRestful matchRestful
+     */
+    public void setMatchRestful(final Boolean matchRestful) {
+        this.matchRestful = matchRestful;
+    }
+    
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        final RuleCacheData ruleCacheData = (RuleCacheData) o;
+        return Objects.equals(id, ruleCacheData.id)
+                && Objects.equals(name, ruleCacheData.name)
+                && Objects.equals(pluginName, ruleCacheData.pluginName)
+                && Objects.equals(selectorId, ruleCacheData.selectorId)
+                && Objects.equals(matchMode, ruleCacheData.matchMode)
+                && Objects.equals(sort, ruleCacheData.sort)
+                && Objects.equals(enabled, ruleCacheData.enabled)
+                && Objects.equals(loged, ruleCacheData.loged)
+                && Objects.equals(handle, ruleCacheData.handle)
+                && Objects.equals(conditionDataList, ruleCacheData.conditionDataList)
+                && Objects.equals(beforeConditionDataList, ruleCacheData.beforeConditionDataList)
+                && Objects.equals(matchRestful, ruleCacheData.matchRestful);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, name, pluginName, selectorId, matchMode, sort, enabled, loged, handle, conditionDataList,
+                beforeConditionDataList, matchRestful);
+    }
+
+    @Override
+    public String toString() {
+        return "RuleCacheData{"
+                + "id='"
+                + id
+                + '\''
+                + ", name='"
+                + name
+                + '\''
+                + ", pluginName='"
+                + pluginName
+                + '\''
+                + ", selectorId='"
+                + selectorId
+                + '\''
+                + ", matchMode="
+                + matchMode
+                + ", sort="
+                + sort
+                + ", enabled="
+                + enabled
+                + ", loged="
+                + loged
+                + ", handle='"
+                + handle
+                + '\''
+                + ", conditionDataList="
+                + conditionDataList
+                + ", matchRestful="
+                + matchRestful
+                + '}';
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+
+        private String id;
+
+        private String name;
+
+        private String pluginName;
+
+        private String selectorId;
+
+        private Integer matchMode;
+
+        private Integer sort;
+
+        private Boolean enabled;
+
+        private Boolean loged;
+
+        private String handle;
+
+        private List<ConditionData> conditionDataList;
+
+        private List<ConditionData> beforeConditionDataList;
+        
+        private Boolean matchRestful;
+
+        /**
+         * no args constructor.
+         */
+        private Builder() {
+        }
+
+        /**
+         * build new Object.
+         *
+         * @return RuleCacheData
+         */
+        public RuleCacheData build() {
+            return new RuleCacheData(this);
+        }
+
+        /**
+         * build id.
+         *
+         * @param id id
+         * @return this
+         */
+        public Builder id(final String id) {
+            this.id = id;
+            return this;
+        }
+
+        /**
+         * build name.
+         *
+         * @param name name
+         * @return this
+         */
+        public Builder name(final String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * build pluginName.
+         *
+         * @param pluginName pluginName
+         * @return this
+         */
+        public Builder pluginName(final String pluginName) {
+            this.pluginName = pluginName;
+            return this;
+        }
+
+        /**
+         * build selectorId.
+         *
+         * @param selectorId selectorId
+         * @return this
+         */
+        public Builder selectorId(final String selectorId) {
+            this.selectorId = selectorId;
+            return this;
+        }
+
+        /**
+         * build matchMode.
+         *
+         * @param matchMode matchMode
+         * @return this
+         */
+        public Builder matchMode(final Integer matchMode) {
+            this.matchMode = matchMode;
+            return this;
+        }
+
+        /**
+         * build sort.
+         *
+         * @param sort sort
+         * @return this
+         */
+        public Builder sort(final Integer sort) {
+            this.sort = sort;
+            return this;
+        }
+
+        /**
+         * build enabled.
+         *
+         * @param enabled enabled
+         * @return this
+         */
+        public Builder enabled(final Boolean enabled) {
+            this.enabled = enabled;
+            return this;
+        }
+
+        /**
+         * build loged.
+         *
+         * @param loged loged
+         * @return this
+         */
+        public Builder loged(final Boolean loged) {
+            this.loged = loged;
+            return this;
+        }
+
+        /**
+         * build handle.
+         *
+         * @param handle handle
+         * @return this
+         */
+        public Builder handle(final String handle) {
+            this.handle = handle;
+            return this;
+        }
+
+        /**
+         * build conditionDataList.
+         *
+         * @param conditionDataList conditionDataList
+         * @return this
+         */
+        public Builder conditionDataList(final List<ConditionData> conditionDataList) {
+            this.conditionDataList = conditionDataList;
+            return this;
+        }
+
+        /**
+         * build conditionDataList.
+         *
+         * @param beforeConditionDataList beforeConditionDataList
+         * @return this
+         */
+        public Builder beforeConditionDataList(final List<ConditionData> beforeConditionDataList) {
+            this.beforeConditionDataList = beforeConditionDataList;
+            return this;
+        }
+    
+        /**
+         * build match restful.
+         *
+         * @param matchRestful matchRestful
+         * @return this
+         */
+        public Builder matchRestful(final Boolean matchRestful) {
+            this.matchRestful = matchRestful;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/RuleData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleData.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/RuleData.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleData.java
index ec92389ab..0a5e4cd09 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/RuleData.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleData.java
@@ -15,13 +15,12 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import org.apache.shenyu.e2e.client.admin.model.MatchMode;
-import org.apache.shenyu.e2e.client.admin.model.handle.RuleHandle;
-import org.apache.shenyu.e2e.client.admin.model.handle.RuleHandle.Serializer;
+import org.apache.shenyu.e2e.model.MatchMode;
+import org.apache.shenyu.e2e.model.handle.RuleHandle;
 
 import java.util.List;
 
@@ -43,7 +42,7 @@ public class RuleData implements ResourceData {
     
     private int sort;
     
-    @JsonSerialize(using = Serializer.class)
+    @JsonSerialize(using = RuleHandle.Serializer.class)
     private RuleHandle handle;
 
     /**
@@ -284,7 +283,7 @@ public class RuleData implements ResourceData {
 
         private int sort;
 
-        @JsonSerialize(using = Serializer.class)
+        @JsonSerialize(using = RuleHandle.Serializer.class)
         private RuleHandle handle;
 
         @JsonProperty("ruleConditions")
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/RuleQueryCondition.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleQueryCondition.java
similarity index 98%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/RuleQueryCondition.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleQueryCondition.java
index b6a5eb2be..d4595d3d2 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/RuleQueryCondition.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/RuleQueryCondition.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SearchCondition.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SearchCondition.java
similarity index 98%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SearchCondition.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SearchCondition.java
index b83434a1e..aa201bd53 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SearchCondition.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SearchCondition.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonInclude.Include;
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorCacheData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorCacheData.java
new file mode 100644
index 000000000..30a6b619b
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorCacheData.java
@@ -0,0 +1,623 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.data;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * SelectorData.
+ *
+ * @since 2.0.0
+ */
+public class SelectorCacheData {
+
+    private String id;
+
+    private String pluginId;
+
+    /**
+     * plugin name.
+     */
+    private String pluginName;
+
+    private String name;
+
+    /**
+     * matchMode(0 and  1 or).
+     */
+    private Integer matchMode;
+
+    /**
+     * type(false full,true custom).
+     */
+    private Integer type;
+
+    private Integer sort;
+
+    private Boolean enabled;
+
+    private Boolean logged;
+
+    private Boolean continued = Boolean.TRUE;
+
+    private String handle;
+
+    private List<ConditionData> conditionList;
+
+    private List<ConditionData> beforeConditionList;
+
+    /**
+     * match restful api.
+     */
+    private Boolean matchRestful;
+
+    /**
+     * no args constructor.
+     */
+    public SelectorCacheData() {
+    }
+
+    /**
+     * builder constructor.
+     *
+     * @param builder builder
+     */
+    private SelectorCacheData(final Builder builder) {
+        this.id = builder.id;
+        this.pluginId = builder.pluginId;
+        this.pluginName = builder.pluginName;
+        this.name = builder.name;
+        this.matchMode = builder.matchMode;
+        this.type = builder.type;
+        this.sort = builder.sort;
+        this.enabled = builder.enabled;
+        this.logged = builder.logged;
+        this.continued = builder.continued;
+        this.handle = builder.handle;
+        this.conditionList = builder.conditionList;
+        this.matchRestful = builder.matchRestful;
+        this.beforeConditionList = builder.beforeConditionList;
+    }
+
+    /**
+     * class builder.
+     *
+     * @return Builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get id.
+     *
+     * @return id
+     */
+    public String getId() {
+        return id;
+    }
+
+    /**
+     * set id.
+     *
+     * @param id id
+     */
+    public void setId(final String id) {
+        this.id = id;
+    }
+
+    /**
+     * get pluginId.
+     *
+     * @return pluginId
+     */
+    public String getPluginId() {
+        return pluginId;
+    }
+
+    /**
+     * set pluginId.
+     *
+     * @param pluginId pluginId
+     */
+    public void setPluginId(final String pluginId) {
+        this.pluginId = pluginId;
+    }
+
+    /**
+     * get pluginName.
+     *
+     * @return pluginName
+     */
+    public String getPluginName() {
+        return pluginName;
+    }
+
+    /**
+     * set pluginName.
+     *
+     * @param pluginName pluginName
+     */
+    public void setPluginName(final String pluginName) {
+        this.pluginName = pluginName;
+    }
+
+    /**
+     * get name.
+     *
+     * @return name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * set name.
+     *
+     * @param name name
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * get matchMode.
+     *
+     * @return matchMode
+     */
+    public Integer getMatchMode() {
+        return matchMode;
+    }
+
+    /**
+     * set matchMode.
+     *
+     * @param matchMode matchMode
+     */
+    public void setMatchMode(final Integer matchMode) {
+        this.matchMode = matchMode;
+    }
+
+    /**
+     * get type.
+     *
+     * @return type
+     */
+    public Integer getType() {
+        return type;
+    }
+
+    /**
+     * set type.
+     *
+     * @param type type
+     */
+    public void setType(final Integer type) {
+        this.type = type;
+    }
+
+    /**
+     * get sort.
+     *
+     * @return sort
+     */
+    public Integer getSort() {
+        return sort;
+    }
+
+    /**
+     * set sort.
+     *
+     * @param sort sort
+     */
+    public void setSort(final Integer sort) {
+        this.sort = sort;
+    }
+
+    /**
+     * get enabled.
+     *
+     * @return enabled
+     */
+    public Boolean getEnabled() {
+        return enabled;
+    }
+
+    /**
+     * set enabled.
+     *
+     * @param enabled enabled
+     */
+    public void setEnabled(final Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    /**
+     * get logged.
+     *
+     * @return logged
+     */
+    public Boolean getLogged() {
+        return logged;
+    }
+
+    /**
+     * set logged.
+     *
+     * @param logged logged
+     */
+    public void setLogged(final Boolean logged) {
+        this.logged = logged;
+    }
+
+    /**
+     * get continued.
+     *
+     * @return continued
+     */
+    public Boolean getContinued() {
+        if (Objects.isNull(continued)) {
+            return true;
+        }
+        return continued;
+    }
+
+    /**
+     * set continued.
+     *
+     * @param continued continued
+     */
+    public void setContinued(final Boolean continued) {
+        this.continued = continued;
+    }
+
+    /**
+     * get handle.
+     *
+     * @return handle
+     */
+    public String getHandle() {
+        return handle;
+    }
+
+    /**
+     * set handle.
+     *
+     * @param handle handle
+     */
+    public void setHandle(final String handle) {
+        this.handle = handle;
+    }
+
+    /**
+     * get conditionList.
+     *
+     * @return conditionList
+     */
+    public List<ConditionData> getConditionList() {
+        return conditionList;
+    }
+
+    /**
+     * set conditionList.
+     *
+     * @param conditionList conditionList
+     */
+    public void setConditionList(final List<ConditionData> conditionList) {
+        this.conditionList = conditionList;
+    }
+    
+    /**
+     * get match restful.
+     *
+     * @return match restful
+     */
+    public Boolean getMatchRestful() {
+        return matchRestful;
+    }
+    
+    /**
+     * set match restful.
+     *
+     * @param matchRestful matchRestful
+     */
+    public void setMatchRestful(final Boolean matchRestful) {
+        this.matchRestful = matchRestful;
+    }
+    
+    /**
+     * get before condition list.
+     *
+     * @return before condition list
+     */
+    public List<ConditionData> getBeforeConditionList() {
+        return beforeConditionList;
+    }
+    
+    /**
+     * set before condition list.
+     *
+     * @param beforeConditionList before condition list
+     */
+    public void setBeforeConditionList(final List<ConditionData> beforeConditionList) {
+        this.beforeConditionList = beforeConditionList;
+    }
+    
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        SelectorCacheData that = (SelectorCacheData) o;
+        return Objects.equals(id, that.id) && Objects.equals(pluginId, that.pluginId) && Objects.equals(pluginName, that.pluginName)
+                && Objects.equals(name, that.name) && Objects.equals(matchMode, that.matchMode) && Objects.equals(type, that.type)
+                && Objects.equals(sort, that.sort) && Objects.equals(enabled, that.enabled) && Objects.equals(logged, that.logged)
+                && Objects.equals(continued, that.continued) && Objects.equals(handle, that.handle)
+                && Objects.equals(conditionList, that.conditionList) && Objects.equals(matchRestful, that.matchRestful)
+                && Objects.equals(beforeConditionList, that.beforeConditionList);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, pluginId, pluginName, name, matchMode, type, sort, enabled, logged, continued, handle, conditionList, matchRestful, beforeConditionList);
+    }
+
+    @Override
+    public String toString() {
+        return "SelectorCacheData{"
+                + "id='"
+                + id
+                + '\''
+                + ", pluginId='"
+                + pluginId
+                + '\''
+                + ", pluginName='"
+                + pluginName
+                + '\''
+                + ", name='"
+                + name
+                + '\''
+                + ", matchMode="
+                + matchMode
+                + ", type="
+                + type
+                + ", sort="
+                + sort
+                + ", enabled="
+                + enabled
+                + ", logged="
+                + logged
+                + ", continued="
+                + continued
+                + ", handle='"
+                + handle
+                + '\''
+                + ", conditionList="
+                + conditionList
+                + ", matchRestful="
+                + matchRestful
+                + '}';
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+
+        private String id;
+
+        private String pluginId;
+
+        private String pluginName;
+
+        private String name;
+
+        private Integer matchMode;
+
+        private Integer type;
+
+        private Integer sort;
+
+        private Boolean enabled;
+
+        private Boolean logged;
+
+        private Boolean continued;
+
+        private String handle;
+
+        private List<ConditionData> conditionList;
+        
+        private Boolean matchRestful;
+        
+        private List<ConditionData> beforeConditionList;
+
+        /**
+         * no args constructor.
+         */
+        private Builder() {
+        }
+
+        /**
+         * build new Object.
+         *
+         * @return SelectorCacheData
+         */
+        public SelectorCacheData build() {
+            return new SelectorCacheData(this);
+        }
+
+        /**
+         * build id.
+         *
+         * @param id id
+         * @return this
+         */
+        public Builder id(final String id) {
+            this.id = id;
+            return this;
+        }
+
+        /**
+         * build pluginId.
+         *
+         * @param pluginId pluginId
+         * @return this
+         */
+        public Builder pluginId(final String pluginId) {
+            this.pluginId = pluginId;
+            return this;
+        }
+
+        /**
+         * build pluginName.
+         *
+         * @param pluginName pluginName
+         * @return this
+         */
+        public Builder pluginName(final String pluginName) {
+            this.pluginName = pluginName;
+            return this;
+        }
+
+        /**
+         * build name.
+         *
+         * @param name name
+         * @return this
+         */
+        public Builder name(final String name) {
+            this.name = name;
+            return this;
+        }
+
+        /**
+         * build matchMode.
+         *
+         * @param matchMode matchMode
+         * @return this
+         */
+        public Builder matchMode(final Integer matchMode) {
+            this.matchMode = matchMode;
+            return this;
+        }
+
+        /**
+         * build type.
+         *
+         * @param type type
+         * @return this
+         */
+        public Builder type(final Integer type) {
+            this.type = type;
+            return this;
+        }
+
+        /**
+         * build sort.
+         *
+         * @param sort sort
+         * @return this
+         */
+        public Builder sort(final Integer sort) {
+            this.sort = sort;
+            return this;
+        }
+
+        /**
+         * build enabled.
+         *
+         * @param enabled enabled
+         * @return this
+         */
+        public Builder enabled(final Boolean enabled) {
+            this.enabled = enabled;
+            return this;
+        }
+
+        /**
+         * build logged.
+         *
+         * @param logged logged
+         * @return this
+         */
+        public Builder logged(final Boolean logged) {
+            this.logged = logged;
+            return this;
+        }
+
+        /**
+         * build continued.
+         *
+         * @param continued continued
+         * @return this
+         */
+        public Builder continued(final Boolean continued) {
+            this.continued = continued;
+            return this;
+        }
+
+        /**
+         * build handle.
+         *
+         * @param handle handle
+         * @return this
+         */
+        public Builder handle(final String handle) {
+            this.handle = handle;
+            return this;
+        }
+
+        /**
+         * build conditionList.
+         *
+         * @param conditionList conditionList
+         * @return this
+         */
+        public Builder conditionList(final List<ConditionData> conditionList) {
+            this.conditionList = conditionList;
+            return this;
+        }
+    
+        /**
+         * build match restful.
+         *
+         * @param matchRestful matchRestful
+         * @return this
+         */
+        public Builder matchRestful(final Boolean matchRestful) {
+            this.matchRestful = matchRestful;
+            return this;
+        }
+        
+        /**
+         * build beforeConditionList.
+         *
+         * @param beforeConditionList beforeConditionList
+         * @return this
+         */
+        public Builder beforeConditionList(final List<ConditionData> beforeConditionList) {
+            this.beforeConditionList = beforeConditionList;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SelectorData.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorData.java
similarity index 97%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SelectorData.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorData.java
index 40d40fcd4..b8b4e31b8 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SelectorData.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorData.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.core.JsonGenerator;
@@ -24,10 +24,10 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.google.common.base.Strings;
-import org.apache.shenyu.e2e.client.admin.model.MatchMode;
-import org.apache.shenyu.e2e.client.admin.model.Plugin;
-import org.apache.shenyu.e2e.client.admin.model.SelectorType;
-import org.apache.shenyu.e2e.client.admin.model.handle.PluginHandle;
+import org.apache.shenyu.e2e.model.MatchMode;
+import org.apache.shenyu.e2e.model.Plugin;
+import org.apache.shenyu.e2e.model.SelectorType;
+import org.apache.shenyu.e2e.model.handle.PluginHandle;
 
 import java.io.IOException;
 import java.util.List;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SelectorQueryCondition.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorQueryCondition.java
similarity index 98%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SelectorQueryCondition.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorQueryCondition.java
index 3d66de57b..450a21171 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/data/SelectorQueryCondition.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/data/SelectorQueryCondition.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.data;
+package org.apache.shenyu.e2e.model.data;
 
 import com.fasterxml.jackson.annotation.JsonAlias;
 import com.fasterxml.jackson.annotation.JsonInclude;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/DivideRuleHandle.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/DivideRuleHandle.java
similarity index 99%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/DivideRuleHandle.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/DivideRuleHandle.java
index 5bf263d9b..543692ea4 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/DivideRuleHandle.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/DivideRuleHandle.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.model.handle;
 
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/DivideUpstream.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/DivideUpstream.java
new file mode 100644
index 000000000..34538d50e
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/DivideUpstream.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.handle;
+
+/**
+ * Divide upstream.
+ */
+public class DivideUpstream {
+
+    /**
+     * this is http protocol.
+     */
+    private String protocol;
+
+    /**
+     * url.
+     */
+    private String upstreamUrl;
+
+    /**
+     * false close/ true open.
+     */
+    private boolean status;
+
+    /**
+     * startup time.
+     */
+    private long timestamp;
+
+    /**
+     * weight.
+     */
+    private int weight;
+
+    /**
+     * warmup.
+     */
+    private int warmup;
+
+    /**
+     * upstreamHost.
+     */
+    private String upstreamHost;
+
+    private DivideUpstream() {
+    }
+
+    public DivideUpstream(Builder builder) {
+        this.protocol = builder.protocol;
+        this.upstreamUrl = builder.upstreamUrl;
+        this.timestamp = builder.timestamp;
+        this.weight = builder.weight;
+        this.warmup = builder.warmup;
+        this.status = builder.status;
+        this.upstreamHost = builder.upstreamHost;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get protocol.
+     *
+     * @return protocol
+     */
+    public String getProtocol() {
+        return protocol;
+    }
+
+    /**
+     * set protocol.
+     *
+     * @param protocol protocol
+     */
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    /**
+     * get upstreamUrl.
+     *
+     * @return upstreamUrl
+     */
+    public String getUpstreamUrl() {
+        return upstreamUrl;
+    }
+
+    /**
+     * set upstreamUrl.
+     *
+     * @param upstreamUrl upstreamUrl
+     */
+    public void setUpstreamUrl(String upstreamUrl) {
+        this.upstreamUrl = upstreamUrl;
+    }
+
+    /**
+     * get timestamp.
+     *
+     * @return timestamp
+     */
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    /**
+     * set timestamp
+     *
+     * @param timestamp timestamp
+     */
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
+    /**
+     * get weight.
+     *
+     * @return weight
+     */
+    public int getWeight() {
+        return weight;
+    }
+
+    /**
+     * set weight.
+     *
+     * @param weight weight
+     */
+    public void setWeight(int weight) {
+        this.weight = weight;
+    }
+
+    /**
+     * get warmup.
+     *
+     * @return warmup
+     */
+    public int getWarmup() {
+        return warmup;
+    }
+
+    /**
+     * set warmup.
+     *
+     * @param warmup warmup
+     */
+    public void setWarmup(int warmup) {
+        this.warmup = warmup;
+    }
+
+    /**
+     * is status.
+     *
+     * @return status
+     */
+    public boolean isStatus() {
+        return status;
+    }
+
+    /**
+     * set status.
+     *
+     * @param status status
+     */
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+
+    public String getUpstreamHost() {
+        return upstreamHost;
+    }
+
+    public void setUpstreamHost(String upstreamHost) {
+        this.upstreamHost = upstreamHost;
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+
+        /**
+         * this is http protocol.
+         */
+        private String protocol;
+
+        /**
+         * url.
+         */
+        private String upstreamUrl;
+
+        /**
+         * startup time.
+         */
+        private long timestamp;
+
+        /**
+         * weight.
+         */
+        private int weight;
+
+        /**
+         * warmup.
+         */
+        private int warmup;
+
+        private boolean status;
+
+        /**
+         * upstreamHost.
+         */
+        private String upstreamHost;
+
+        public Builder() {
+        }
+
+        public DivideUpstream build() {
+            return new DivideUpstream(this);
+        }
+
+        /**
+         * build protocol.
+         *
+         * @param protocol protocol
+         * @return this
+         */
+        public Builder protocol(String protocol) {
+            this.protocol = protocol;
+            return this;
+        }
+
+        /**
+         * build upstreamUrl.
+         *
+         * @param upstreamUrl upstreamUrl
+         * @return this
+         */
+        public Builder upstreamUrl(String upstreamUrl) {
+            this.upstreamUrl = upstreamUrl;
+            return this;
+        }
+
+        /**
+         * build timestamp.
+         *
+         * @param timestamp timestamp
+         * @return this
+         */
+        public Builder timestamp(long timestamp) {
+            this.timestamp = timestamp;
+            return this;
+        }
+
+        /**
+         * build weight.
+         *
+         * @param weight weight
+         * @return this
+         */
+        public Builder weight(int weight) {
+            this.weight = weight;
+            return this;
+        }
+
+        /**
+         * build warmup.
+         *
+         * @param warmup warmup
+         * @return this
+         */
+        public Builder warmup(int warmup) {
+            this.warmup = warmup;
+            return this;
+        }
+
+        /**
+         * build status
+         *
+         * @param status status
+         * @return this
+         */
+        public Builder status(boolean status) {
+            this.status = status;
+            return this;
+        }
+
+        public Builder upstreamHost(String upstreamHost) {
+            this.upstreamHost = upstreamHost;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/PluginHandle.java
similarity index 93%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/PluginHandle.java
index 2d0522be5..76ae443dd 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/PluginHandle.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/PluginHandle.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.model.handle;
 
 public interface PluginHandle {
 }
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/RuleHandle.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/RuleHandle.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/RuleHandle.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/RuleHandle.java
index 8c9cee25f..940be1e1c 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/RuleHandle.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/RuleHandle.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.model.handle;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/SpringCloudRuleHandle.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/SpringCloudRuleHandle.java
new file mode 100644
index 000000000..0b433db7f
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/SpringCloudRuleHandle.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.handle;
+
+/**
+ * SpringCLoud rule handle.
+ */
+public class SpringCloudRuleHandle implements RuleHandle {
+
+    private String loadBalance;
+
+    private String path;
+
+    private long timeout;
+
+    /**
+     * no args constructor.
+     */
+    public SpringCloudRuleHandle() {
+    }
+
+    public SpringCloudRuleHandle(Builder builder) {
+        this.loadBalance = builder.loadBalance;
+        this.path = builder.path;
+        this.timeout = builder.timeout;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get loadBalance.
+     *
+     * @return loadBalance
+     */
+    public String getLoadBalance() {
+        return loadBalance;
+    }
+
+    /**
+     * set loadBalance.
+     *
+     * @param loadBalance loadBalance
+     */
+    public void setLoadBalance(String loadBalance) {
+        this.loadBalance = loadBalance;
+    }
+
+    /**
+     * get path.
+     *
+     * @return path
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * set path.
+     *
+     * @param path path
+     */
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    /**
+     * get timeout.
+     *
+     * @return timeout
+     */
+    public long getTimeout() {
+        return timeout;
+    }
+
+    /**
+     * set timeout.
+     *
+     * @param timeout timeout
+     */
+    public void setTimeout(long timeout) {
+        this.timeout = timeout;
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+
+        private String loadBalance;
+
+        private String path;
+
+        private long timeout;
+
+        /**
+         * no args constructor.
+         */
+        private Builder() {
+        }
+
+        public SpringCloudRuleHandle build() {
+            return new SpringCloudRuleHandle(this);
+        }
+
+        /**
+         * build loadBalance.
+         *
+         * @param loadBalance loadBalance
+         * @return this
+         */
+        public Builder loadBalance(String loadBalance) {
+            this.loadBalance = loadBalance;
+            return this;
+        }
+
+        /**
+         * build path.
+         *
+         * @param path path
+         * @return this
+         */
+        public Builder path(String path) {
+            this.path = path;
+            return this;
+        }
+
+        /**
+         * build timeout.
+         *
+         * @param timeout timeout
+         * @return this
+         */
+        public Builder timeout(long timeout) {
+            this.timeout = timeout;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/SpringCloudSelectorHandle.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/SpringCloudSelectorHandle.java
new file mode 100644
index 000000000..e4fcda869
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/SpringCloudSelectorHandle.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.handle;
+
+import java.util.List;
+
+/**
+ * SpringCLoud selector handle.
+ */
+public class SpringCloudSelectorHandle implements PluginHandle {
+
+    /**
+     * this is register eureka serviceId.
+     */
+    private String serviceId;
+
+    /**
+     * this is gray.
+     */
+    private boolean gray;
+
+    /**
+     * The divideUpstreams.
+     */
+    private List<DivideUpstream> divideUpstreams;
+
+    /**
+     * no args constructor.
+     */
+    public SpringCloudSelectorHandle() {
+    }
+
+    /**
+     * builder constructor.
+     *
+     * @param builder builder
+     */
+    private SpringCloudSelectorHandle(final Builder builder) {
+        this.gray = builder.gray;
+        this.serviceId = builder.serviceId;
+        this.divideUpstreams = builder.divideUpstreams;
+    }
+
+    /**
+     * class builder.
+     *
+     * @return class Builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get serviceId.
+     *
+     * @return serviceId
+     */
+    public String getServiceId() {
+        return serviceId;
+    }
+
+    /**
+     * set serviceId.
+     *
+     * @param serviceId serviceId
+     */
+    public void setServiceId(final String serviceId) {
+        this.serviceId = serviceId;
+    }
+
+    /**
+     * get gray.
+     *
+     * @return the boolean
+     */
+    public boolean getGray() {
+        return gray;
+    }
+
+    /**
+     * set gray.
+     *
+     * @param gray gray
+     */
+    public void setGray(final Boolean gray) {
+        this.gray = gray;
+    }
+
+    /**
+     * get divideUpstreams.
+     *
+     * @return the divideUpstreams
+     */
+    public List<DivideUpstream> getDivideUpstreams() {
+        return divideUpstreams;
+    }
+
+    /**
+     * set divideUpstreams.
+     *
+     * @param divideUpstreams divideUpstreams
+     */
+    public void setDivideUpstreams(final List<DivideUpstream> divideUpstreams) {
+        this.divideUpstreams = divideUpstreams;
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+        /**
+         * serviceId.
+         */
+        private String serviceId;
+
+        /**
+         * this is gray.
+         */
+        private boolean gray;
+
+        /**
+         * The divideUpstreams.
+         */
+        private List<DivideUpstream> divideUpstreams;
+
+        /**
+         * no args constructor.
+         */
+        private Builder() {
+        }
+
+        /**
+         * build new Object.
+         *
+         * @return SpringCloudSelectorHandle
+         */
+        public SpringCloudSelectorHandle build() {
+            return new SpringCloudSelectorHandle(this);
+        }
+
+        /**
+         * build serviceId.
+         *
+         * @param serviceId serviceId
+         * @return this
+         */
+        public Builder serviceId(final String serviceId) {
+            this.serviceId = serviceId;
+            return this;
+        }
+
+        /**
+         * build gray.
+         *
+         * @param gray gray
+         * @return this
+         */
+        public Builder gray(final boolean gray) {
+            this.gray = gray;
+            return this;
+        }
+
+        /**
+         * build serviceId.
+         *
+         * @param divideUpstreams divideUpstreams
+         * @return this
+         */
+        public Builder divideUpstreams(final List<DivideUpstream> divideUpstreams) {
+            this.divideUpstreams = divideUpstreams;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/Upstreams.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/Upstreams.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/Upstreams.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/Upstreams.java
index d695f0963..69bc6db58 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/handle/Upstreams.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/handle/Upstreams.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.handle;
+package org.apache.shenyu.e2e.model.handle;
 
 import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.JsonSerializer;
@@ -23,7 +23,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.SerializerProvider;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.google.common.collect.Lists;
-import org.apache.shenyu.e2e.client.admin.model.handle.Upstreams.Serializer;
+import org.apache.shenyu.e2e.model.handle.Upstreams.Serializer;
 
 import java.io.IOException;
 import java.util.List;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/request/RequestVO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/request/RequestVO.java
similarity index 93%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/request/RequestVO.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/request/RequestVO.java
index 1d1de06ff..b310e3ec6 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/request/RequestVO.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/request/RequestVO.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.request;
+package org.apache.shenyu.e2e.model.request;
 
 public interface RequestVO {
 }
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/FakeResourceDTO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/FakeResourceDTO.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/FakeResourceDTO.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/FakeResourceDTO.java
index 9d482d403..c4cc8fcd9 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/FakeResourceDTO.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/FakeResourceDTO.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/LoginInfo.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/LoginInfo.java
similarity index 97%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/LoginInfo.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/LoginInfo.java
index 6b76c8896..bc7a73227 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/LoginInfo.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/LoginInfo.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonAlias;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
diff --git a/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/MetaDataDTO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/MetaDataDTO.java
new file mode 100644
index 000000000..0fcaeeb19
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/MetaDataDTO.java
@@ -0,0 +1,324 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.model.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+
+import java.util.Date;
+
+/**
+ * MetaDataDTO
+ */
+public class MetaDataDTO implements ResourceDTO {
+
+    /**
+     * appName.
+     */
+    private String appName;
+
+    /**
+     * the path.
+     */
+    private String path;
+
+    /**
+     * path desc.
+     */
+    private String pathDesc;
+
+    /**
+     * rpc type.
+     */
+    private String rpcType;
+
+    /**
+     * service name.
+     */
+    private String serviceName;
+
+    /**
+     * method name.
+     */
+    private String methodName;
+
+    /**
+     * parameter typs.
+     */
+    private String parameterTypes;
+
+    /**
+     * rpc ext.
+     */
+    private String rpcExt;
+
+    private String id;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date dateCreated;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date dateUpdated;
+
+    private boolean enabled;
+
+    private MetaDataDTO() {
+    }
+
+    private MetaDataDTO(Builder builder) {
+        this.appName = builder.appName;
+        this.path = builder.path;
+        this.pathDesc = builder.pathDesc;
+        this.rpcType = builder.rpcType;
+        this.serviceName = builder.serviceName;
+        this.methodName = builder.methodName;
+        this.parameterTypes = builder.parameterTypes;
+        this.rpcExt = builder.rpcExt;
+        this.id = builder.id;
+        this.dateCreated = builder.dateCreated;
+        this.dateUpdated = builder.dateUpdated;
+        this.enabled = builder.enabled;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    public String getAppName() {
+        return appName;
+    }
+
+    public void setAppName(String appName) {
+        this.appName = appName;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public String getPathDesc() {
+        return pathDesc;
+    }
+
+    public void setPathDesc(String pathDesc) {
+        this.pathDesc = pathDesc;
+    }
+
+    public String getRpcType() {
+        return rpcType;
+    }
+
+    public void setRpcType(String rpcType) {
+        this.rpcType = rpcType;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getMethodName() {
+        return methodName;
+    }
+
+    public void setMethodName(String methodName) {
+        this.methodName = methodName;
+    }
+
+    public String getParameterTypes() {
+        return parameterTypes;
+    }
+
+    public void setParameterTypes(String parameterTypes) {
+        this.parameterTypes = parameterTypes;
+    }
+
+    public String getRpcExt() {
+        return rpcExt;
+    }
+
+    public void setRpcExt(String rpcExt) {
+        this.rpcExt = rpcExt;
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public String getName() {
+        return null;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @Override
+    public Date getDateCreated() {
+        return dateCreated;
+    }
+
+    public void setDateCreated(Date dateCreated) {
+        this.dateCreated = dateCreated;
+    }
+
+    @Override
+    public Date getDateUpdated() {
+        return dateUpdated;
+    }
+
+    public void setDateUpdated(Date dateUpdated) {
+        this.dateUpdated = dateUpdated;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public static final class Builder {
+        /**
+         * appName.
+         */
+        private String appName;
+
+        /**
+         * the path.
+         */
+        private String path;
+
+        /**
+         * path desc.
+         */
+        private String pathDesc;
+
+        /**
+         * rpc type.
+         */
+        private String rpcType;
+
+        /**
+         * service name.
+         */
+        private String serviceName;
+
+        /**
+         * method name.
+         */
+        private String methodName;
+
+        /**
+         * parameter typs.
+         */
+        private String parameterTypes;
+
+        /**
+         * rpc ext.
+         */
+        private String rpcExt;
+
+        private String id;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private Date dateCreated;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private Date dateUpdated;
+
+        private boolean enabled;
+
+        private Builder() {
+
+        }
+
+        public MetaDataDTO build() {
+            return new MetaDataDTO(this);
+        }
+
+        public Builder appName(String appName) {
+            this.appName = appName;
+            return this;
+        }
+
+        public Builder path(String path) {
+            this.path = path;
+            return this;
+        }
+
+        public Builder pathDesc(String pathDesc) {
+            this.pathDesc = pathDesc;
+            return this;
+        }
+
+        public Builder rpcType(String rpcType) {
+            this.rpcType = rpcType;
+            return this;
+        }
+
+        public Builder serviceName(String serviceName) {
+            this.serviceName = serviceName;
+            return this;
+        }
+
+        public Builder methodName(String methodName) {
+            this.methodName = methodName;
+            return this;
+        }
+
+        public Builder parameterTypes(String parameterTypes) {
+            this.parameterTypes = parameterTypes;
+            return this;
+        }
+
+        public Builder rpcExt(String rpcExt) {
+            this.rpcExt = rpcExt;
+            return this;
+        }
+
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public Builder dateCreated(Date dateCreated) {
+            this.dateCreated = dateCreated;
+            return this;
+        }
+
+        public Builder dateUpdated(Date dateUpdated) {
+            this.dateUpdated = dateUpdated;
+            return this;
+        }
+
+        public Builder enabled(boolean enabled) {
+            this.enabled = enabled;
+            return this;
+        }
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/PaginatedResources.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/PaginatedResources.java
similarity index 96%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/PaginatedResources.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/PaginatedResources.java
index 4b4dd4fb9..74e2fa760 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/PaginatedResources.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/PaginatedResources.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import java.util.List;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/Pagination.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/Pagination.java
similarity index 97%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/Pagination.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/Pagination.java
index 019a26f9d..aa41c21bb 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/Pagination.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/Pagination.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonAlias;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/PluginDTO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/PluginDTO.java
similarity index 98%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/PluginDTO.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/PluginDTO.java
index cc144242f..72c9425dd 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/PluginDTO.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/PluginDTO.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/ResourceDTO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/ResourceDTO.java
similarity index 94%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/ResourceDTO.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/ResourceDTO.java
index c7d9f9996..703a32d1a 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/ResourceDTO.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/ResourceDTO.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/RuleDTO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/RuleDTO.java
similarity index 64%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/RuleDTO.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/RuleDTO.java
index adde30275..995efd5c7 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/RuleDTO.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/RuleDTO.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonAlias;
 import com.fasterxml.jackson.annotation.JsonFormat;
@@ -55,6 +55,29 @@ public class RuleDTO implements ResourceDTO {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date dateUpdated;
 
+    private RuleDTO() {
+
+    }
+
+    private RuleDTO(Builder builder) {
+        this.id = builder.id;
+        this.name = builder.name;
+        this.selectorId = builder.selectorId;
+        this.matchMode = builder.matchMode;
+        this.matchModeName = builder.matchModeName;
+        this.sort = builder.sort;
+        this.logged = builder.logged;
+        this.enabled = builder.enabled;
+        this.handle = builder.handle;
+        this.ruleConditions = builder.ruleConditions;
+        this.dateCreated = builder.dateCreated;
+        this.dateUpdated = builder.dateUpdated;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
     /**
      * get id.
      *
@@ -274,4 +297,102 @@ public class RuleDTO implements ResourceDTO {
     public void setDateUpdated(Date dateUpdated) {
         this.dateUpdated = dateUpdated;
     }
+
+    public static final class Builder {
+
+        private String id;
+
+        private String name;
+
+        private String selectorId;
+
+        private int matchMode;
+
+        private String matchModeName;
+
+        private int sort;
+
+        @JsonAlias("loged")
+        private boolean logged;
+
+        private boolean enabled;
+
+        private String handle;
+
+        private JsonNode ruleConditions;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private Date dateCreated;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+        private Date dateUpdated;
+
+        private Builder() {
+
+        }
+
+        public RuleDTO build() {
+            return new RuleDTO(this);
+        }
+
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        public Builder selectorId(String selectorId) {
+            this.selectorId = selectorId;
+            return this;
+        }
+
+        public Builder matchMode(int matchMode) {
+            this.matchMode = matchMode;
+            return this;
+        }
+
+        public Builder matchModeName(String matchModeName) {
+            this.matchModeName = matchModeName;
+            return this;
+        }
+
+        public Builder sort(int sort) {
+            this.sort = sort;
+            return this;
+        }
+
+        public Builder logged(boolean logged) {
+            this.logged = logged;
+            return this;
+        }
+
+        public Builder enabled(boolean enabled) {
+            this.enabled = enabled;
+            return this;
+        }
+
+        public Builder handle(String handle) {
+            this.handle = handle;
+            return this;
+        }
+
+        public Builder ruleConditions(JsonNode ruleConditions) {
+            this.ruleConditions = ruleConditions;
+            return this;
+        }
+
+        public Builder dateCreated(Date dateCreated) {
+            this.dateCreated = dateCreated;
+            return this;
+        }
+
+        public Builder dateUpdated(Date dateUpdated) {
+            this.dateUpdated = dateUpdated;
+            return this;
+        }
+    }
 }
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/SearchedResources.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/SearchedResources.java
similarity index 97%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/SearchedResources.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/SearchedResources.java
index b92550ffb..252b1cd3c 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/SearchedResources.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/SearchedResources.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
diff --git a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/SelectorDTO.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/SelectorDTO.java
similarity index 63%
rename from shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/SelectorDTO.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/SelectorDTO.java
index 52a1182e6..956653fe6 100644
--- a/shenyu-e2e/shenyu-e2e-client/src/main/java/org/apache/shenyu/e2e/client/admin/model/response/SelectorDTO.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/model/response/SelectorDTO.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.client.admin.model.response;
+package org.apache.shenyu.e2e.model.response;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition;
+import org.apache.shenyu.e2e.model.data.Condition;
 
 import java.util.Date;
 import java.util.List;
@@ -63,6 +63,32 @@ public class SelectorDTO implements ResourceDTO {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
     private Date dateUpdated;
 
+    private SelectorDTO() {
+
+    }
+
+    private SelectorDTO(Builder builder) {
+        this.id = builder.id;
+        this.pluginId = builder.pluginId;
+        this.name = builder.name;
+        this.matchMode = builder.matchMode;
+        this.matchModeName = builder.matchModeName;
+        this.type = builder.type;
+        this.typeName = builder.typeName;
+        this.sort = builder.sort;
+        this.enabled = builder.enabled;
+        this.logged = builder.logged;
+        this.continued = builder.continued;
+        this.handle = builder.handle;
+        this.conditionList = builder.conditionList;
+        this.dateCreated = builder.dateCreated;
+        this.dateUpdated = builder.dateUpdated;
+    }
+
+    public static Builder builder() {
+        return new Builder();
+    }
+
     /**
      * get id.
      *
@@ -336,4 +362,124 @@ public class SelectorDTO implements ResourceDTO {
     public void setDateUpdated(Date dateUpdated) {
         this.dateUpdated = dateUpdated;
     }
+
+    public static final class Builder {
+
+        private String id;
+
+        private String pluginId;
+
+        private String name;
+
+        private int matchMode;
+
+        private String matchModeName;
+
+        private int type;
+
+        private String typeName;
+
+        private int sort;
+
+        private boolean enabled;
+
+        @JsonProperty(value = "loged")
+        private boolean logged;
+
+        private boolean continued;
+
+        private String handle;
+
+        @JsonProperty("selectorConditions")
+        private List<Condition> conditionList;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
+        private Date dateCreated;
+
+        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
+        private Date dateUpdated;
+
+        private Builder() {
+
+        }
+
+        public SelectorDTO build() {
+            return new SelectorDTO(this);
+        }
+
+        public Builder id(String id) {
+            this.id = id;
+            return this;
+        }
+
+        public Builder pluginId(String pluginId) {
+            this.pluginId = pluginId;
+            return this;
+        }
+
+        public Builder name(String name) {
+            this.name = name;
+            return this;
+        }
+
+        public Builder matchMode(int matchMode) {
+            this.matchMode = matchMode;
+            return this;
+        }
+
+        public Builder matchModeName(String matchModeName) {
+            this.matchModeName = matchModeName;
+            return this;
+        }
+
+        public Builder type(int type) {
+            this.type = type;
+            return this;
+        }
+
+        public Builder typeName(String typeName) {
+            this.typeName = typeName;
+            return this;
+        }
+
+        public Builder sort(int sort) {
+            this.sort = sort;
+            return this;
+        }
+
+        public Builder enabled(boolean enabled) {
+            this.enabled = enabled;
+            return this;
+        }
+
+        public Builder logged(boolean logged) {
+            this.logged = logged;
+            return this;
+        }
+
+        public Builder continued(boolean continued) {
+            this.continued = continued;
+            return this;
+        }
+
+        public Builder handle(String handle) {
+            this.handle = handle;
+            return this;
+        }
+
+        public Builder conditionList(List<Condition> conditionList) {
+            this.conditionList = conditionList;
+            return this;
+        }
+
+        public Builder dateCreated(Date dateCreated) {
+            this.dateCreated = dateCreated;
+            return this;
+        }
+
+        public Builder dateUpdated(Date dateUpdated) {
+            this.dateUpdated = dateUpdated;
+            return this;
+        }
+    }
 }
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/ResourceDataTemplate.java b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/template/ResourceDataTemplate.java
similarity index 74%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/ResourceDataTemplate.java
rename to shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/template/ResourceDataTemplate.java
index f91930a8e..c862eabaa 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/ResourceDataTemplate.java
+++ b/shenyu-e2e/shenyu-e2e-common/src/main/java/org/apache/shenyu/e2e/template/ResourceDataTemplate.java
@@ -15,22 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common;
+package org.apache.shenyu.e2e.template;
 
 import com.google.common.base.Strings;
-import org.apache.shenyu.e2e.client.admin.model.MatchMode;
-import org.apache.shenyu.e2e.client.admin.model.Plugin;
-import org.apache.shenyu.e2e.client.admin.model.SelectorType;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition.Operator;
-import org.apache.shenyu.e2e.client.admin.model.data.Condition.ParamType;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleData;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorData;
-import org.apache.shenyu.e2e.client.admin.model.handle.DivideRuleHandle;
-import org.apache.shenyu.e2e.client.admin.model.handle.Upstreams;
-import org.apache.shenyu.e2e.client.admin.model.handle.Upstreams.Upstream;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
+import groovyjarjarantlr4.v4.runtime.misc.NotNull;
+import groovyjarjarantlr4.v4.runtime.misc.Nullable;
+import org.apache.shenyu.e2e.model.MatchMode;
+import org.apache.shenyu.e2e.model.Plugin;
+import org.apache.shenyu.e2e.model.SelectorType;
+import org.apache.shenyu.e2e.model.data.Condition;
+import org.apache.shenyu.e2e.model.data.RuleData;
+import org.apache.shenyu.e2e.model.data.SelectorData;
+import org.apache.shenyu.e2e.model.handle.DivideRuleHandle;
+import org.apache.shenyu.e2e.model.handle.Upstreams;
 
 import javax.annotation.Nonnull;
 import java.util.ArrayList;
@@ -106,11 +103,11 @@ public class ResourceDataTemplate {
      * @param value value
      * @return Condition
      */
-    public static Condition newCondition(ParamType type, Operator opt, String value) {
+    public static Condition newCondition(Condition.ParamType type, Condition.Operator opt, String value) {
         return newCondition(type, opt, null, value);
     }
     
-    public static Condition newCondition(ParamType type, Operator opt, @Nullable String key, String value) {
+    public static Condition newCondition(Condition.ParamType type, Condition.Operator opt, @Nullable String key, String value) {
         return Condition.builder()
                 .paramType(type)
                 .operator(opt)
@@ -119,7 +116,7 @@ public class ResourceDataTemplate {
                 .build();
     }
     
-    public static List<Condition> newConditions(ParamType type, Operator opt, String value) {
+    public static List<Condition> newConditions(Condition.ParamType type, Condition.Operator opt, String value) {
         ArrayList<Condition> list = new ArrayList<>();
         list.add(newCondition(type, opt, value));
         return list;
@@ -131,8 +128,8 @@ public class ResourceDataTemplate {
      * @param url url
      * @return Upstream
      */
-    public static Upstream newUpstream(String url) {
-        return Upstream.builder()
+    public static Upstreams.Upstream newUpstream(String url) {
+        return Upstreams.Upstream.builder()
                 .upstreamUrl(url)
                 .build();
     }
diff --git a/shenyu-e2e/shenyu-e2e-engine/pom.xml b/shenyu-e2e/shenyu-e2e-engine/pom.xml
index 00e774cd0..af4e40238 100644
--- a/shenyu-e2e/shenyu-e2e-engine/pom.xml
+++ b/shenyu-e2e/shenyu-e2e-engine/pom.xml
@@ -74,5 +74,12 @@
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-core</artifactId>
+            <version>5.3.23</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/handler/AdminDataSynHandler.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/handler/AdminDataSynHandler.java
new file mode 100644
index 000000000..2f0b70814
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/handler/AdminDataSynHandler.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.engine.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Admin DataSyn Handler.
+ */
+public class AdminDataSynHandler {
+    private static final Map<String, Map<String, Object>> DATA_SYN_MAP = new HashMap<>();
+
+    private static final Map<String, Object> WEBSOCKET_MAP = new HashMap<>();
+
+    private static final Map<String, Object> ZOOKEEPER_MAP = new HashMap<>();
+
+    private static final Map<String, Object> APOLLO_MAP = new HashMap<>();
+
+    private static final Map<String, Object> HTTP_MAP = new HashMap<>();
+
+    private static final Map<String, Object> NACOS_MAP = new HashMap<>();
+
+    private static final Map<String, Object> ACM_MAP = new HashMap<>();
+
+    public static void init() {
+        DATA_SYN_MAP.put("websocket", WEBSOCKET_MAP);
+        DATA_SYN_MAP.put("zookeeper", ZOOKEEPER_MAP);
+        DATA_SYN_MAP.put("apollo", APOLLO_MAP);
+        DATA_SYN_MAP.put("http", HTTP_MAP);
+        DATA_SYN_MAP.put("nacos", NACOS_MAP);
+
+        WEBSOCKET_MAP.put("enabled", "true");
+
+        ZOOKEEPER_MAP.put("url", "localhost:2181");
+        ZOOKEEPER_MAP.put("sessionTimeout", "5000");
+        ZOOKEEPER_MAP.put("connectionTimeout", "2000");
+
+        HTTP_MAP.put("enabled", "true");
+
+        NACOS_MAP.put("url", "localhost:8848");
+        NACOS_MAP.put("namespace", "1c10d748-af86-43b9-8265-75f487d20c6c");
+        NACOS_MAP.put("username", "");
+        NACOS_MAP.put("password", "");
+        ACM_MAP.put("enabled", "false");
+        ACM_MAP.put("endpoint", "acm.aliyun.com");
+        ACM_MAP.put("namespace", "");
+        ACM_MAP.put("accessKey", "");
+        ACM_MAP.put("secretKey", "");
+        NACOS_MAP.put("acm", ACM_MAP);
+
+        APOLLO_MAP.put("meta", "http://localhost:8080");
+        APOLLO_MAP.put("appId", "shenyu");
+        APOLLO_MAP.put("portalUrl", "http://localhost:8070");
+        APOLLO_MAP.put("env", "dev");
+        APOLLO_MAP.put("clusterName", "test");
+        APOLLO_MAP.put("namespace", "application");
+        APOLLO_MAP.put("token", "0fff5645fc74ee5e0d63a6389433c8c8afc0beea31eed0279ecc1c8961d12da9");
+    }
+
+    public static Map<String, Object> getDataSynMap(String dataSyn) {
+        return DATA_SYN_MAP.get(dataSyn);
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/handler/GatewayDataSynHandler.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/handler/GatewayDataSynHandler.java
new file mode 100644
index 000000000..58602b50f
--- /dev/null
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/handler/GatewayDataSynHandler.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.e2e.engine.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Gateway DataSyn Handler.
+ */
+public class GatewayDataSynHandler {
+
+    private static final Map<String, Map<String, Object>> DATA_SYN_MAP = new HashMap<>();
+
+    private static final Map<String, Object> WEBSOCKET_MAP = new HashMap<>();
+
+    private static final Map<String, Object> ZOOKEEPER_MAP = new HashMap<>();
+
+    private static final Map<String, Object> APOLLO_MAP = new HashMap<>();
+
+    private static final Map<String, Object> HTTP_MAP = new HashMap<>();
+
+    private static final Map<String, Object> NACOS_MAP = new HashMap<>();
+
+    private static final Map<String, Object> ACM_MAP = new HashMap<>();
+
+    public static void init() {
+        DATA_SYN_MAP.put("websocket", WEBSOCKET_MAP);
+        DATA_SYN_MAP.put("zookeeper", ZOOKEEPER_MAP);
+        DATA_SYN_MAP.put("apollo", APOLLO_MAP);
+        DATA_SYN_MAP.put("http", HTTP_MAP);
+        DATA_SYN_MAP.put("nacos", NACOS_MAP);
+
+        WEBSOCKET_MAP.put("urls", "ws://localhost:9095/websocket");
+
+        ZOOKEEPER_MAP.put("url", "localhost:2181");
+        ZOOKEEPER_MAP.put("sessionTimeout", "5000");
+        ZOOKEEPER_MAP.put("connectionTimeout", "2000");
+
+        HTTP_MAP.put("url", "http://localhost:9095");
+
+        NACOS_MAP.put("url", "localhost:8848");
+        NACOS_MAP.put("namespace", "1c10d748-af86-43b9-8265-75f487d20c6c");
+        NACOS_MAP.put("username", "");
+        NACOS_MAP.put("password", "");
+        ACM_MAP.put("enabled", "false");
+        ACM_MAP.put("endpoint", "acm.aliyun.com");
+        ACM_MAP.put("namespace", "");
+        ACM_MAP.put("accessKey", "");
+        ACM_MAP.put("secretKey", "");
+        NACOS_MAP.put("acm", ACM_MAP);
+
+        APOLLO_MAP.put("appId", "shenyu");
+        APOLLO_MAP.put("meta", "http://localhost:8080");
+        APOLLO_MAP.put("env", "dev");
+        APOLLO_MAP.put("clusterName", "test");
+        APOLLO_MAP.put("namespace", "application");
+    }
+
+    public static Map<String, Object> getDataSynMap(String dataSyn) {
+        return DATA_SYN_MAP.get(dataSyn);
+    }
+}
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpChecker.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpChecker.java
similarity index 92%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpChecker.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpChecker.java
index d76b39ead..54b108537 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpChecker.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpChecker.java
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.function;
+package org.apache.shenyu.e2e.engine.scenario.function;
 
 import io.restassured.specification.RequestSpecification;
 import org.apache.shenyu.e2e.client.gateway.GatewayClient;
-import org.apache.shenyu.e2e.engine.scenario.function.Checker;
 import org.slf4j.MDC;
 
 import java.util.function.Supplier;
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpCheckers.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpCheckers.java
similarity index 98%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpCheckers.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpCheckers.java
index 4d2d3480a..ee6fba5c1 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpCheckers.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpCheckers.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.function;
+package org.apache.shenyu.e2e.engine.scenario.function;
 
 import io.restassured.http.Method;
 import org.junit.jupiter.api.Assertions;
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpVerifier.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpVerifier.java
similarity index 94%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpVerifier.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpVerifier.java
index fb205e137..a24cf21bf 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpVerifier.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpVerifier.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.function;
+package org.apache.shenyu.e2e.engine.scenario.function;
 
 import org.apache.shenyu.e2e.engine.scenario.function.Verifier;
 
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpWaiting.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpWaiting.java
similarity index 95%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpWaiting.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpWaiting.java
index c3c079761..f94959ebe 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/HttpWaiting.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/HttpWaiting.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.function;
+package org.apache.shenyu.e2e.engine.scenario.function;
 
 import io.restassured.specification.RequestSpecification;
 import org.apache.shenyu.e2e.client.gateway.GatewayClient;
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/WaitForHelper.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/WaitForHelper.java
similarity index 99%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/WaitForHelper.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/WaitForHelper.java
index 88d4ac0ca..d46af5cec 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/function/WaitForHelper.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/function/WaitForHelper.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.function;
+package org.apache.shenyu.e2e.engine.scenario.function;
 
 import com.google.common.util.concurrent.MoreExecutors;
 import io.restassured.http.Method;
diff --git a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/BeforeEachSpec.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/BeforeEachSpec.java
index 3f5caa93f..0eb0cfdeb 100644
--- a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/BeforeEachSpec.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/BeforeEachSpec.java
@@ -17,7 +17,7 @@
 
 package org.apache.shenyu.e2e.engine.scenario.specification;
 
-import org.apache.shenyu.e2e.client.admin.model.ResourcesData;
+import org.apache.shenyu.e2e.model.ResourcesData;
 import org.apache.shenyu.e2e.engine.annotation.ShenYuScenarioParameter;
 import org.apache.shenyu.e2e.engine.scenario.function.Checker;
 import org.apache.shenyu.e2e.engine.scenario.function.Waiting;
diff --git a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ScenarioSpecLogProxy.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ScenarioSpecLogProxy.java
index 09af2aaca..fb3010acb 100644
--- a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ScenarioSpecLogProxy.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ScenarioSpecLogProxy.java
@@ -17,7 +17,7 @@
 
 package org.apache.shenyu.e2e.engine.scenario.specification;
 
-import org.apache.shenyu.e2e.client.admin.model.ResourcesData;
+import org.apache.shenyu.e2e.model.ResourcesData;
 import org.apache.shenyu.e2e.engine.scenario.function.Checker;
 import org.apache.shenyu.e2e.engine.scenario.function.Deleter;
 import org.apache.shenyu.e2e.engine.scenario.function.Verifier;
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuAfterEachSpec.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuAfterEachSpec.java
similarity index 92%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuAfterEachSpec.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuAfterEachSpec.java
index acd9a1c17..ce5c1489d 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuAfterEachSpec.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuAfterEachSpec.java
@@ -15,11 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.specification;
+package org.apache.shenyu.e2e.engine.scenario.specification;
 
 import org.apache.shenyu.e2e.engine.scenario.function.Checker;
 import org.apache.shenyu.e2e.engine.scenario.function.Deleter;
-import org.apache.shenyu.e2e.engine.scenario.specification.AfterEachSpec;
 
 /**
  * ShenYu after each specification.
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuBeforeEachSpec.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuBeforeEachSpec.java
similarity index 85%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuBeforeEachSpec.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuBeforeEachSpec.java
index 0fc547523..5c49bd603 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuBeforeEachSpec.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuBeforeEachSpec.java
@@ -15,20 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.specification;
+package org.apache.shenyu.e2e.engine.scenario.specification;
 
+import org.apache.shenyu.e2e.engine.scenario.function.HttpChecker;
+import org.apache.shenyu.e2e.engine.scenario.function.HttpWaiting;
+import org.apache.shenyu.e2e.engine.scenario.function.WaitForHelper;
 import io.restassured.http.Method;
 import io.restassured.specification.ResponseSpecification;
-import org.apache.shenyu.e2e.client.admin.model.ResourcesData;
-import org.apache.shenyu.e2e.client.admin.model.ResourcesData.ResourcesDataBuilder;
-import org.apache.shenyu.e2e.client.admin.model.data.RuleData;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorData;
+import org.apache.shenyu.e2e.model.ResourcesData;
+import org.apache.shenyu.e2e.model.ResourcesData.ResourcesDataBuilder;
+import org.apache.shenyu.e2e.model.data.RuleData;
+import org.apache.shenyu.e2e.model.data.SelectorData;
 import org.apache.shenyu.e2e.engine.scenario.function.Checker;
 import org.apache.shenyu.e2e.engine.scenario.function.Waiting;
-import org.apache.shenyu.e2e.engine.scenario.specification.BeforeEachSpec;
-import org.apache.shenyu.e2e.testcase.common.function.HttpChecker;
-import org.apache.shenyu.e2e.testcase.common.function.HttpWaiting;
-import org.apache.shenyu.e2e.testcase.common.function.WaitForHelper;
 import org.jetbrains.annotations.NotNull;
 
 /**
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuCaseSpec.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuCaseSpec.java
similarity index 93%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuCaseSpec.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuCaseSpec.java
index eb4950b7b..f390526b7 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuCaseSpec.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuCaseSpec.java
@@ -15,19 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.specification;
+package org.apache.shenyu.e2e.engine.scenario.specification;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
 import io.restassured.http.Method;
 import org.apache.shenyu.e2e.engine.scenario.function.Verifier;
-import org.apache.shenyu.e2e.engine.scenario.specification.CaseSpec;
 import org.hamcrest.Matcher;
 
 import java.util.List;
 
-import static org.apache.shenyu.e2e.testcase.common.function.HttpCheckers.exists;
-import static org.apache.shenyu.e2e.testcase.common.function.HttpCheckers.notExists;
+import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.exists;
+import static org.apache.shenyu.e2e.engine.scenario.function.HttpCheckers.notExists;
+
 
 /**
  * ShenYu case specification.
diff --git a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuScenarioSpec.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuScenarioSpec.java
similarity index 90%
rename from shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuScenarioSpec.java
rename to shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuScenarioSpec.java
index ee6f00cc9..00e77ae28 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/main/java/org/apache/shenyu/e2e/testcase/common/specification/ShenYuScenarioSpec.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/scenario/specification/ShenYuScenarioSpec.java
@@ -15,14 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.specification;
+package org.apache.shenyu.e2e.engine.scenario.specification;
 
 import com.google.common.base.Strings;
 import org.apache.shenyu.e2e.common.IdGenerator;
-import org.apache.shenyu.e2e.engine.scenario.specification.AfterEachSpec;
-import org.apache.shenyu.e2e.engine.scenario.specification.BeforeEachSpec;
-import org.apache.shenyu.e2e.engine.scenario.specification.CaseSpec;
-import org.apache.shenyu.e2e.engine.scenario.specification.ScenarioSpec;
 import org.junit.jupiter.api.Assertions;
 
 /**
diff --git a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/service/DockerServiceCompose.java b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/service/DockerServiceCompose.java
index 9d2ceea17..bc4a5cc40 100644
--- a/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/service/DockerServiceCompose.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/main/java/org/apache/shenyu/e2e/engine/service/DockerServiceCompose.java
@@ -26,14 +26,25 @@ import org.apache.shenyu.e2e.client.gateway.GatewayClient;
 import org.apache.shenyu.e2e.common.TableView;
 import org.apache.shenyu.e2e.engine.config.ShenYuEngineConfigure.DockerConfigure;
 import org.apache.shenyu.e2e.engine.config.ShenYuEngineConfigure.DockerConfigure.DockerServiceConfigure;
+import org.apache.shenyu.e2e.engine.handler.GatewayDataSynHandler;
 import org.apache.shenyu.e2e.engine.service.docker.DockerComposeFile;
 import org.apache.shenyu.e2e.engine.service.docker.ShenYuLogConsumer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testcontainers.containers.ContainerState;
 import org.testcontainers.containers.DockerComposeContainer;
+import org.testcontainers.shaded.org.yaml.snakeyaml.DumperOptions;
+import org.testcontainers.shaded.org.yaml.snakeyaml.Yaml;
 
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
@@ -44,6 +55,10 @@ public class DockerServiceCompose implements ServiceCompose {
 
     private static final Logger log = LoggerFactory.getLogger(DockerServiceCompose.class);
 
+    private static final String GATEWAY_YML_LOCATION = "../../../shenyu-bootstrap/target/classes/application.yml";
+
+    private static final String ADMIN_YML_LOCATION = "../../../shenyu-admin/target/classes/application.yml";
+
     private final DockerComposeContainer<?> container;
 
     private final DockerConfigure configure;
@@ -58,10 +73,11 @@ public class DockerServiceCompose implements ServiceCompose {
         this.configure = configure;
         this.adminConfigure = configure.getAdmin();
         this.gatewayConfigure = configure.getGateway();
-        
+//        modifyGatewayConfiguration(this.gatewayConfigure);
+//        chooseDataSyn(GATEWAY_YML_LOCATION, this.gatewayConfigure);
+//        chooseDataSyn(ADMIN_YML_LOCATION, this.adminConfigure);
         DockerComposeFile parsedDockerComposeFile = DockerComposeFile.parse(configure.getDockerComposeFile());
         container = new DockerComposeContainer<>("e2e", parsedDockerComposeFile.getFile());
-        
         List<String> services = parsedDockerComposeFile.getServices();
         services.forEach(name -> container.withLogConsumer(name, new ShenYuLogConsumer(name)));
     }
@@ -170,4 +186,82 @@ public class DockerServiceCompose implements ServiceCompose {
     public void stop() {
         container.stop();
     }
+
+    private void modifyGatewayConfiguration(DockerServiceConfigure gatewayConfigure) {
+        String value = gatewayConfigure.getProperties().getProperty("application");
+        if (Objects.isNull(value)) {
+            return;
+        }
+
+        try (InputStream inputStream = new FileInputStream(GATEWAY_YML_LOCATION)) {
+            Yaml yaml = new Yaml();
+            Map<String, Object> yamlData = yaml.load(inputStream);
+            String[] sonValues = value.split(",");
+            for (String sonValue : sonValues) {
+                String[] subModule = sonValue.split("\\:");
+
+                String[] subModulePath = subModule[0].split("\\.");
+
+                modifyYamlValue(yamlData, subModulePath, subModule[1]);
+            }
+
+            DumperOptions options = new DumperOptions();
+            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+            options.setExplicitStart(true);
+            options.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
+            yaml = new Yaml(options);
+            try (OutputStream outputStream = new FileOutputStream(GATEWAY_YML_LOCATION)) {
+                yaml.dump(yamlData, new OutputStreamWriter(outputStream));
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void modifyYamlValue(Map<String, Object> yamlData, String[] subModulePath, String newValue) {
+        if (subModulePath.length == 0) {
+            return;
+        }
+
+        Map<String, Object> currentMap = yamlData;
+        for (int i = 0; i < subModulePath.length - 1; i++) {
+            if (!currentMap.containsKey(subModulePath[i])) {
+                currentMap.put(subModulePath[i], new LinkedHashMap<>());
+            }
+            currentMap = (Map<String, Object>) currentMap.get(subModulePath[i]);
+        }
+
+        currentMap.put(subModulePath[subModulePath.length - 1], newValue);
+    }
+
+    private void chooseDataSyn(String path, DockerServiceConfigure dockerServiceConfigure) {
+
+        String yamlFilePath = path;
+
+        try (InputStream inputStream = new FileInputStream(yamlFilePath)) {
+            Yaml yaml = new Yaml();
+            Map<String, Object> yamlData = yaml.load(inputStream);
+
+            Map<String, Object> shenyuParameter = (Map<String, Object>) yamlData.get("shenyu");
+            Map<String, Object> parameter = (Map<String, Object>) shenyuParameter.get("sync");
+
+            String synMethod = dockerServiceConfigure.getProperties().getProperty("dataSyn");
+            Map<String, Object> subParameters = GatewayDataSynHandler.getDataSynMap(synMethod);
+            parameter.put(synMethod, subParameters);
+            parameter.keySet().removeIf(key -> !key.equals(synMethod));
+
+            DumperOptions options = new DumperOptions();
+            options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+            options.setExplicitStart(true);
+            options.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
+            yaml = new Yaml(options);
+
+            try (OutputStream outputStream = new FileOutputStream(yamlFilePath)) {
+                yaml.dump(yamlData, new OutputStreamWriter(outputStream));
+                System.out.println("YAML file modified successfully.");
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
 }
diff --git a/shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/ShenYuEngineTest.java b/shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/ShenYuEngineTest.java
index cae7b9ee8..51a2a8d3c 100644
--- a/shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/ShenYuEngineTest.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/ShenYuEngineTest.java
@@ -19,9 +19,9 @@ package org.apache.shenyu.e2e.engine;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import org.apache.shenyu.e2e.client.admin.AdminClient;
-import org.apache.shenyu.e2e.client.admin.model.data.SelectorQueryCondition;
-import org.apache.shenyu.e2e.client.admin.model.response.SearchedResources;
-import org.apache.shenyu.e2e.client.admin.model.response.SelectorDTO;
+import org.apache.shenyu.e2e.model.data.SelectorQueryCondition;
+import org.apache.shenyu.e2e.model.response.SearchedResources;
+import org.apache.shenyu.e2e.model.response.SelectorDTO;
 import org.apache.shenyu.e2e.engine.annotation.ShenYuTest;
 import org.apache.shenyu.e2e.engine.annotation.ShenYuTest.Parameter;
 import org.apache.shenyu.e2e.engine.annotation.ShenYuTest.ServiceConfigure;
diff --git a/shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/common/function/WaitForHelperTest.java b/shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/function/WaitForHelperTest.java
similarity index 94%
rename from shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/common/function/WaitForHelperTest.java
rename to shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/function/WaitForHelperTest.java
index afb60e382..fbe246739 100644
--- a/shenyu-e2e/shenyu-e2e-case/src/test/java/org/apache/shenyu/e2e/testcase/common/function/WaitForHelperTest.java
+++ b/shenyu-e2e/shenyu-e2e-engine/src/test/java/org/apache/shenyu/e2e/engine/function/WaitForHelperTest.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.e2e.testcase.common.function;
+package org.apache.shenyu.e2e.engine.function;
 
+import org.apache.shenyu.e2e.engine.scenario.function.WaitForHelper;
 import io.restassured.builder.ResponseSpecBuilder;
 import io.restassured.http.Method;
-import org.apache.shenyu.e2e.testcase.common.function.WaitForHelper;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;