You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by mi...@apache.org on 2018/11/29 10:43:42 UTC

[incubator-dubbo-ops] branch metadata updated: support dubbo2.7 & tag router

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

min pushed a commit to branch metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo-ops.git


The following commit(s) were added to refs/heads/metadata by this push:
     new 1177f83  support dubbo2.7 & tag router
1177f83 is described below

commit 1177f83544ae0394cdb719336dd17bf5cb8f46f0
Author: nzomkxia <z8...@gmail.com>
AuthorDate: Thu Nov 29 18:44:03 2018 +0800

    support dubbo2.7 & tag router
---
 dubbo-admin-backend/pom.xml                        |    4 +
 .../apache/dubbo/admin/common/util/Constants.java  |    8 +
 .../dubbo/admin/common/util/OverrideUtils.java     |  274 ++---
 .../apache/dubbo/admin/common/util/RouteRule.java  | 1126 ++++++++++----------
 .../apache/dubbo/admin/common/util/SyncUtils.java  |   85 +-
 .../apache/dubbo/admin/config/ConfigCenter.java    |    3 +-
 .../dubbo/admin/controller/AccessesController.java |  328 +++---
 ...troller.java => ConditionRoutesController.java} |  137 ++-
 .../admin/controller/LoadBalanceController.java    |  268 ++---
 .../admin/controller/OverridesController.java      |  226 ++--
 .../admin/controller/TagRoutesController.java      |  114 ++
 .../dubbo/admin/controller/WeightController.java   |  244 ++---
 .../admin/data/config/GovernanceConfiguration.java |    2 +
 .../data/config/impl/ApolloConfiguration.java      |    5 +
 .../data/config/impl/ZookeeperConfiguration.java   |   40 +-
 .../metadata/impl/ZookeeperMetaDataCollector.java  |    3 +-
 .../dubbo/admin/model/domain/ConditionRoute.java   |   22 +
 .../apache/dubbo/admin/model/domain/Consumer.java  |   12 +-
 .../apache/dubbo/admin/model/domain/Operation.java |    2 +-
 .../apache/dubbo/admin/model/domain/Override.java  |  172 +--
 .../dubbo/admin/model/domain/OverrideConfig.java   |   60 ++
 .../org/apache/dubbo/admin/model/domain/Route.java |  219 +---
 .../org/apache/dubbo/admin/model/domain/Tag.java   |   25 +
 .../apache/dubbo/admin/model/domain/TagRoute.java  |   15 +
 .../dubbo/admin/model/dto/ConditionRouteDTO.java   |   22 +
 .../apache/dubbo/admin/model/dto/OverrideDTO.java  |   56 +-
 .../org/apache/dubbo/admin/model/dto/RouteDTO.java |   30 +-
 .../apache/dubbo/admin/model/dto/TagRouteDTO.java  |   16 +
 .../dubbo/admin/service/OverrideService.java       |   14 +-
 .../dubbo/admin/service/ProviderService.java       |    8 +-
 .../apache/dubbo/admin/service/RouteService.java   |   37 +-
 .../admin/service/impl/OverrideServiceImpl.java    |  154 +--
 .../dubbo/admin/service/impl/OwnerServiceImpl.java |  318 +++---
 .../admin/service/impl/ProviderServiceImpl.java    |  274 ++---
 .../dubbo/admin/service/impl/RouteServiceImpl.java |  212 ++--
 dubbo-admin-frontend/src/api/menu.js               |    1 +
 .../src/components/ServiceSearch.vue               |   29 +-
 .../src/components/governance/AccessControl.vue    |    9 +-
 .../src/components/governance/LoadBalance.vue      |    7 +-
 .../src/components/governance/Overrides.vue        |  186 +++-
 .../src/components/governance/RoutingRule.vue      |  224 ++--
 .../governance/{RoutingRule.vue => TagRule.vue}    |  134 ++-
 .../src/components/governance/WeightAdjust.vue     |    7 +-
 dubbo-admin-frontend/src/router/index.js           |    6 +
 pom.xml                                            |    6 +
 45 files changed, 2598 insertions(+), 2546 deletions(-)

diff --git a/dubbo-admin-backend/pom.xml b/dubbo-admin-backend/pom.xml
index 879b1ee..7986fbd 100644
--- a/dubbo-admin-backend/pom.xml
+++ b/dubbo-admin-backend/pom.xml
@@ -62,6 +62,10 @@
             <artifactId>apollo-openapi</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.dubbo</groupId>
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index 9e4c5d0..24d976b 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -5,5 +5,13 @@ public class Constants {
 
     public static final String REGISTRY_ADDRESS = "dubbo.registry.address";
     public static final String METADATA_ADDRESS = "dubbo.metadatareport.address";
+    public static final String DEFAULT_ROOT = "dubbo";
+    public static final String PATH_SEPARATOR = "/";
+    public static final String GROUP_KEY = "group";
+    public static final String CONFIG_KEY = "config";
+    public static final String CATEGORY_KEY = "category";
+    public static final String ROUTERS_CATEGORY = "routers";
+    public static final String CONDITION_ROUTE = "condition_route";
+    public static final String TAG_ROUTE = "tag_route";
 
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/OverrideUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/OverrideUtils.java
index e7b55d6..87778dd 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/OverrideUtils.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/OverrideUtils.java
@@ -1,137 +1,137 @@
-/*
- * 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.dubbo.admin.common.util;
-
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.model.domain.LoadBalance;
-import org.apache.dubbo.admin.model.domain.Override;
-import org.apache.dubbo.admin.model.domain.Weight;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-/**
- * OverrideUtils.java
- *
- */
-public class OverrideUtils {
-    public static List<Weight> overridesToWeights(List<Override> overrides) {
-        List<Weight> weights = new ArrayList<Weight>();
-        if (overrides == null) {
-            return weights;
-        }
-        for (Override o : overrides) {
-            if (StringUtils.isEmpty(o.getParams())) {
-                continue;
-            } else {
-                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
-                for (Map.Entry<String, String> entry : params.entrySet()) {
-                    if (entry.getKey().equals("weight")) {
-                        Weight weight = new Weight();
-                        weight.setAddress(o.getAddress());
-                        weight.setId(o.getId());
-                        weight.setHash(o.getHash());
-                        weight.setService(o.getService());
-                        weight.setWeight(Integer.valueOf(entry.getValue()));
-                        weights.add(weight);
-                    }
-                }
-            }
-        }
-        return weights;
-    }
-
-    public static Weight overrideToWeight(Override override) {
-        List<Weight> weights = OverrideUtils.overridesToWeights(Arrays.asList(override));
-        if (weights != null && weights.size() > 0) {
-            return overridesToWeights(Arrays.asList(override)).get(0);
-        }
-        return null;
-    }
-
-    public static Override weightToOverride(Weight weight) {
-        Override override = new Override();
-        override.setId(weight.getId());
-        override.setHash(weight.getHash());
-        override.setAddress(weight.getAddress());
-        override.setEnabled(true);
-        override.setParams("weight=" + weight.getWeight());
-        override.setService(weight.getService());
-        return override;
-    }
-
-    public static List<LoadBalance> overridesToLoadBalances(List<Override> overrides) {
-        List<LoadBalance> loadBalances = new ArrayList<LoadBalance>();
-        if (overrides == null) {
-            return loadBalances;
-        }
-        for (Override o : overrides) {
-            if (StringUtils.isEmpty(o.getParams())) {
-                continue;
-            } else {
-                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
-                for (Map.Entry<String, String> entry : params.entrySet()) {
-                    if (entry.getKey().endsWith("loadbalance")) {
-                        LoadBalance loadBalance = new LoadBalance();
-                        String method = null;
-                        if (entry.getKey().endsWith(".loadbalance")) {
-                            method = entry.getKey().split(".loadbalance")[0];
-                        } else {
-                            method = "*";
-                        }
-
-                        loadBalance.setMethod(method);
-                        loadBalance.setId(o.getId());
-                        loadBalance.setHash(o.getHash());
-                        loadBalance.setService(o.getService());
-                        loadBalance.setStrategy(entry.getValue());
-                        loadBalances.add(loadBalance);
-
-                    }
-                }
-            }
-        }
-        return loadBalances;
-    }
-
-    public static LoadBalance overrideToLoadBalance(Override override) {
-        List<LoadBalance> loadBalances = OverrideUtils.overridesToLoadBalances(Arrays.asList(override));
-        if (loadBalances != null && loadBalances.size() > 0) {
-            return loadBalances.get(0);
-        }
-        return null;
-    }
-
-    public static Override loadBalanceToOverride(LoadBalance loadBalance) {
-        Override override = new Override();
-        override.setId(loadBalance.getId());
-        override.setHash(loadBalance.getHash());
-        override.setService(loadBalance.getService());
-        override.setEnabled(true);
-        String method = loadBalance.getMethod();
-        String strategy = loadBalance.getStrategy();
-        if (StringUtils.isEmpty(method) || method.equals("*")) {
-            override.setParams("loadbalance=" + strategy);
-        } else {
-            override.setParams(method + ".loadbalance=" + strategy);
-        }
-        return override;
-    }
-
-}
+///*
+// * 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.dubbo.admin.common.util;
+//
+//import org.apache.dubbo.common.utils.StringUtils;
+//import org.apache.dubbo.admin.model.domain.LoadBalance;
+//import org.apache.dubbo.admin.model.domain.Override;
+//import org.apache.dubbo.admin.model.domain.Weight;
+//
+//import java.util.ArrayList;
+//import java.util.Arrays;
+//import java.util.List;
+//import java.util.Map;
+//
+///**
+// * OverrideUtils.java
+// *
+// */
+//public class OverrideUtils {
+//    public static List<Weight> overridesToWeights(List<Override> overrides) {
+//        List<Weight> weights = new ArrayList<Weight>();
+//        if (overrides == null) {
+//            return weights;
+//        }
+//        for (Override o : overrides) {
+//            if (StringUtils.isEmpty(o.getParams())) {
+//                continue;
+//            } else {
+//                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
+//                for (Map.Entry<String, String> entry : params.entrySet()) {
+//                    if (entry.getKey().equals("weight")) {
+//                        Weight weight = new Weight();
+//                        weight.setAddress(o.getAddress());
+//                        weight.setId(o.getId());
+//                        weight.setHash(o.getHash());
+//                        weight.setService(o.getService());
+//                        weight.setWeight(Integer.valueOf(entry.getValue()));
+//                        weights.add(weight);
+//                    }
+//                }
+//            }
+//        }
+//        return weights;
+//    }
+//
+//    public static Weight overrideToWeight(Override override) {
+//        List<Weight> weights = OverrideUtils.overridesToWeights(Arrays.asList(override));
+//        if (weights != null && weights.size() > 0) {
+//            return overridesToWeights(Arrays.asList(override)).get(0);
+//        }
+//        return null;
+//    }
+//
+//    public static Override weightToOverride(Weight weight) {
+//        Override override = new Override();
+//        override.setId(weight.getId());
+//        override.setHash(weight.getHash());
+//        override.setAddress(weight.getAddress());
+//        override.setEnabled(true);
+//        override.setParams("weight=" + weight.getWeight());
+//        override.setService(weight.getService());
+//        return override;
+//    }
+//
+//    public static List<LoadBalance> overridesToLoadBalances(List<Override> overrides) {
+//        List<LoadBalance> loadBalances = new ArrayList<LoadBalance>();
+//        if (overrides == null) {
+//            return loadBalances;
+//        }
+//        for (Override o : overrides) {
+//            if (StringUtils.isEmpty(o.getParams())) {
+//                continue;
+//            } else {
+//                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
+//                for (Map.Entry<String, String> entry : params.entrySet()) {
+//                    if (entry.getKey().endsWith("loadbalance")) {
+//                        LoadBalance loadBalance = new LoadBalance();
+//                        String method = null;
+//                        if (entry.getKey().endsWith(".loadbalance")) {
+//                            method = entry.getKey().split(".loadbalance")[0];
+//                        } else {
+//                            method = "*";
+//                        }
+//
+//                        loadBalance.setMethod(method);
+//                        loadBalance.setId(o.getId());
+//                        loadBalance.setHash(o.getHash());
+//                        loadBalance.setService(o.getService());
+//                        loadBalance.setStrategy(entry.getValue());
+//                        loadBalances.add(loadBalance);
+//
+//                    }
+//                }
+//            }
+//        }
+//        return loadBalances;
+//    }
+//
+//    public static LoadBalance overrideToLoadBalance(Override override) {
+//        List<LoadBalance> loadBalances = OverrideUtils.overridesToLoadBalances(Arrays.asList(override));
+//        if (loadBalances != null && loadBalances.size() > 0) {
+//            return loadBalances.get(0);
+//        }
+//        return null;
+//    }
+//
+//    public static Override loadBalanceToOverride(LoadBalance loadBalance) {
+//        Override override = new Override();
+//        override.setId(loadBalance.getId());
+//        override.setHash(loadBalance.getHash());
+//        override.setService(loadBalance.getService());
+//        override.setEnabled(true);
+//        String method = loadBalance.getMethod();
+//        String strategy = loadBalance.getStrategy();
+//        if (StringUtils.isEmpty(method) || method.equals("*")) {
+//            override.setParams("loadbalance=" + strategy);
+//        } else {
+//            override.setParams(method + ".loadbalance=" + strategy);
+//        }
+//        return override;
+//    }
+//
+//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
index ac9f683..43df3f4 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
@@ -1,563 +1,563 @@
-/*
- * 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.dubbo.admin.common.util;
-
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.model.domain.Route;
-
-import java.text.ParseException;
-import java.util.*;
-import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Router rule can be divided into two parts, When Condition and Then Condition <br>
- * When/Then Confition is expressed in a style of (KV) pair, the V part of the condition pair can contain multiple values (a list) <br>
- * The meaning of Rule: If a request matches When Condition, then use Then Condition to filter providers (only providers match Then Condition will be returned). <br>
- * The process of using Conditions to match consumers and providers is called `Filter`.
- * When Condition are used to filter ConsumersController, while Then Condition are used to filter ProvidersController.
- * RouteRule performs like this: If a Consumer matches When Condition, then only return the ProvidersController matches Then Condition. This means RouteRule should be applied to current Consumer and the providers returned are filtered by RouteRule.<br>
- *
- * An example of Route Rule:<code>
- * key1 = value11,value12 & key2 = value21 & key2 != value22 => key3 = value3 & key4 = value41,vlaue42 & key5 !=value51
- * </code>。
- * The part before <code>=></code> is called When Condition, it's a KV pair; the follower part is Then Condition, also a KV pair. V part in KV can have more than one value, separated by ','<br><br>
- *
- * Value object, thread safe.
- *
- */
-public class RouteRule {
-    @SuppressWarnings("unchecked")
-    static RouteRule EMPTY = new RouteRule(Collections.EMPTY_MAP, Collections.EMPTY_MAP);
-    private static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
-    private static Pattern CONDITION_SEPERATOR = Pattern.compile("(.*)=>(.*)");
-    private static Pattern VALUE_LIST_SEPARATOR = Pattern.compile("\\s*,\\s*");
-    final Map<String, MatchPair> whenCondition;
-    final Map<String, MatchPair> thenCondition;
-    private volatile String tostring = null;
-
-    // FIXME
-    private RouteRule(Map<String, MatchPair> when, Map<String, MatchPair> then) {
-        for (Map.Entry<String, MatchPair> entry : when.entrySet()) {
-            entry.getValue().freeze();
-        }
-        for (Map.Entry<String, MatchPair> entry : then.entrySet()) {
-            entry.getValue().freeze();
-        }
-
-        // NOTE: Both When Condition and Then Condition can be null
-        this.whenCondition = when;
-        this.thenCondition = then;
-    }
-
-    public static Map<String, MatchPair> parseRule(String rule)
-            throws ParseException {
-        Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
-        if (StringUtils.isBlank(rule)) {
-            return condition;
-        }
-        // K-V pair, contains matches part and mismatches part
-        MatchPair pair = null;
-        // V part has multiple values
-        Set<String> values = null;
-        final Matcher matcher = ROUTE_PATTERN.matcher(rule);
-        while (matcher.find()) { // match one by one
-            String separator = matcher.group(1);
-            String content = matcher.group(2);
-            // The expression starts
-            if (separator == null || separator.length() == 0) {
-                pair = new MatchPair();
-                condition.put(content, pair);
-            }
-            // The KV starts
-            else if ("&".equals(separator)) {
-                if (condition.get(content) == null) {
-                    pair = new MatchPair();
-                    condition.put(content, pair);
-                } else {
-                    condition.put(content, pair);
-                }
-
-            }
-            // The Value part of KV starts
-            else if ("=".equals(separator)) {
-                if (pair == null)
-                    throw new ParseException("Illegal route rule \""
-                            + rule + "\", The error char '" + separator
-                            + "' at index " + matcher.start() + " before \""
-                            + content + "\".", matcher.start());
-
-                values = pair.matches;
-                values.add(content);
-            }
-            // The Value part of KV starts
-            else if ("!=".equals(separator)) {
-                if (pair == null)
-                    throw new ParseException("Illegal route rule \""
-                            + rule + "\", The error char '" + separator
-                            + "' at index " + matcher.start() + " before \""
-                            + content + "\".", matcher.start());
-
-                values = pair.unmatches;
-                values.add(content);
-            }
-            // The Value part of KV has multiple values, separated by ','
-            else if (",".equals(separator)) { // separated by ','
-                if (values == null || values.size() == 0)
-                    throw new ParseException("Illegal route rule \""
-                            + rule + "\", The error char '" + separator
-                            + "' at index " + matcher.start() + " before \""
-                            + content + "\".", matcher.start());
-                values.add(content);
-            } else {
-                throw new ParseException("Illegal route rule \"" + rule
-                        + "\", The error char '" + separator + "' at index "
-                        + matcher.start() + " before \"" + content + "\".", matcher.start());
-            }
-        }
-        return condition;
-    }
-
-    /**
-     * Parse the RouteRule as a string into an object.
-     *
-     * @throws ParseException RouteRule string format is wrong. The following input conditions, RouteRule are illegal.
-     * <ul> <li> input is <code>null</code>。
-     * <li> input is "" or " "。
-     * <li> input Rule doesn't have a When Condition
-     * <li> input Rule doesn't have a Then Condition
-     * </ul>
-     */
-    public static RouteRule parse(Route route) throws ParseException {
-        if (route == null)
-            throw new ParseException("null route!", 0);
-
-        if (route.getMatchRule() == null && route.getFilterRule() == null) {
-            return parse(route.getRule());
-        }
-
-        return parse(route == null ? null : route.getMatchRule(), route == null ? null : route.getFilterRule());
-    }
-
-    public static RouteRule parse(String whenRule, String thenRule) throws ParseException {
-        /*if (whenRule == null || whenRule.trim().length() == 0) {
-            throw new ParseException("Illegal route rule without when express", 0);
-    	}*/
-        if (thenRule == null || thenRule.trim().length() == 0) {
-            throw new ParseException("Illegal route rule without then express", 0);
-        }
-        Map<String, MatchPair> when = parseRule(whenRule.trim());
-        Map<String, MatchPair> then = parseRule(thenRule.trim());
-        return new RouteRule(when, then);
-    }
-
-    public static RouteRule parse(String rule) throws ParseException {
-        if (StringUtils.isBlank(rule)) {
-            throw new ParseException("Illegal blank route rule", 0);
-        }
-
-        final Matcher matcher = CONDITION_SEPERATOR.matcher(rule);
-        if (!matcher.matches()) throw new ParseException("condition seperator => not found!", 0);
-
-        return parse(matcher.group(1), matcher.group(2));
-    }
-
-    /**
-     * @see #parse(String)
-     * @throws RuntimeException This is an wrapper exception for the {@link ParseException} thrown by the {@link #parse (String)} method.
-     */
-    public static RouteRule parseQuitely(Route route) {
-        try {
-            return parse(route);
-        } catch (ParseException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static Map<String, MatchPair> parseNameAndValueListString2Condition(Map<String, String> params, Map<String, String> notParams) {
-        Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
-
-        for (Entry<String, String> entry : params.entrySet()) {
-            String valueListString = entry.getValue();
-            if (StringUtils.isBlank(valueListString)) {
-                continue;
-            }
-            String[] list = VALUE_LIST_SEPARATOR.split(valueListString);
-            Set<String> set = new HashSet<String>();
-            for (String item : list) {
-                if (StringUtils.isBlank(item)) {
-                    continue;
-                }
-                set.add(item.trim());
-            }
-            if (set.isEmpty()) {
-                continue;
-            }
-
-            String key = entry.getKey();
-            MatchPair matchPair = condition.get(key);
-            if (null == matchPair) {
-                matchPair = new MatchPair();
-                condition.put(key, matchPair);
-            }
-
-            matchPair.matches = set;
-        }
-        for (Entry<String, String> entry : notParams.entrySet()) {
-            String valueListString = entry.getValue();
-            if (StringUtils.isBlank(valueListString)) {
-                continue;
-            }
-            String[] list = VALUE_LIST_SEPARATOR.split(valueListString);
-            Set<String> set = new HashSet<String>();
-            for (String item : list) {
-                if (StringUtils.isBlank(item)) {
-                    continue;
-                }
-                set.add(item.trim());
-            }
-            if (set.isEmpty()) {
-                continue;
-            }
-
-            String key = entry.getKey();
-            MatchPair matchPair = condition.get(key);
-            if (null == matchPair) {
-                matchPair = new MatchPair();
-                condition.put(key, matchPair);
-            }
-
-            matchPair.unmatches = set;
-        }
-
-        return condition;
-    }
-
-    public static RouteRule createFromNameAndValueListString(Map<String, String> whenParams, Map<String, String> notWhenParams,
-                                                             Map<String, String> thenParams, Map<String, String> notThenParams) {
-        Map<String, MatchPair> when = parseNameAndValueListString2Condition(whenParams, notWhenParams);
-        Map<String, MatchPair> then = parseNameAndValueListString2Condition(thenParams, notThenParams);
-
-        return new RouteRule(when, then);
-    }
-
-    public static RouteRule createFromCondition(Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
-        return new RouteRule(whenCondition, thenCondition);
-    }
-
-    public static RouteRule copyWithRemove(RouteRule copy, Set<String> whenParams, Set<String> thenParams) {
-        Map<String, MatchPair> when = new HashMap<String, MatchPair>();
-        for (Entry<String, MatchPair> entry : copy.getWhenCondition().entrySet()) {
-            if (whenParams == null || !whenParams.contains(entry.getKey())) {
-                when.put(entry.getKey(), entry.getValue());
-            }
-        }
-
-        Map<String, MatchPair> then = new HashMap<String, MatchPair>();
-        for (Entry<String, MatchPair> entry : copy.getThenCondition().entrySet()) {
-            if (thenParams == null || !thenParams.contains(entry.getKey())) {
-                then.put(entry.getKey(), entry.getValue());
-            }
-        }
-
-        return new RouteRule(when, then);
-    }
-
-    /**
-     * Replace with the new condition value.
-     *
-     * @param copy Replace Base
-     * @param whenCondition WhenCondition to replace, if Base does not have an item, insert it directly.
-     * @param thenCondition ThenCondition to replace, if Base has no items, then insert directly.
-     * @return RouteRule after replacement
-     */
-    public static RouteRule copyWithReplace(RouteRule copy, Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
-        if (null == copy) {
-            throw new NullPointerException("Argument copy is null!");
-        }
-
-        Map<String, MatchPair> when = new HashMap<String, MatchPair>();
-        when.putAll(copy.getWhenCondition());
-        if (whenCondition != null) {
-            when.putAll(whenCondition);
-        }
-
-        Map<String, MatchPair> then = new HashMap<String, MatchPair>();
-        then.putAll(copy.getThenCondition());
-        if (thenCondition != null) {
-            then.putAll(thenCondition);
-        }
-
-        return new RouteRule(when, then);
-    }
-
-    // TODO ToString out of the current list is out of order, should we sort?
-    static void join(StringBuilder sb, Set<String> valueSet) {
-        boolean isFirst = true;
-        for (String s : valueSet) {
-            if (isFirst) {
-                isFirst = false;
-            } else {
-                sb.append(",");
-            }
-
-            sb.append(s);
-        }
-    }
-
-    /**
-     * Whether the sample passed the conditions.
-     * <p>
-     * If there is a Key in the KV for the sample, there is a corresponding MatchPair, and Value does not pass through MatchPair; {@code false} is returned; otherwise, {@code true} is returned.
-     *
-     * @see MatchPair#pass(String)
-     */
-    public static boolean matchCondition(Map<String, String> sample,
-                                         Map<String, MatchPair> condition) {
-        for (Map.Entry<String, String> entry : sample.entrySet()) {
-            String key = entry.getKey();
-
-            MatchPair pair = condition.get(key);
-            if (pair != null && !pair.pass(entry.getValue())) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    // FIXME Remove such method calls
-    public static String join(Set<String> valueSet) {
-        StringBuilder sb = new StringBuilder(128);
-        join(sb, valueSet);
-        return sb.toString();
-    }
-
-    // TODO At present, the multiple Key of Condition is in disorder. Should we sort it?
-    public static void contidionToString(StringBuilder sb, Map<String, MatchPair> condition) {
-        boolean isFirst = true;
-        for (Entry<String, MatchPair> entry : condition.entrySet()) {
-            String keyName = entry.getKey();
-            MatchPair p = entry.getValue();
-
-            @SuppressWarnings("unchecked")
-            Set<String>[] setArray = new Set[]{p.matches, p.unmatches};
-            String[] opArray = {" = ", " != "};
-
-            for (int i = 0; i < setArray.length; ++i) {
-                if (setArray[i].isEmpty()) {
-                    continue;
-                }
-                if (isFirst) {
-                    isFirst = false;
-                } else {
-                    sb.append(" & ");
-                }
-
-                sb.append(keyName);
-                sb.append(opArray[i]);
-                join(sb, setArray[i]);
-            }
-        }
-    }
-
-    public boolean isWhenContainValue(String key, String value) {
-        MatchPair matchPair = whenCondition.get(key);
-        if (null == matchPair) {
-            return false;
-        }
-
-        return matchPair.containeValue(value);
-    }
-
-    public boolean isThenContainValue(String key, String value) {
-        MatchPair matchPair = thenCondition.get(key);
-        if (null == matchPair) {
-            return false;
-        }
-
-        return matchPair.containeValue(value);
-    }
-
-    public boolean isContainValue(String key, String value) {
-        return isWhenContainValue(key, value) || isThenContainValue(key, value);
-    }
-
-    public Map<String, MatchPair> getWhenCondition() {
-        return whenCondition;
-    }
-
-    public Map<String, MatchPair> getThenCondition() {
-        return thenCondition;
-    }
-
-    public String getWhenConditionString() {
-        StringBuilder sb = new StringBuilder(512);
-        contidionToString(sb, whenCondition);
-        return sb.toString();
-    }
-
-    public String getThenConditionString() {
-        StringBuilder sb = new StringBuilder(512);
-        contidionToString(sb, thenCondition);
-        return sb.toString();
-    }
-
-    @Override
-    public String toString() {
-        if (tostring != null)
-            return tostring;
-        StringBuilder sb = new StringBuilder(512);
-        contidionToString(sb, whenCondition);
-        sb.append(" => ");
-        contidionToString(sb, thenCondition);
-        return tostring = sb.toString();
-    }
-
-    // Automatic generation with Eclipse
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((thenCondition == null) ? 0 : thenCondition.hashCode());
-        result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
-        return result;
-    }
-
-    // Automatic generation with Eclipse
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        RouteRule other = (RouteRule) obj;
-        if (thenCondition == null) {
-            if (other.thenCondition != null)
-                return false;
-        } else if (!thenCondition.equals(other.thenCondition))
-            return false;
-        if (whenCondition == null) {
-            if (other.whenCondition != null)
-                return false;
-        } else if (!whenCondition.equals(other.whenCondition))
-            return false;
-        return true;
-    }
-
-    public static class MatchPair {
-        Set<String> matches = new HashSet<String>();
-        Set<String> unmatches = new HashSet<String>();
-        private volatile boolean freezed = false;
-
-        public MatchPair() {
-        }
-
-        public MatchPair(Set<String> matches, Set<String> unmatches) {
-            if (matches == null || unmatches == null) {
-                throw new IllegalArgumentException("argument of MatchPair is null!");
-            }
-
-            this.matches = matches;
-            this.unmatches = unmatches;
-        }
-
-        public Set<String> getMatches() {
-            return matches;
-        }
-
-        public Set<String> getUnmatches() {
-            return unmatches;
-        }
-
-        public MatchPair copy() {
-            MatchPair ret = new MatchPair();
-            ret.matches.addAll(matches);
-            ret.unmatches.addAll(unmatches);
-            return ret;
-        }
-
-        void freeze() {
-            if (freezed) return;
-            synchronized (this) {
-                if (freezed) return;
-                matches = Collections.unmodifiableSet(matches);
-                unmatches = Collections.unmodifiableSet(unmatches);
-            }
-        }
-
-        public boolean containeValue(String value) {
-            return matches.contains(value) || unmatches.contains(value);
-        }
-
-        /**
-         * Whether a given value is matched by the {@link MatchPair}.
-         * return {@code false}, if
-         * <ol>
-         * <li>value is in unmatches
-         * <li>matches is not null, but value is not in matches.
-         * </ol>
-         * otherwise, return<code>true</code>。
-         */
-        public boolean pass(String sample) {
-            if (unmatches.contains(sample)) return false;
-            if (matches.isEmpty()) return true;
-            return matches.contains(sample);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("{matches=%s,unmatches=%s}", matches.toString(), unmatches.toString());
-        }
-
-        // Automatic generation with Eclipse
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((matches == null) ? 0 : matches.hashCode());
-            result = prime * result + ((unmatches == null) ? 0 : unmatches.hashCode());
-            return result;
-        }
-
-        // Automatic generation with Eclipse
-        @Override
-        public boolean equals(Object obj) {
-            if (this == obj)
-                return true;
-            if (obj == null)
-                return false;
-            if (getClass() != obj.getClass())
-                return false;
-            MatchPair other = (MatchPair) obj;
-            if (matches == null) {
-                if (other.matches != null)
-                    return false;
-            } else if (!matches.equals(other.matches))
-                return false;
-            if (unmatches == null) {
-                if (other.unmatches != null)
-                    return false;
-            } else if (!unmatches.equals(other.unmatches))
-                return false;
-            return true;
-        }
-    }
-}
+///*
+// * 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.dubbo.admin.common.util;
+//
+//import org.apache.dubbo.admin.model.domain.ConditionRoute;
+//import org.apache.dubbo.common.utils.StringUtils;
+//
+//import java.text.ParseException;
+//import java.util.*;
+//import java.util.Map.Entry;
+//import java.util.regex.Matcher;
+//import java.util.regex.Pattern;
+//
+///**
+// * Router rule can be divided into two parts, When Condition and Then Condition <br>
+// * When/Then Confition is expressed in a style of (KV) pair, the V part of the condition pair can contain multiple values (a list) <br>
+// * The meaning of Rule: If a request matches When Condition, then use Then Condition to filter providers (only providers match Then Condition will be returned). <br>
+// * The process of using Conditions to match consumers and providers is called `Filter`.
+// * When Condition are used to filter ConsumersController, while Then Condition are used to filter ProvidersController.
+// * RouteRule performs like this: If a Consumer matches When Condition, then only return the ProvidersController matches Then Condition. This means RouteRule should be applied to current Consumer and the providers returned are filtered by RouteRule.<br>
+// *
+// * An example of ConditionRoute Rule:<code>
+// * key1 = value11,value12 & key2 = value21 & key2 != value22 => key3 = value3 & key4 = value41,vlaue42 & key5 !=value51
+// * </code>。
+// * The part before <code>=></code> is called When Condition, it's a KV pair; the follower part is Then Condition, also a KV pair. V part in KV can have more than one value, separated by ','<br><br>
+// *
+// * Value object, thread safe.
+// *
+// */
+//public class RouteRule {
+//    @SuppressWarnings("unchecked")
+//    static RouteRule EMPTY = new RouteRule(Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+//    private static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
+//    private static Pattern CONDITION_SEPERATOR = Pattern.compile("(.*)=>(.*)");
+//    private static Pattern VALUE_LIST_SEPARATOR = Pattern.compile("\\s*,\\s*");
+//    final Map<String, MatchPair> whenCondition;
+//    final Map<String, MatchPair> thenCondition;
+//    private volatile String tostring = null;
+//
+//    // FIXME
+//    private RouteRule(Map<String, MatchPair> when, Map<String, MatchPair> then) {
+//        for (Map.Entry<String, MatchPair> entry : when.entrySet()) {
+//            entry.getValue().freeze();
+//        }
+//        for (Map.Entry<String, MatchPair> entry : then.entrySet()) {
+//            entry.getValue().freeze();
+//        }
+//
+//        // NOTE: Both When Condition and Then Condition can be null
+//        this.whenCondition = when;
+//        this.thenCondition = then;
+//    }
+//
+//    public static Map<String, MatchPair> parseRule(String rule)
+//            throws ParseException {
+//        Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
+//        if (StringUtils.isBlank(rule)) {
+//            return condition;
+//        }
+//        // K-V pair, contains matches part and mismatches part
+//        MatchPair pair = null;
+//        // V part has multiple values
+//        Set<String> values = null;
+//        final Matcher matcher = ROUTE_PATTERN.matcher(rule);
+//        while (matcher.find()) { // match one by one
+//            String separator = matcher.group(1);
+//            String content = matcher.group(2);
+//            // The expression starts
+//            if (separator == null || separator.length() == 0) {
+//                pair = new MatchPair();
+//                condition.put(content, pair);
+//            }
+//            // The KV starts
+//            else if ("&".equals(separator)) {
+//                if (condition.get(content) == null) {
+//                    pair = new MatchPair();
+//                    condition.put(content, pair);
+//                } else {
+//                    condition.put(content, pair);
+//                }
+//
+//            }
+//            // The Value part of KV starts
+//            else if ("=".equals(separator)) {
+//                if (pair == null)
+//                    throw new ParseException("Illegal route rule \""
+//                            + rule + "\", The error char '" + separator
+//                            + "' at index " + matcher.start() + " before \""
+//                            + content + "\".", matcher.start());
+//
+//                values = pair.matches;
+//                values.add(content);
+//            }
+//            // The Value part of KV starts
+//            else if ("!=".equals(separator)) {
+//                if (pair == null)
+//                    throw new ParseException("Illegal route rule \""
+//                            + rule + "\", The error char '" + separator
+//                            + "' at index " + matcher.start() + " before \""
+//                            + content + "\".", matcher.start());
+//
+//                values = pair.unmatches;
+//                values.add(content);
+//            }
+//            // The Value part of KV has multiple values, separated by ','
+//            else if (",".equals(separator)) { // separated by ','
+//                if (values == null || values.size() == 0)
+//                    throw new ParseException("Illegal route rule \""
+//                            + rule + "\", The error char '" + separator
+//                            + "' at index " + matcher.start() + " before \""
+//                            + content + "\".", matcher.start());
+//                values.add(content);
+//            } else {
+//                throw new ParseException("Illegal route rule \"" + rule
+//                        + "\", The error char '" + separator + "' at index "
+//                        + matcher.start() + " before \"" + content + "\".", matcher.start());
+//            }
+//        }
+//        return condition;
+//    }
+//
+//    /**
+//     * Parse the RouteRule as a string into an object.
+//     *
+//     * @throws ParseException RouteRule string format is wrong. The following input conditions, RouteRule are illegal.
+//     * <ul> <li> input is <code>null</code>。
+//     * <li> input is "" or " "。
+//     * <li> input Rule doesn't have a When Condition
+//     * <li> input Rule doesn't have a Then Condition
+//     * </ul>
+//     */
+//    public static RouteRule parse(ConditionRoute conditionRoute) throws ParseException {
+//        if (conditionRoute == null)
+//            throw new ParseException("null conditionRoute!", 0);
+//
+//        if (conditionRoute.getMatchRule() == null && conditionRoute.getFilterRule() == null) {
+//            return parse(conditionRoute.getRule());
+//        }
+//
+//        return parse(conditionRoute == null ? null : conditionRoute.getMatchRule(), conditionRoute == null ? null : conditionRoute.getFilterRule());
+//    }
+//
+//    public static RouteRule parse(String whenRule, String thenRule) throws ParseException {
+//        /*if (whenRule == null || whenRule.trim().length() == 0) {
+//            throw new ParseException("Illegal route rule without when express", 0);
+//    	}*/
+//        if (thenRule == null || thenRule.trim().length() == 0) {
+//            throw new ParseException("Illegal route rule without then express", 0);
+//        }
+//        Map<String, MatchPair> when = parseRule(whenRule.trim());
+//        Map<String, MatchPair> then = parseRule(thenRule.trim());
+//        return new RouteRule(when, then);
+//    }
+//
+//    public static RouteRule parse(String rule) throws ParseException {
+//        if (StringUtils.isBlank(rule)) {
+//            throw new ParseException("Illegal blank route rule", 0);
+//        }
+//
+//        final Matcher matcher = CONDITION_SEPERATOR.matcher(rule);
+//        if (!matcher.matches()) throw new ParseException("condition seperator => not found!", 0);
+//
+//        return parse(matcher.group(1), matcher.group(2));
+//    }
+//
+//    /**
+//     * @see #parse(String)
+//     * @throws RuntimeException This is an wrapper exception for the {@link ParseException} thrown by the {@link #parse (String)} method.
+//     */
+//    public static RouteRule parseQuitely(ConditionRoute conditionRoute) {
+//        try {
+//            return parse(conditionRoute);
+//        } catch (ParseException e) {
+//            throw new RuntimeException(e);
+//        }
+//    }
+//
+//    static Map<String, MatchPair> parseNameAndValueListString2Condition(Map<String, String> params, Map<String, String> notParams) {
+//        Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
+//
+//        for (Entry<String, String> entry : params.entrySet()) {
+//            String valueListString = entry.getValue();
+//            if (StringUtils.isBlank(valueListString)) {
+//                continue;
+//            }
+//            String[] list = VALUE_LIST_SEPARATOR.split(valueListString);
+//            Set<String> set = new HashSet<String>();
+//            for (String item : list) {
+//                if (StringUtils.isBlank(item)) {
+//                    continue;
+//                }
+//                set.add(item.trim());
+//            }
+//            if (set.isEmpty()) {
+//                continue;
+//            }
+//
+//            String key = entry.getKey();
+//            MatchPair matchPair = condition.get(key);
+//            if (null == matchPair) {
+//                matchPair = new MatchPair();
+//                condition.put(key, matchPair);
+//            }
+//
+//            matchPair.matches = set;
+//        }
+//        for (Entry<String, String> entry : notParams.entrySet()) {
+//            String valueListString = entry.getValue();
+//            if (StringUtils.isBlank(valueListString)) {
+//                continue;
+//            }
+//            String[] list = VALUE_LIST_SEPARATOR.split(valueListString);
+//            Set<String> set = new HashSet<String>();
+//            for (String item : list) {
+//                if (StringUtils.isBlank(item)) {
+//                    continue;
+//                }
+//                set.add(item.trim());
+//            }
+//            if (set.isEmpty()) {
+//                continue;
+//            }
+//
+//            String key = entry.getKey();
+//            MatchPair matchPair = condition.get(key);
+//            if (null == matchPair) {
+//                matchPair = new MatchPair();
+//                condition.put(key, matchPair);
+//            }
+//
+//            matchPair.unmatches = set;
+//        }
+//
+//        return condition;
+//    }
+//
+//    public static RouteRule createFromNameAndValueListString(Map<String, String> whenParams, Map<String, String> notWhenParams,
+//                                                             Map<String, String> thenParams, Map<String, String> notThenParams) {
+//        Map<String, MatchPair> when = parseNameAndValueListString2Condition(whenParams, notWhenParams);
+//        Map<String, MatchPair> then = parseNameAndValueListString2Condition(thenParams, notThenParams);
+//
+//        return new RouteRule(when, then);
+//    }
+//
+//    public static RouteRule createFromCondition(Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
+//        return new RouteRule(whenCondition, thenCondition);
+//    }
+//
+//    public static RouteRule copyWithRemove(RouteRule copy, Set<String> whenParams, Set<String> thenParams) {
+//        Map<String, MatchPair> when = new HashMap<String, MatchPair>();
+//        for (Entry<String, MatchPair> entry : copy.getWhenCondition().entrySet()) {
+//            if (whenParams == null || !whenParams.contains(entry.getKey())) {
+//                when.put(entry.getKey(), entry.getValue());
+//            }
+//        }
+//
+//        Map<String, MatchPair> then = new HashMap<String, MatchPair>();
+//        for (Entry<String, MatchPair> entry : copy.getThenCondition().entrySet()) {
+//            if (thenParams == null || !thenParams.contains(entry.getKey())) {
+//                then.put(entry.getKey(), entry.getValue());
+//            }
+//        }
+//
+//        return new RouteRule(when, then);
+//    }
+//
+//    /**
+//     * Replace with the new condition value.
+//     *
+//     * @param copy Replace Base
+//     * @param whenCondition WhenCondition to replace, if Base does not have an item, insert it directly.
+//     * @param thenCondition ThenCondition to replace, if Base has no items, then insert directly.
+//     * @return RouteRule after replacement
+//     */
+//    public static RouteRule copyWithReplace(RouteRule copy, Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
+//        if (null == copy) {
+//            throw new NullPointerException("Argument copy is null!");
+//        }
+//
+//        Map<String, MatchPair> when = new HashMap<String, MatchPair>();
+//        when.putAll(copy.getWhenCondition());
+//        if (whenCondition != null) {
+//            when.putAll(whenCondition);
+//        }
+//
+//        Map<String, MatchPair> then = new HashMap<String, MatchPair>();
+//        then.putAll(copy.getThenCondition());
+//        if (thenCondition != null) {
+//            then.putAll(thenCondition);
+//        }
+//
+//        return new RouteRule(when, then);
+//    }
+//
+//    // TODO ToString out of the current list is out of order, should we sort?
+//    static void join(StringBuilder sb, Set<String> valueSet) {
+//        boolean isFirst = true;
+//        for (String s : valueSet) {
+//            if (isFirst) {
+//                isFirst = false;
+//            } else {
+//                sb.append(",");
+//            }
+//
+//            sb.append(s);
+//        }
+//    }
+//
+//    /**
+//     * Whether the sample passed the conditions.
+//     * <p>
+//     * If there is a Key in the KV for the sample, there is a corresponding MatchPair, and Value does not pass through MatchPair; {@code false} is returned; otherwise, {@code true} is returned.
+//     *
+//     * @see MatchPair#pass(String)
+//     */
+//    public static boolean matchCondition(Map<String, String> sample,
+//                                         Map<String, MatchPair> condition) {
+//        for (Map.Entry<String, String> entry : sample.entrySet()) {
+//            String key = entry.getKey();
+//
+//            MatchPair pair = condition.get(key);
+//            if (pair != null && !pair.pass(entry.getValue())) {
+//                return false;
+//            }
+//        }
+//        return true;
+//    }
+//
+//
+//    // FIXME Remove such method calls
+//    public static String join(Set<String> valueSet) {
+//        StringBuilder sb = new StringBuilder(128);
+//        join(sb, valueSet);
+//        return sb.toString();
+//    }
+//
+//    // TODO At present, the multiple Key of Condition is in disorder. Should we sort it?
+//    public static void contidionToString(StringBuilder sb, Map<String, MatchPair> condition) {
+//        boolean isFirst = true;
+//        for (Entry<String, MatchPair> entry : condition.entrySet()) {
+//            String keyName = entry.getKey();
+//            MatchPair p = entry.getValue();
+//
+//            @SuppressWarnings("unchecked")
+//            Set<String>[] setArray = new Set[]{p.matches, p.unmatches};
+//            String[] opArray = {" = ", " != "};
+//
+//            for (int i = 0; i < setArray.length; ++i) {
+//                if (setArray[i].isEmpty()) {
+//                    continue;
+//                }
+//                if (isFirst) {
+//                    isFirst = false;
+//                } else {
+//                    sb.append(" & ");
+//                }
+//
+//                sb.append(keyName);
+//                sb.append(opArray[i]);
+//                join(sb, setArray[i]);
+//            }
+//        }
+//    }
+//
+//    public boolean isWhenContainValue(String key, String value) {
+//        MatchPair matchPair = whenCondition.get(key);
+//        if (null == matchPair) {
+//            return false;
+//        }
+//
+//        return matchPair.containeValue(value);
+//    }
+//
+//    public boolean isThenContainValue(String key, String value) {
+//        MatchPair matchPair = thenCondition.get(key);
+//        if (null == matchPair) {
+//            return false;
+//        }
+//
+//        return matchPair.containeValue(value);
+//    }
+//
+//    public boolean isContainValue(String key, String value) {
+//        return isWhenContainValue(key, value) || isThenContainValue(key, value);
+//    }
+//
+//    public Map<String, MatchPair> getWhenCondition() {
+//        return whenCondition;
+//    }
+//
+//    public Map<String, MatchPair> getThenCondition() {
+//        return thenCondition;
+//    }
+//
+//    public String getWhenConditionString() {
+//        StringBuilder sb = new StringBuilder(512);
+//        contidionToString(sb, whenCondition);
+//        return sb.toString();
+//    }
+//
+//    public String getThenConditionString() {
+//        StringBuilder sb = new StringBuilder(512);
+//        contidionToString(sb, thenCondition);
+//        return sb.toString();
+//    }
+//
+//    @Override
+//    public String toString() {
+//        if (tostring != null)
+//            return tostring;
+//        StringBuilder sb = new StringBuilder(512);
+//        contidionToString(sb, whenCondition);
+//        sb.append(" => ");
+//        contidionToString(sb, thenCondition);
+//        return tostring = sb.toString();
+//    }
+//
+//    // Automatic generation with Eclipse
+//    @Override
+//    public int hashCode() {
+//        final int prime = 31;
+//        int result = 1;
+//        result = prime * result + ((thenCondition == null) ? 0 : thenCondition.hashCode());
+//        result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
+//        return result;
+//    }
+//
+//    // Automatic generation with Eclipse
+//    @Override
+//    public boolean equals(Object obj) {
+//        if (this == obj)
+//            return true;
+//        if (obj == null)
+//            return false;
+//        if (getClass() != obj.getClass())
+//            return false;
+//        RouteRule other = (RouteRule) obj;
+//        if (thenCondition == null) {
+//            if (other.thenCondition != null)
+//                return false;
+//        } else if (!thenCondition.equals(other.thenCondition))
+//            return false;
+//        if (whenCondition == null) {
+//            if (other.whenCondition != null)
+//                return false;
+//        } else if (!whenCondition.equals(other.whenCondition))
+//            return false;
+//        return true;
+//    }
+//
+//    public static class MatchPair {
+//        Set<String> matches = new HashSet<String>();
+//        Set<String> unmatches = new HashSet<String>();
+//        private volatile boolean freezed = false;
+//
+//        public MatchPair() {
+//        }
+//
+//        public MatchPair(Set<String> matches, Set<String> unmatches) {
+//            if (matches == null || unmatches == null) {
+//                throw new IllegalArgumentException("argument of MatchPair is null!");
+//            }
+//
+//            this.matches = matches;
+//            this.unmatches = unmatches;
+//        }
+//
+//        public Set<String> getMatches() {
+//            return matches;
+//        }
+//
+//        public Set<String> getUnmatches() {
+//            return unmatches;
+//        }
+//
+//        public MatchPair copy() {
+//            MatchPair ret = new MatchPair();
+//            ret.matches.addAll(matches);
+//            ret.unmatches.addAll(unmatches);
+//            return ret;
+//        }
+//
+//        void freeze() {
+//            if (freezed) return;
+//            synchronized (this) {
+//                if (freezed) return;
+//                matches = Collections.unmodifiableSet(matches);
+//                unmatches = Collections.unmodifiableSet(unmatches);
+//            }
+//        }
+//
+//        public boolean containeValue(String value) {
+//            return matches.contains(value) || unmatches.contains(value);
+//        }
+//
+//        /**
+//         * Whether a given value is matched by the {@link MatchPair}.
+//         * return {@code false}, if
+//         * <ol>
+//         * <li>value is in unmatches
+//         * <li>matches is not null, but value is not in matches.
+//         * </ol>
+//         * otherwise, return<code>true</code>。
+//         */
+//        public boolean pass(String sample) {
+//            if (unmatches.contains(sample)) return false;
+//            if (matches.isEmpty()) return true;
+//            return matches.contains(sample);
+//        }
+//
+//        @Override
+//        public String toString() {
+//            return String.format("{matches=%s,unmatches=%s}", matches.toString(), unmatches.toString());
+//        }
+//
+//        // Automatic generation with Eclipse
+//        @Override
+//        public int hashCode() {
+//            final int prime = 31;
+//            int result = 1;
+//            result = prime * result + ((matches == null) ? 0 : matches.hashCode());
+//            result = prime * result + ((unmatches == null) ? 0 : unmatches.hashCode());
+//            return result;
+//        }
+//
+//        // Automatic generation with Eclipse
+//        @Override
+//        public boolean equals(Object obj) {
+//            if (this == obj)
+//                return true;
+//            if (obj == null)
+//                return false;
+//            if (getClass() != obj.getClass())
+//                return false;
+//            MatchPair other = (MatchPair) obj;
+//            if (matches == null) {
+//                if (other.matches != null)
+//                    return false;
+//            } else if (!matches.equals(other.matches))
+//                return false;
+//            if (unmatches == null) {
+//                if (other.unmatches != null)
+//                    return false;
+//            } else if (!unmatches.equals(other.unmatches))
+//                return false;
+//            return true;
+//        }
+//    }
+//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
index c87d916..1ff3ec8 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.admin.model.domain.Consumer;
 import org.apache.dubbo.admin.model.domain.Override;
 import org.apache.dubbo.admin.model.domain.Provider;
-import org.apache.dubbo.admin.model.domain.Route;
+import org.apache.dubbo.admin.model.domain.ConditionRoute;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -102,79 +102,6 @@ public class SyncUtils {
         return list;
     }
 
-    public static Route url2Route(Pair<String, URL> pair) {
-        if (pair == null) {
-            return null;
-        }
-
-        String id = pair.getKey();
-        URL url = pair.getValue();
-
-        if (null == url)
-            return null;
-
-        Route r = new Route();
-        r.setHash(id);
-        r.setName(url.getParameter("name"));
-        r.setService(url.getServiceKey());
-        r.setPriority(url.getParameter(Constants.PRIORITY_KEY, 0));
-        r.setEnabled(url.getParameter(Constants.ENABLED_KEY, true));
-        r.setForce(url.getParameter(Constants.FORCE_KEY, false));
-        r.setDynamic(url.getParameter(Constants.DYNAMIC_KEY, false));
-        r.setRuntime(url.getParameter(Constants.RUNTIME_KEY, false));
-        r.setRule(url.getParameterAndDecoded(Constants.RULE_KEY));
-        return r;
-    }
-
-    public static List<Route> url2RouteList(Map<String, URL> cs) {
-        List<Route> list = new ArrayList<Route>();
-        if (cs == null) return list;
-        for (Map.Entry<String, URL> entry : cs.entrySet()) {
-            list.add(url2Route(new Pair<>(entry.getKey(), entry.getValue())));
-        }
-        return list;
-    }
-
-    public static Override url2Override(Pair<String, URL> pair) {
-        if (pair == null) {
-            return null;
-        }
-
-        String id = pair.getKey();
-        URL url = pair.getValue();
-
-        if (null == url)
-            return null;
-
-        Override o = new Override();
-        o.setHash(id);
-
-        Map<String, String> parameters = new HashMap<String, String>(url.getParameters());
-
-        o.setService(url.getServiceKey());
-        parameters.remove(Constants.INTERFACE_KEY);
-        parameters.remove(Constants.GROUP_KEY);
-        parameters.remove(Constants.VERSION_KEY);
-        parameters.remove(Constants.APPLICATION_KEY);
-        parameters.remove(Constants.CATEGORY_KEY);
-        parameters.remove(Constants.DYNAMIC_KEY);
-        parameters.remove(Constants.ENABLED_KEY);
-
-        o.setEnabled(url.getParameter(Constants.ENABLED_KEY, true));
-
-        String host = url.getHost();
-        boolean anyhost = url.getParameter(Constants.ANYHOST_VALUE, false);
-        if (!anyhost || !"0.0.0.0".equals(host)) {
-            o.setAddress(url.getAddress());
-        }
-
-        o.setApplication(url.getParameter(Constants.APPLICATION_KEY, url.getUsername()));
-        parameters.remove(Constants.VERSION_KEY);
-
-        o.setParams(StringUtils.toQueryString(parameters));
-
-        return o;
-    }
 
     // Map<category, Map<servicename, Map<Long, URL>>>
     public static <SM extends Map<String, Map<String, URL>>> Map<String, URL> filterFromCategory(Map<String, SM> urls, Map<String, String> filter) {
@@ -185,16 +112,6 @@ public class SyncUtils {
         return filterFromService(urls.get(c), filter);
     }
 
-    public static List<Override> url2OverrideList(Map<String, URL> cs) {
-        List<Override>
-            list = new ArrayList<Override>();
-        if (cs == null) return list;
-        for (Map.Entry<String, URL> entry : cs.entrySet()) {
-            list.add(url2Override(new Pair<>(entry.getKey(), entry.getValue())));
-        }
-        return list;
-    }
-
 
     // Map<servicename, Map<Long, URL>>
     public static Map<String, URL> filterFromService(Map<String, Map<String, URL>> urls, Map<String, String> filter) {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
index 4417653..b422ab1 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -26,7 +26,7 @@ public class ConfigCenter {
     @Value("${dubbo.registry.address:}")
     private String registryAddress;
 
-    private static String globalConfigPath = "/config/dubbo/dubbo.properties";
+    private static String globalConfigPath = "config/dubbo/dubbo.properties";
 
     @Value("${dubbo.registry.group:}")
     private String group;
@@ -47,7 +47,6 @@ public class ConfigCenter {
             GovernanceConfiguration dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(configCenterUrl.getProtocol());
             dynamicConfiguration.setUrl(configCenterUrl);
             dynamicConfiguration.init();
-            globalConfigPath = group == null ? "/dubbo" + globalConfigPath : "/" + group + globalConfigPath;
             String config = dynamicConfiguration.getConfig(globalConfigPath);
 
             Arrays.stream(config.split("\n")).forEach( s -> {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java
index 6634d1e..276ebbf 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/AccessesController.java
@@ -1,163 +1,165 @@
-/*
- * 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.dubbo.admin.controller;
-
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.dubbo.admin.common.exception.ParamValidationException;
-import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
-import org.apache.dubbo.admin.model.dto.AccessDTO;
-import org.apache.dubbo.admin.service.RouteService;
-import org.apache.dubbo.admin.model.domain.Route;
-import org.apache.dubbo.admin.common.util.RouteRule;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.*;
-
-import java.text.ParseException;
-import java.util.*;
-
-@RestController
-@RequestMapping("/api/{env}/rules/access")
-public class AccessesController {
-    private static final Logger logger = LoggerFactory.getLogger(AccessesController.class);
-
-    private final RouteService routeService;
-
-    @Autowired
-    public AccessesController(RouteService routeService) {
-        this.routeService = routeService;
-    }
-
-    @RequestMapping(method = RequestMethod.GET)
-    public List<AccessDTO> searchAccess(@RequestParam(required = false) String service, @PathVariable String env) throws ParseException {
-        List<AccessDTO> result = new ArrayList<>();
-        List<Route> routes = new ArrayList<>();
-        if (StringUtils.isNotBlank(service)) {
-            Route route = routeService.getBlackwhitelistRouteByService(service.trim());
-            if (route != null) {
-                routes.add(route);
-            }
-        } else {
-            routes = routeService.findAllForceRoute();
-        }
-
-        for (Route route : routes) {
-            // Match WhiteBlackList Route
-            if (route.getName().endsWith(AccessDTO.KEY_BLACK_WHITE_LIST)) {
-                AccessDTO accessDTO = new AccessDTO();
-                accessDTO.setId(route.getHash());
-                accessDTO.setService(route.getService());
-                Map<String, RouteRule.MatchPair> when = RouteRule.parseRule(route.getMatchRule());
-                for (String key : when.keySet()) {
-                    accessDTO.setWhitelist(when.get(key).getUnmatches());
-                    accessDTO.setBlacklist(when.get(key).getMatches());
-                }
-                result.add(accessDTO);
-            }
-        }
-        return result;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
-    public AccessDTO detailAccess(@PathVariable String id, @PathVariable String env) throws ParseException {
-        Route route = routeService.findRoute(id);
-        if (route.getName().endsWith(AccessDTO.KEY_BLACK_WHITE_LIST)) {
-            AccessDTO accessDTO = new AccessDTO();
-            accessDTO.setId(route.getHash());
-            accessDTO.setService(route.getService());
-            Map<String, RouteRule.MatchPair> when = RouteRule.parseRule(route.getMatchRule());
-            for (String key : when.keySet()) {
-                accessDTO.setWhitelist(when.get(key).getUnmatches());
-                accessDTO.setBlacklist(when.get(key).getMatches());
-            }
-            return accessDTO;
-        } else {
-            return null;
-        }
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
-    public void deleteAccess(@PathVariable String id, @PathVariable String env) {
-        routeService.deleteRoute(id);
-    }
-
-    @RequestMapping(method = RequestMethod.POST)
-    @ResponseStatus(HttpStatus.CREATED)
-    public void createAccess(@RequestBody AccessDTO accessDTO, @PathVariable String env) {
-        if (StringUtils.isBlank(accessDTO.getService())) {
-            throw new ParamValidationException("Service is required.");
-        }
-        if (accessDTO.getBlacklist() == null && accessDTO.getWhitelist() == null) {
-            throw new ParamValidationException("One of Blacklist/Whitelist is required.");
-        }
-
-        Route route = routeService.getBlackwhitelistRouteByService(accessDTO.getService());
-
-        if (route != null) {
-            throw new ParamValidationException(accessDTO.getService() + " is existed.");
-        }
-
-        route = new Route();
-        route.setService(accessDTO.getService());
-        route.setForce(true);
-        route.setName(accessDTO.getService() + " " + AccessDTO.KEY_BLACK_WHITE_LIST);
-        route.setFilterRule("false");
-        route.setEnabled(true);
-
-        Map<String, RouteRule.MatchPair> when = new HashMap<>();
-        RouteRule.MatchPair matchPair = new RouteRule.MatchPair(new HashSet<>(), new HashSet<>());
-        when.put(Route.KEY_CONSUMER_HOST, matchPair);
-
-        if (accessDTO.getWhitelist() != null) {
-            matchPair.getUnmatches().addAll(accessDTO.getWhitelist());
-        }
-        if (accessDTO.getBlacklist() != null) {
-            matchPair.getMatches().addAll(accessDTO.getBlacklist());
-        }
-
-        StringBuilder sb = new StringBuilder();
-        RouteRule.contidionToString(sb, when);
-        route.setMatchRule(sb.toString());
-        routeService.createRoute(route);
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
-    public void updateAccess(@PathVariable String id, @RequestBody AccessDTO accessDTO, @PathVariable String env) {
-        Route route = routeService.findRoute(id);
-        if (Objects.isNull(route)) {
-            throw new ResourceNotFoundException("Unknown ID!");
-        }
-        Map<String, RouteRule.MatchPair> when = new HashMap<>();
-        RouteRule.MatchPair matchPair = new RouteRule.MatchPair(new HashSet<>(), new HashSet<>());
-        when.put(Route.KEY_CONSUMER_HOST, matchPair);
-
-        if (accessDTO.getWhitelist() != null) {
-            matchPair.getUnmatches().addAll(accessDTO.getWhitelist());
-        }
-        if (accessDTO.getBlacklist() != null) {
-            matchPair.getMatches().addAll(accessDTO.getBlacklist());
-        }
-
-        StringBuilder sb = new StringBuilder();
-        RouteRule.contidionToString(sb, when);
-        route.setMatchRule(sb.toString());
-
-        routeService.updateRoute(route);
-    }
-}
+///*
+// * 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.dubbo.admin.controller;
+//
+//import org.apache.dubbo.common.logger.Logger;
+//import org.apache.dubbo.common.logger.LoggerFactory;
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.dubbo.admin.common.exception.ParamValidationException;
+//import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+//import org.apache.dubbo.admin.model.dto.AccessDTO;
+//import org.apache.dubbo.admin.service.RouteService;
+//import org.apache.dubbo.admin.model.domain.ConditionRoute;
+//import org.apache.dubbo.admin.common.util.RouteRule;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.http.HttpStatus;
+//import org.springframework.web.bind.annotation.*;
+//
+//import java.text.ParseException;
+//import java.util.*;
+//
+//@RestController
+//@RequestMapping("/api/{env}/rules/access")
+//public class AccessesController {
+//    private static final Logger logger = LoggerFactory.getLogger(AccessesController.class);
+//
+//    private final RouteService routeService;
+//
+//    @Autowired
+//    public AccessesController(RouteService routeService) {
+//        this.routeService = routeService;
+//    }
+//
+//    @RequestMapping(method = RequestMethod.GET)
+//    public List<AccessDTO> searchAccess(@RequestParam(required = false) String service,
+//                                        @RequestParam(required = false) String application,
+//                                        @PathVariable String env) throws ParseException {
+//        List<AccessDTO> result = new ArrayList<>();
+//        List<ConditionRoute> routes = new ArrayList<>();
+//        if (StringUtils.isNotBlank(service)) {
+//            ConditionRoute route = routeService.getBlackwhitelistRouteByService(service.trim());
+//            if (route != null) {
+//                routes.add(route);
+//            }
+//        } else if (StringUtils.isNotBlank(application)) {
+//            ConditionRoute route = routeService.getBlackwhitelistRouteByService()
+//        }
+//
+//        for (ConditionRoute route : routes) {
+//            // Match WhiteBlackList ConditionRoute
+//            if (route.getName().endsWith(AccessDTO.KEY_BLACK_WHITE_LIST)) {
+//                AccessDTO accessDTO = new AccessDTO();
+//                accessDTO.setId(route.getHash());
+//                accessDTO.setService(route.getService());
+//                Map<String, RouteRule.MatchPair> when = RouteRule.parseRule(route.getMatchRule());
+//                for (String key : when.keySet()) {
+//                    accessDTO.setWhitelist(when.get(key).getUnmatches());
+//                    accessDTO.setBlacklist(when.get(key).getMatches());
+//                }
+//                result.add(accessDTO);
+//            }
+//        }
+//        return result;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+//    public AccessDTO detailAccess(@PathVariable String id, @PathVariable String env) throws ParseException {
+//        ConditionRoute route = routeService.findRoute(id);
+//        if (route.getName().endsWith(AccessDTO.KEY_BLACK_WHITE_LIST)) {
+//            AccessDTO accessDTO = new AccessDTO();
+//            accessDTO.setId(route.getHash());
+//            accessDTO.setService(route.getService());
+//            Map<String, RouteRule.MatchPair> when = RouteRule.parseRule(route.getMatchRule());
+//            for (String key : when.keySet()) {
+//                accessDTO.setWhitelist(when.get(key).getUnmatches());
+//                accessDTO.setBlacklist(when.get(key).getMatches());
+//            }
+//            return accessDTO;
+//        } else {
+//            return null;
+//        }
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+//    public void deleteAccess(@PathVariable String id, @PathVariable String env) {
+//        routeService.deleteRoute(id);
+//    }
+//
+//    @RequestMapping(method = RequestMethod.POST)
+//    @ResponseStatus(HttpStatus.CREATED)
+//    public void createAccess(@RequestBody AccessDTO accessDTO, @PathVariable String env) {
+//        if (StringUtils.isBlank(accessDTO.getService())) {
+//            throw new ParamValidationException("Service is required.");
+//        }
+//        if (accessDTO.getBlacklist() == null && accessDTO.getWhitelist() == null) {
+//            throw new ParamValidationException("One of Blacklist/Whitelist is required.");
+//        }
+//
+//        ConditionRoute route = routeService.getBlackwhitelistRouteByService(accessDTO.getService());
+//
+//        if (route != null) {
+//            throw new ParamValidationException(accessDTO.getService() + " is existed.");
+//        }
+//
+//        route = new ConditionRoute();
+//        route.setService(accessDTO.getService());
+//        route.setForce(true);
+//        route.setName(accessDTO.getService() + " " + AccessDTO.KEY_BLACK_WHITE_LIST);
+//        route.setFilterRule("false");
+//        route.setEnabled(true);
+//
+//        Map<String, RouteRule.MatchPair> when = new HashMap<>();
+//        RouteRule.MatchPair matchPair = new RouteRule.MatchPair(new HashSet<>(), new HashSet<>());
+//        when.put(ConditionRoute.KEY_CONSUMER_HOST, matchPair);
+//
+//        if (accessDTO.getWhitelist() != null) {
+//            matchPair.getUnmatches().addAll(accessDTO.getWhitelist());
+//        }
+//        if (accessDTO.getBlacklist() != null) {
+//            matchPair.getMatches().addAll(accessDTO.getBlacklist());
+//        }
+//
+//        StringBuilder sb = new StringBuilder();
+//        RouteRule.contidionToString(sb, when);
+//        route.setMatchRule(sb.toString());
+//        routeService.createRoute(route);
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+//    public void updateAccess(@PathVariable String id, @RequestBody AccessDTO accessDTO, @PathVariable String env) {
+//        ConditionRoute route = routeService.findRoute(id);
+//        if (Objects.isNull(route)) {
+//            throw new ResourceNotFoundException("Unknown ID!");
+//        }
+//        Map<String, RouteRule.MatchPair> when = new HashMap<>();
+//        RouteRule.MatchPair matchPair = new RouteRule.MatchPair(new HashSet<>(), new HashSet<>());
+//        when.put(ConditionRoute.KEY_CONSUMER_HOST, matchPair);
+//
+//        if (accessDTO.getWhitelist() != null) {
+//            matchPair.getUnmatches().addAll(accessDTO.getWhitelist());
+//        }
+//        if (accessDTO.getBlacklist() != null) {
+//            matchPair.getMatches().addAll(accessDTO.getBlacklist());
+//        }
+//
+//        StringBuilder sb = new StringBuilder();
+//        RouteRule.contidionToString(sb, when);
+//        route.setMatchRule(sb.toString());
+//
+//        routeService.updateRoute(route);
+//    }
+//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/RoutesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
similarity index 53%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/RoutesController.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
index d871b75..5743d98 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/RoutesController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
@@ -20,107 +20,94 @@ package org.apache.dubbo.admin.controller;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.dubbo.admin.common.exception.ParamValidationException;
 import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
-import org.apache.dubbo.admin.model.dto.RouteDTO;
+import org.apache.dubbo.admin.model.domain.ConditionRoute;
+import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
 import org.apache.dubbo.admin.service.RouteService;
-import org.apache.dubbo.admin.model.domain.Route;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @RestController
-@RequestMapping("/api/{env}/rules/route")
-public class RoutesController {
+@RequestMapping("/api/{env}/rules/route/condition")
+public class ConditionRoutesController {
 
     private final RouteService routeService;
 
     @Autowired
-    public RoutesController(RouteService routeService) {
+    public ConditionRoutesController(RouteService routeService) {
         this.routeService = routeService;
     }
 
     @RequestMapping(method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public boolean createRule(@RequestBody RouteDTO routeDTO, @PathVariable String env) {
+    public boolean createRule(@RequestBody ConditionRouteDTO routeDTO, @PathVariable String env) {
         String serviceName = routeDTO.getService();
-        String app = routeDTO.getApp();
+        String app = routeDTO.getApplication();
         if (StringUtils.isEmpty(serviceName) && StringUtils.isEmpty(app)) {
             throw new ParamValidationException("serviceName and app is Empty!");
         }
-        if (StringUtils.isNotEmpty(serviceName)) {
-            //2.6
-            routeDTO.setService(serviceName);
-
-            Route route = convertRouteDTOtoRoute(routeDTO, null);
-            routeService.createRoute(route);
-
-        } else {
-            //new feature in 2.7
-        }
+        ConditionRoute conditionRoute = convertRouteDTOtoRoute(routeDTO);
+        routeService.createConditionRoute(conditionRoute);
         return true;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
-    public boolean updateRule(@PathVariable String id, @RequestBody RouteDTO routeDTO, @PathVariable String env) {
-        Route route = routeService.findRoute(id);
-        if (route == null) {
-            throw new ResourceNotFoundException("Unknown ID!");
+    public boolean updateRule(@PathVariable String id, @RequestBody ConditionRouteDTO routeDTO, @PathVariable String env) {
+        if (routeService.findConditionRoute(id) == null) {
+           //throw exception
         }
-        routeDTO.setService(route.getService());
-        Route newRoute = convertRouteDTOtoRoute(routeDTO, id);
-        routeService.updateRoute(newRoute);
+        ConditionRoute newConditionRoute = convertRouteDTOtoRoute(routeDTO);
+        routeService.updateConditionRoute(newConditionRoute);
         return true;
     }
 
     @RequestMapping(method = RequestMethod.GET)
-    public List<RouteDTO> searchRoutes(@RequestParam(required = false) String app,
-                                       @RequestParam(required = false) String service, @PathVariable String env) {
-        List<Route> routes;
-        if (StringUtils.isNotEmpty(app)) {
-            // app scope in 2.7
+    public List<ConditionRouteDTO> searchRoutes(@RequestParam(required = false) String application,
+                                                @RequestParam(required = false) String serviceName, @PathVariable String env) {
+        ConditionRoute conditionRoute = null;
+        List<ConditionRouteDTO> result = new ArrayList<>();
+        if (StringUtils.isNotEmpty(application)) {
+            conditionRoute = routeService.findConditionRoute(application);
         }
-        if (StringUtils.isNotEmpty(service)) {
-            routes = routeService.findByService(service);
-        } else {
-            routes = routeService.findAll();
+        if (StringUtils.isNotEmpty(serviceName)) {
+            conditionRoute = routeService.findConditionRoute(serviceName);
         }
-        List<RouteDTO> routeDTOS = new ArrayList<>();
-        for (Route route : routes) {
-            RouteDTO routeDTO = convertRoutetoRouteDTO(route, route.getHash());
-            routeDTOS.add(routeDTO);
+        ConditionRouteDTO routeDTO = convertRouteToRouteDTO(conditionRoute);
+        if (routeDTO != null) {
+            result.add(routeDTO);
         }
-        return routeDTOS;
+        return result;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
-    public RouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
-        Route route = routeService.findRoute(id);
-        if (route == null) {
+    public ConditionRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
+        ConditionRoute conditionRoute = routeService.findConditionRoute(id);
+        if (conditionRoute == null) {
             throw new ResourceNotFoundException("Unknown ID!");
         }
-        RouteDTO routeDTO = convertRoutetoRouteDTO(route, id);
+        ConditionRouteDTO routeDTO = convertRouteToRouteDTO(conditionRoute);
         return routeDTO;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
-        routeService.deleteRoute(id);
+        routeService.deleteConditionRoute(id);
         return true;
     }
 
     @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
     public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
-
-        routeService.enableRoute(id);
+        routeService.enableConditionRoute(id);
         return true;
     }
 
     @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
     public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
-
-        routeService.disableRoute(id);
+        routeService.disableConditionRoute(id);
         return true;
     }
 
@@ -152,34 +139,40 @@ public class RoutesController {
         return (when.append(" => ").append(then)).toString();
     }
 
-    private Route convertRouteDTOtoRoute(RouteDTO routeDTO, String id) {
-        Route route = new Route();
-        String[] conditions = routeDTO.getConditions();
-        String rule = parseCondition(conditions);
-        route.setService(routeDTO.getService());
-        route.setEnabled(routeDTO.isEnabled());
-        route.setForce(routeDTO.isForce());
-        route.setDynamic(routeDTO.isDynamic());
-        route.setRuntime(routeDTO.isRuntime());
-        route.setPriority(routeDTO.getPriority());
-        route.setRule(rule);
-        if (id != null) {
-            route.setHash(id);
+    private ConditionRoute convertRouteDTOtoRoute(ConditionRouteDTO routeDTO) {
+        if (routeDTO == null) {
+            return null;
         }
-        return route;
+        ConditionRoute conditionRoute = new ConditionRoute();
+        conditionRoute.setConditions(routeDTO.getConditions());
+        conditionRoute.setEnabled(routeDTO.isEnabled());
+        conditionRoute.setForce(routeDTO.isForce());
+        conditionRoute.setRuntime(routeDTO.isRuntime());
+        conditionRoute.setPriority(routeDTO.getPriority());
+        if (StringUtils.isNotEmpty(routeDTO.getApplication())) {
+            conditionRoute.setScope("application");
+            conditionRoute.setKey(routeDTO.getApplication());
+        } else {
+            conditionRoute.setScope("service");
+            conditionRoute.setKey(routeDTO.getService());
+        }
+        return conditionRoute;
     }
 
-    private RouteDTO convertRoutetoRouteDTO(Route route, String id) {
-        RouteDTO routeDTO = new RouteDTO();
-        routeDTO.setDynamic(route.isDynamic());
-        routeDTO.setConditions(new String[]{route.getRule()});
-        routeDTO.setEnabled(route.isEnabled());
-        routeDTO.setForce(route.isForce());
-        routeDTO.setPriority(route.getPriority());
-        routeDTO.setRuntime(route.isRuntime());
-        routeDTO.setService(route.getService());
-        if (id != null) {
-            routeDTO.setId(route.getHash());
+    private ConditionRouteDTO convertRouteToRouteDTO(ConditionRoute conditionRoute) {
+        if (conditionRoute == null) {
+            return null;
+        }
+        ConditionRouteDTO routeDTO = new ConditionRouteDTO();
+        routeDTO.setConditions(conditionRoute.getConditions());
+        routeDTO.setEnabled(conditionRoute.isEnabled());
+        routeDTO.setForce(conditionRoute.isForce());
+        routeDTO.setPriority(conditionRoute.getPriority());
+        routeDTO.setRuntime(conditionRoute.isRuntime());
+        if (conditionRoute.getScope().equals("application")) {
+            routeDTO.setApplication(conditionRoute.getKey());
+        } else {
+            routeDTO.setService(conditionRoute.getKey());
         }
         return routeDTO;
     }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java
index bbfa25c..590e6ef 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/LoadBalanceController.java
@@ -1,134 +1,134 @@
-/*
- * 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.dubbo.admin.controller;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.dubbo.admin.common.exception.ParamValidationException;
-import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
-import org.apache.dubbo.admin.model.dto.BalancingDTO;
-import org.apache.dubbo.admin.service.OverrideService;
-import org.apache.dubbo.admin.model.domain.LoadBalance;
-import org.apache.dubbo.admin.model.domain.Override;
-import org.apache.dubbo.admin.common.util.OverrideUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.apache.dubbo.admin.common.util.OverrideUtils.overrideToLoadBalance;
-
-@RestController
-@RequestMapping("/api/{env}/rules/balancing")
-public class LoadBalanceController {
-
-    private final OverrideService overrideService;
-
-    @Autowired
-    public LoadBalanceController(OverrideService overrideService) {
-        this.overrideService = overrideService;
-    }
-
-    @RequestMapping(method = RequestMethod.POST)
-    @ResponseStatus(HttpStatus.CREATED)
-    public boolean createLoadbalance(@RequestBody BalancingDTO balancingDTO, @PathVariable String env) throws ParamValidationException {
-        String serviceName = balancingDTO.getService();
-        if (StringUtils.isEmpty(serviceName)) {
-            throw new ParamValidationException("serviceName is Empty!");
-        }
-        LoadBalance loadBalance = new LoadBalance();
-        loadBalance.setService(serviceName);
-        loadBalance.setMethod(formatMethodName(balancingDTO.getMethodName()));
-        loadBalance.setStrategy(balancingDTO.getStrategy());
-        overrideService.saveOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
-        return true;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
-    public boolean updateLoadbalance(@PathVariable String id, @RequestBody BalancingDTO balancingDTO, @PathVariable String env) throws ParamValidationException {
-        Override override = overrideService.findById(id);
-        if (override == null) {
-            throw new ResourceNotFoundException("Unknown ID!");
-        }
-        LoadBalance old = overrideToLoadBalance(override);
-        LoadBalance loadBalance = new LoadBalance();
-        loadBalance.setStrategy(balancingDTO.getStrategy());
-        loadBalance.setMethod(formatMethodName(balancingDTO.getMethodName()));
-        loadBalance.setService(old.getService());
-        loadBalance.setHash(id);
-        overrideService.updateOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
-        return true;
-    }
-
-    @RequestMapping(method = RequestMethod.GET)
-    public List<BalancingDTO> searchLoadbalances(@RequestParam(required = false) String service, @PathVariable String env) {
-        List<Override> overrides;
-        if (StringUtils.isEmpty(service)) {
-            overrides = overrideService.findAll();
-        } else {
-            overrides = overrideService.findByService(service);
-        }
-        List<BalancingDTO> loadBalances = new ArrayList<>();
-        if (overrides != null) {
-            for (Override override : overrides) {
-                LoadBalance l = overrideToLoadBalance(override);
-                if (l != null) {
-                    BalancingDTO balancingDTO = new BalancingDTO();
-                    balancingDTO.setService(l.getService());
-                    balancingDTO.setMethodName(l.getMethod());
-                    balancingDTO.setStrategy(l.getStrategy());
-                    balancingDTO.setId(l.getHash());
-                    loadBalances.add(balancingDTO);
-                }
-            }
-        }
-        return loadBalances;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
-    public BalancingDTO detailLoadBalance(@PathVariable String id, @PathVariable String env) throws ParamValidationException {
-        Override override = overrideService.findById(id);
-        if (override == null) {
-            throw new ResourceNotFoundException("Unknown ID!");
-        }
-
-        LoadBalance loadBalance = OverrideUtils.overrideToLoadBalance(override);
-        BalancingDTO balancingDTO = new BalancingDTO();
-        balancingDTO.setService(loadBalance.getService());
-        balancingDTO.setMethodName(loadBalance.getMethod());
-        balancingDTO.setStrategy(loadBalance.getStrategy());
-        return balancingDTO;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
-    public boolean deleteLoadBalance(@PathVariable String id, @PathVariable String env) {
-        if (id == null) {
-            throw new IllegalArgumentException("Argument of id is null!");
-        }
-        overrideService.deleteOverride(id);
-        return true;
-    }
-
-    private String formatMethodName(String method) {
-        if (method.equals("0")) {
-            return "*";
-        }
-        return method;
-    }
-}
+///*
+// * 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.dubbo.admin.controller;
+//
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.dubbo.admin.common.exception.ParamValidationException;
+//import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+//import org.apache.dubbo.admin.model.dto.BalancingDTO;
+//import org.apache.dubbo.admin.service.OverrideService;
+//import org.apache.dubbo.admin.model.domain.LoadBalance;
+//import org.apache.dubbo.admin.model.domain.Override;
+//import org.apache.dubbo.admin.common.util.OverrideUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.http.HttpStatus;
+//import org.springframework.web.bind.annotation.*;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//
+//import static org.apache.dubbo.admin.common.util.OverrideUtils.overrideToLoadBalance;
+//
+//@RestController
+//@RequestMapping("/api/{env}/rules/balancing")
+//public class LoadBalanceController {
+//
+//    private final OverrideService overrideService;
+//
+//    @Autowired
+//    public LoadBalanceController(OverrideService overrideService) {
+//        this.overrideService = overrideService;
+//    }
+//
+//    @RequestMapping(method = RequestMethod.POST)
+//    @ResponseStatus(HttpStatus.CREATED)
+//    public boolean createLoadbalance(@RequestBody BalancingDTO balancingDTO, @PathVariable String env) throws ParamValidationException {
+//        String serviceName = balancingDTO.getService();
+//        if (StringUtils.isEmpty(serviceName)) {
+//            throw new ParamValidationException("serviceName is Empty!");
+//        }
+//        LoadBalance loadBalance = new LoadBalance();
+//        loadBalance.setService(serviceName);
+//        loadBalance.setMethod(formatMethodName(balancingDTO.getMethodName()));
+//        loadBalance.setStrategy(balancingDTO.getStrategy());
+//        overrideService.saveOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
+//        return true;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+//    public boolean updateLoadbalance(@PathVariable String id, @RequestBody BalancingDTO balancingDTO, @PathVariable String env) throws ParamValidationException {
+//        Override override = overrideService.findById(id);
+//        if (override == null) {
+//            throw new ResourceNotFoundException("Unknown ID!");
+//        }
+//        LoadBalance old = overrideToLoadBalance(override);
+//        LoadBalance loadBalance = new LoadBalance();
+//        loadBalance.setStrategy(balancingDTO.getStrategy());
+//        loadBalance.setMethod(formatMethodName(balancingDTO.getMethodName()));
+//        loadBalance.setService(old.getService());
+//        loadBalance.setHash(id);
+//        overrideService.updateOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
+//        return true;
+//    }
+//
+//    @RequestMapping(method = RequestMethod.GET)
+//    public List<BalancingDTO> searchLoadbalances(@RequestParam(required = false) String service, @PathVariable String env) {
+//        List<Override> overrides;
+//        if (StringUtils.isEmpty(service)) {
+//            overrides = overrideService.findAll();
+//        } else {
+//            overrides = overrideService.findByService(service);
+//        }
+//        List<BalancingDTO> loadBalances = new ArrayList<>();
+//        if (overrides != null) {
+//            for (Override override : overrides) {
+//                LoadBalance l = overrideToLoadBalance(override);
+//                if (l != null) {
+//                    BalancingDTO balancingDTO = new BalancingDTO();
+//                    balancingDTO.setService(l.getService());
+//                    balancingDTO.setMethodName(l.getMethod());
+//                    balancingDTO.setStrategy(l.getStrategy());
+//                    balancingDTO.setId(l.getHash());
+//                    loadBalances.add(balancingDTO);
+//                }
+//            }
+//        }
+//        return loadBalances;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+//    public BalancingDTO detailLoadBalance(@PathVariable String id, @PathVariable String env) throws ParamValidationException {
+//        Override override = overrideService.findById(id);
+//        if (override == null) {
+//            throw new ResourceNotFoundException("Unknown ID!");
+//        }
+//
+//        LoadBalance loadBalance = OverrideUtils.overrideToLoadBalance(override);
+//        BalancingDTO balancingDTO = new BalancingDTO();
+//        balancingDTO.setService(loadBalance.getService());
+//        balancingDTO.setMethodName(loadBalance.getMethod());
+//        balancingDTO.setStrategy(loadBalance.getStrategy());
+//        return balancingDTO;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+//    public boolean deleteLoadBalance(@PathVariable String id, @PathVariable String env) {
+//        if (id == null) {
+//            throw new IllegalArgumentException("Argument of id is null!");
+//        }
+//        overrideService.deleteOverride(id);
+//        return true;
+//    }
+//
+//    private String formatMethodName(String method) {
+//        if (method.equals("0")) {
+//            return "*";
+//        }
+//        return method;
+//    }
+//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java
index 52e933a..95a3326 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/OverridesController.java
@@ -17,7 +17,6 @@
 
 package org.apache.dubbo.admin.controller;
 
-import org.apache.dubbo.common.URL;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.dubbo.admin.common.exception.ParamValidationException;
 import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
@@ -28,10 +27,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 @RestController
 @RequestMapping("/api/{env}/rules/override")
@@ -48,53 +44,39 @@ public class OverridesController {
     @ResponseStatus(HttpStatus.CREATED)
     public boolean createOverride(@RequestBody OverrideDTO overrideDTO, @PathVariable String env) {
         String serviceName = overrideDTO.getService();
-        if (StringUtils.isEmpty(serviceName)) {
-            throw new ParamValidationException("serviceName is Empty!");
+        String application = overrideDTO.getApplication();
+        if (StringUtils.isEmpty(serviceName) && StringUtils.isEmpty(application)) {
+            throw new ParamValidationException("serviceName and application are Empty!");
         }
-        Override override = new Override();
-        override.setService(serviceName);
-        override.setApplication(overrideDTO.getApplication());
-        override.setAddress(overrideDTO.getAddress());
-        override.setEnabled(overrideDTO.isEnabled());
-        overrideDTOToParams(override, overrideDTO);
+        Override override = convertOverrideDTOtoOverride(overrideDTO);
         overrideService.saveOverride(override);
         return true;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
     public boolean updateOverride(@PathVariable String id, @RequestBody OverrideDTO overrideDTO, @PathVariable String env) {
-        Override old = overrideService.findById(id);
+        Override old = overrideService.findOverride(id);
         if (old == null) {
             throw new ResourceNotFoundException("Unknown ID!");
         }
-        Override override = new Override();
-        override.setService(overrideDTO.getService());
-        override.setApplication(overrideDTO.getApplication());
-        override.setAddress(overrideDTO.getAddress());
-        override.setEnabled(overrideDTO.isEnabled());
-        overrideDTOToParams(override, overrideDTO);
-        override.setHash(id);
+        Override override = convertOverrideDTOtoOverride(overrideDTO);
         overrideService.updateOverride(override);
         return true;
     }
 
     @RequestMapping(method = RequestMethod.GET)
-    public List<OverrideDTO> searchOverride(@RequestParam(required = false) String service, @PathVariable String env) {
-        List<Override> overrides;
-        if (StringUtils.isEmpty(service)) {
-            overrides = overrideService.findAll();
-        } else {
-            overrides = overrideService.findByService(service);
-        }
+    public List<OverrideDTO> searchOverride(@RequestParam(required = false) String service,
+                                            @RequestParam(required = false) String application,
+                                            @PathVariable String env) {
+        Override override = null;
         List<OverrideDTO> result = new ArrayList<>();
-        for (Override override : overrides) {
-            OverrideDTO overrideDTO = new OverrideDTO();
-            overrideDTO.setAddress(override.getAddress().split(":")[0]);
-            overrideDTO.setApplication(override.getApplication());
-            overrideDTO.setEnabled(override.isEnabled());
-            overrideDTO.setService(override.getService());
-            overrideDTO.setId(override.getHash());
-            paramsToOverrideDTO(override, overrideDTO);
+        if (StringUtils.isNotEmpty(service)) {
+            override = overrideService.findOverride(service);
+        } else if(StringUtils.isNotEmpty(application)){
+            override = overrideService.findOverride(application);
+        }
+        OverrideDTO overrideDTO = convertOverrideToOverrideDTO(override);
+        if (overrideDTO != null) {
             result.add(overrideDTO);
         }
         return result;
@@ -102,16 +84,12 @@ public class OverridesController {
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public OverrideDTO detailOverride(@PathVariable String id, @PathVariable String env) {
-        Override override = overrideService.findById(id);
+        Override override = overrideService.findOverride(id);
         if (override == null) {
             throw new ResourceNotFoundException("Unknown ID!");
         }
-        OverrideDTO overrideDTO = new OverrideDTO();
-        overrideDTO.setAddress(override.getAddress().split(":")[0]);
-        overrideDTO.setApplication(override.getApplication());
-        overrideDTO.setEnabled(override.isEnabled());
-        overrideDTO.setService(override.getService());
-        paramsToOverrideDTO(override, overrideDTO);
+
+        OverrideDTO overrideDTO = convertOverrideToOverrideDTO(override);
         return overrideDTO;
     }
 
@@ -135,75 +113,109 @@ public class OverridesController {
         return true;
     }
 
-    private void overrideDTOToParams(Override override, OverrideDTO overrideDTO) {
-        Map<Object, String>[] mocks = overrideDTO.getMock();
-        Map<String, Object>[] parameters = overrideDTO.getParameters();
-        StringBuilder params = new StringBuilder();
-        if (mocks != null) {
-            for (Map<Object, String> mock : mocks) {
-                for (Map.Entry<Object, String> entry : mock.entrySet()) {
-                    String key;
-                    if (entry.getKey().equals("0")) {
-                        key = "mock";
-                    } else {
-                        key = entry.getKey() + ".mock";
-                    }
-                    String value = key + "=" + URL.encode(entry.getValue());
-                    params.append(value).append("&");
-                }
-            }
-        }
-
-        if (parameters != null) {
-            for (Map<String, Object> param : parameters) {
-                for (Map.Entry<String, Object> entry : param.entrySet()) {
-                    String value = entry.getKey() + "=" + entry.getValue();
-                    params.append(value).append("&");
-                }
-            }
+    private Override convertOverrideDTOtoOverride(OverrideDTO overrideDTO) {
+        if (overrideDTO == null) {
+            return null;
         }
-        if (StringUtils.isNotEmpty(params)) {
-            int length = params.length();
-            if (params.charAt(length - 1) == '&') {
-                params.deleteCharAt(length - 1);
-            }
+        Override override = new Override();
+        if (overrideDTO.getApplication() != null) {
+            override.setScope("application");
+            override.setKey(overrideDTO.getApplication());
+        } else {
+            override.setScope("service");
+            override.setKey(overrideDTO.getService());
         }
-        override.setParams(params.toString());
+        override.setEnabled(overrideDTO.isEnabled());
+        override.setApiVersion("v2.7");
+        override.setConfigs(overrideDTO.getConfigs());
+        return override;
     }
 
-    private void paramsToOverrideDTO(Override override, OverrideDTO overrideDTO) {
-        String params = override.getParams();
-        if (StringUtils.isNotEmpty(params)) {
-            List<Map<Object, String>> mock = new ArrayList<>();
-            List<Map<String, Object>> parameters = new ArrayList<>();
-            String[] pair = params.split("&");
-            for (String p : pair) {
-                String key = p.split("=")[0];
-                if (key.contains("mock")) {
-                    //mock
-                    String value = URL.decode(p.split("=")[1]);
-                    Map<Object, String> item = new HashMap<>();
-                    if (key.contains(".")) {
-                        //single method mock
-                        key = key.split("\\.")[0];
-                        item.put(key, value);
-                    } else {
-                        item.put(0, value);
-                    }
-                    mock.add(item);
-                } else {
-                    //parameter
-                    String value = p.split("=")[1];
-                    Map<String, Object> item = new HashMap<>();
-                    item.put(key, value);
-                    parameters.add(item);
-                }
-            }
-            Map<Object, String>[] mockArray = new Map[mock.size()];
-            overrideDTO.setMock(mock.toArray(mockArray));
-            Map<String, Object>[] paramArray = new Map[parameters.size()];
-            overrideDTO.setParameters(parameters.toArray(paramArray));
+    private OverrideDTO convertOverrideToOverrideDTO(Override override) {
+        if (override == null) {
+            return null;
         }
+        OverrideDTO overrideDTO = new OverrideDTO();
+        overrideDTO.setApiVersion(override.getApiVersion());
+        if (override.getScope().equals("application")) {
+            overrideDTO.setApplication(override.getKey());
+        } else {
+            overrideDTO.setService(override.getKey());
+        }
+        overrideDTO.setEnabled(override.isEnabled());
+        overrideDTO.setConfigs(override.getConfigs());
+        return overrideDTO;
     }
 
+//    private void overrideDTOToParams(Override override, OverrideDTO overrideDTO) {
+//        Map<Object, String>[] mocks = overrideDTO.getMock();
+//        Map<String, Object>[] parameters = overrideDTO.getParameters();
+//        StringBuilder params = new StringBuilder();
+//        if (mocks != null) {
+//            for (Map<Object, String> mock : mocks) {
+//                for (Map.Entry<Object, String> entry : mock.entrySet()) {
+//                    String key;
+//                    if (entry.getKey().equals("0")) {
+//                        key = "mock";
+//                    } else {
+//                        key = entry.getKey() + ".mock";
+//                    }
+//                    String value = key + "=" + URL.encode(entry.getValue());
+//                    params.append(value).append("&");
+//                }
+//            }
+//        }
+//
+//        if (parameters != null) {
+//            for (Map<String, Object> param : parameters) {
+//                for (Map.Entry<String, Object> entry : param.entrySet()) {
+//                    String value = entry.getKey() + "=" + entry.getValue();
+//                    params.append(value).append("&");
+//                }
+//            }
+//        }
+//        if (StringUtils.isNotEmpty(params)) {
+//            int length = params.length();
+//            if (params.charAt(length - 1) == '&') {
+//                params.deleteCharAt(length - 1);
+//            }
+//        }
+//        override.setParams(params.toString());
+//    }
+//
+//    private void paramsToOverrideDTO(Override override, OverrideDTO overrideDTO) {
+//        String params = override.getParams();
+//        if (StringUtils.isNotEmpty(params)) {
+//            List<Map<Object, String>> mock = new ArrayList<>();
+//            List<Map<String, Object>> parameters = new ArrayList<>();
+//            String[] pair = params.split("&");
+//            for (String p : pair) {
+//                String key = p.split("=")[0];
+//                if (key.contains("mock")) {
+//                    //mock
+//                    String value = URL.decode(p.split("=")[1]);
+//                    Map<Object, String> item = new HashMap<>();
+//                    if (key.contains(".")) {
+//                        //single method mock
+//                        key = key.split("\\.")[0];
+//                        item.put(key, value);
+//                    } else {
+//                        item.put(0, value);
+//                    }
+//                    mock.add(item);
+//                } else {
+//                    //parameter
+//                    String value = p.split("=")[1];
+//                    Map<String, Object> item = new HashMap<>();
+//                    item.put(key, value);
+//                    parameters.add(item);
+//                }
+//            }
+//            Map<Object, String>[] mockArray = new Map[mock.size()];
+//            overrideDTO.setMock(mock.toArray(mockArray));
+//            Map<String, Object>[] paramArray = new Map[parameters.size()];
+//            overrideDTO.setParameters(parameters.toArray(paramArray));
+//        }
+//    }
+
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java
new file mode 100644
index 0000000..8c3d273
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java
@@ -0,0 +1,114 @@
+package org.apache.dubbo.admin.controller;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.admin.common.exception.ParamValidationException;
+import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+import org.apache.dubbo.admin.model.domain.TagRoute;
+import org.apache.dubbo.admin.model.dto.RouteDTO;
+import org.apache.dubbo.admin.model.dto.TagRouteDTO;
+import org.apache.dubbo.admin.service.RouteService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+@RestController
+@RequestMapping("/api/{env}/rules/route/tag")
+public class TagRoutesController {
+
+
+    private final RouteService routeService;
+
+    @Autowired
+    public TagRoutesController(RouteService routeService) {
+        this.routeService = routeService;
+    }
+
+    @RequestMapping(method = RequestMethod.POST)
+    @ResponseStatus(HttpStatus.CREATED)
+    public boolean createRule(@RequestBody TagRouteDTO routeDTO, @PathVariable String env) {
+        String app = routeDTO.getApplication();
+        if (StringUtils.isEmpty(app)) {
+            throw new ParamValidationException("app is Empty!");
+        }
+        TagRoute tagRoute = convertTagRouteDTOToTagRoute(routeDTO);
+        routeService.createTagRoute(tagRoute);
+        return true;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+    public boolean updateRule(@PathVariable String id, @RequestBody TagRouteDTO routeDTO, @PathVariable String dev) {
+        if (routeService.findConditionRoute(id) == null) {
+            //throw exception
+        }
+        TagRoute tagRoute = convertTagRouteDTOToTagRoute(routeDTO);
+        routeService.updateTagRoute(tagRoute);
+        return true;
+
+    }
+
+    @RequestMapping(method = RequestMethod.GET)
+    public TagRouteDTO searchRoutes(@RequestParam String application, @PathVariable String env) {
+        TagRoute tagRoute = null;
+        if (StringUtils.isNotEmpty(application)) {
+            tagRoute = routeService.findTagRoute(application);
+        }
+        if (tagRoute != null) {
+            TagRouteDTO routeDTO = convertTagRouteToTagRouteDTO(tagRoute);
+            return routeDTO;
+        }
+        return null;
+
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+    public TagRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
+        TagRoute tagRoute = routeService.findTagRoute(id);
+        if (tagRoute == null) {
+            throw new ResourceNotFoundException("Unknown ID!");
+        }
+        TagRouteDTO tagRouteDTO = convertTagRouteToTagRouteDTO(tagRoute);
+        return tagRouteDTO;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+    public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
+        routeService.deleteTagRoute(id);
+        return true;
+    }
+
+    @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
+    public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
+        routeService.enableTagRoute(id);
+        return true;
+    }
+
+    @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
+    public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
+        routeService.disableTagRoute(id);
+        return true;
+    }
+
+    private TagRouteDTO convertTagRouteToTagRouteDTO(TagRoute tagRoute) {
+        TagRouteDTO tagRouteDTO = new TagRouteDTO();
+        tagRouteDTO.setTags(tagRoute.getTags());
+        tagRouteDTO.setApplication(tagRoute.getKey());
+        tagRouteDTO.setEnabled(tagRoute.isEnabled());
+        tagRouteDTO.setForce(tagRoute.isForce());
+        tagRouteDTO.setPriority(tagRoute.getPriority());
+        tagRouteDTO.setRuntime(tagRoute.isRuntime());
+        return tagRouteDTO;
+    }
+
+    private TagRoute convertTagRouteDTOToTagRoute(TagRouteDTO tagRouteDTO) {
+        TagRoute tagRoute = new TagRoute();
+        tagRoute.setEnabled(tagRouteDTO.isEnabled());
+        tagRoute.setForce(tagRouteDTO.isForce());
+        tagRoute.setKey(tagRouteDTO.getApplication());
+        tagRoute.setPriority(tagRouteDTO.getPriority());
+        tagRoute.setRuntime(tagRouteDTO.isRuntime());
+        tagRoute.setTags(tagRouteDTO.getTags());
+        return tagRoute;
+    }
+
+}
+
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/WeightController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/WeightController.java
index 92d6009..cf91622 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/WeightController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/WeightController.java
@@ -1,122 +1,122 @@
-/*
- * 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.dubbo.admin.controller;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.dubbo.admin.common.exception.ParamValidationException;
-import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
-import org.apache.dubbo.admin.model.dto.WeightDTO;
-import org.apache.dubbo.admin.service.OverrideService;
-import org.apache.dubbo.admin.model.domain.Override;
-import org.apache.dubbo.admin.model.domain.Weight;
-import org.apache.dubbo.admin.common.util.OverrideUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RestController
-@RequestMapping("/api/{env}/rules/weight")
-public class WeightController {
-
-    private final OverrideService overrideService;
-
-    @Autowired
-    public WeightController(OverrideService overrideService) {
-        this.overrideService = overrideService;
-    }
-
-    @RequestMapping(method = RequestMethod.POST)
-    @ResponseStatus(HttpStatus.CREATED)
-    public boolean createWeight(@RequestBody WeightDTO weightDTO, @PathVariable String env) {
-        String[] addresses = weightDTO.getProvider();
-        for (String address : addresses) {
-            Weight weight = new Weight();
-            weight.setService(weightDTO.getService());
-            weight.setWeight(weight.getWeight());
-            weight.setAddress(address);
-            overrideService.saveOverride(OverrideUtils.weightToOverride(weight));
-        }
-        return true;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
-    public boolean updateWeight(@PathVariable String id, @RequestBody WeightDTO weightDTO, @PathVariable String env) {
-        if (id == null) {
-            throw new ParamValidationException("Unknown ID!");
-        }
-        Override override = overrideService.findById(id);
-        if (override == null) {
-            throw new ResourceNotFoundException("Unknown ID!");
-        }
-        Weight old = OverrideUtils.overrideToWeight(override);
-        Weight weight = new Weight();
-        weight.setWeight(weightDTO.getWeight());
-        weight.setHash(id);
-        weight.setService(old.getService());
-        overrideService.updateOverride(OverrideUtils.weightToOverride(weight));
-        return true;
-    }
-
-    @RequestMapping(method = RequestMethod.GET)
-    public List<WeightDTO> searchWeight(@RequestParam(required = false) String service, @PathVariable String env) {
-        List<Override> overrides;
-        if (StringUtils.isEmpty(service)) {
-            overrides = overrideService.findAll();
-        } else {
-            overrides = overrideService.findByService(service);
-        }
-        List<WeightDTO> weightDTOS = new ArrayList<>();
-        for (Override override : overrides) {
-            Weight w = OverrideUtils.overrideToWeight(override);
-            if (w != null) {
-                WeightDTO weightDTO = new WeightDTO();
-                weightDTO.setProvider(new String[]{w.getAddress()});
-                weightDTO.setService(w.getService());
-                weightDTO.setWeight(w.getWeight());
-                weightDTO.setId(w.getHash());
-                weightDTOS.add(weightDTO);
-            }
-        }
-        return weightDTOS;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
-    public WeightDTO detailWeight(@PathVariable String id, @PathVariable String env) {
-        Override override = overrideService.findById(id);
-        if (override != null) {
-
-            Weight w = OverrideUtils.overrideToWeight(override);
-            WeightDTO weightDTO = new WeightDTO();
-            weightDTO.setProvider(new String[]{w.getAddress()});
-            weightDTO.setService(w.getService());
-            weightDTO.setWeight(w.getWeight());
-            weightDTO.setId(w.getHash());
-            return weightDTO;
-        }
-        return null;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
-    public boolean deleteWeight(@PathVariable String id, @PathVariable String env) {
-        overrideService.deleteOverride(id);
-        return true;
-    }
-}
+///*
+// * 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.dubbo.admin.controller;
+//
+//import org.apache.commons.lang3.StringUtils;
+//import org.apache.dubbo.admin.common.exception.ParamValidationException;
+//import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
+//import org.apache.dubbo.admin.model.dto.WeightDTO;
+//import org.apache.dubbo.admin.service.OverrideService;
+//import org.apache.dubbo.admin.model.domain.Override;
+//import org.apache.dubbo.admin.model.domain.Weight;
+//import org.apache.dubbo.admin.common.util.OverrideUtils;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.http.HttpStatus;
+//import org.springframework.web.bind.annotation.*;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//
+//@RestController
+//@RequestMapping("/api/{env}/rules/weight")
+//public class WeightController {
+//
+//    private final OverrideService overrideService;
+//
+//    @Autowired
+//    public WeightController(OverrideService overrideService) {
+//        this.overrideService = overrideService;
+//    }
+//
+//    @RequestMapping(method = RequestMethod.POST)
+//    @ResponseStatus(HttpStatus.CREATED)
+//    public boolean createWeight(@RequestBody WeightDTO weightDTO, @PathVariable String env) {
+//        String[] addresses = weightDTO.getProvider();
+//        for (String address : addresses) {
+//            Weight weight = new Weight();
+//            weight.setService(weightDTO.getService());
+//            weight.setWeight(weight.getWeight());
+//            weight.setAddress(address);
+//            overrideService.saveOverride(OverrideUtils.weightToOverride(weight));
+//        }
+//        return true;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+//    public boolean updateWeight(@PathVariable String id, @RequestBody WeightDTO weightDTO, @PathVariable String env) {
+//        if (id == null) {
+//            throw new ParamValidationException("Unknown ID!");
+//        }
+//        Override override = overrideService.findById(id);
+//        if (override == null) {
+//            throw new ResourceNotFoundException("Unknown ID!");
+//        }
+//        Weight old = OverrideUtils.overrideToWeight(override);
+//        Weight weight = new Weight();
+//        weight.setWeight(weightDTO.getWeight());
+//        weight.setHash(id);
+//        weight.setService(old.getService());
+//        overrideService.updateOverride(OverrideUtils.weightToOverride(weight));
+//        return true;
+//    }
+//
+//    @RequestMapping(method = RequestMethod.GET)
+//    public List<WeightDTO> searchWeight(@RequestParam(required = false) String service, @PathVariable String env) {
+//        List<Override> overrides;
+//        if (StringUtils.isEmpty(service)) {
+//            overrides = overrideService.findAll();
+//        } else {
+//            overrides = overrideService.findByService(service);
+//        }
+//        List<WeightDTO> weightDTOS = new ArrayList<>();
+//        for (Override override : overrides) {
+//            Weight w = OverrideUtils.overrideToWeight(override);
+//            if (w != null) {
+//                WeightDTO weightDTO = new WeightDTO();
+//                weightDTO.setProvider(new String[]{w.getAddress()});
+//                weightDTO.setService(w.getService());
+//                weightDTO.setWeight(w.getWeight());
+//                weightDTO.setId(w.getHash());
+//                weightDTOS.add(weightDTO);
+//            }
+//        }
+//        return weightDTOS;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+//    public WeightDTO detailWeight(@PathVariable String id, @PathVariable String env) {
+//        Override override = overrideService.findById(id);
+//        if (override != null) {
+//
+//            Weight w = OverrideUtils.overrideToWeight(override);
+//            WeightDTO weightDTO = new WeightDTO();
+//            weightDTO.setProvider(new String[]{w.getAddress()});
+//            weightDTO.setService(w.getService());
+//            weightDTO.setWeight(w.getWeight());
+//            weightDTO.setId(w.getHash());
+//            return weightDTO;
+//        }
+//        return null;
+//    }
+//
+//    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+//    public boolean deleteWeight(@PathVariable String id, @PathVariable String env) {
+//        overrideService.deleteOverride(id);
+//        return true;
+//    }
+//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
index ef5ad30..7ab06f8 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
@@ -15,4 +15,6 @@ public interface GovernanceConfiguration {
 
     String getConfig(String key);
 
+    boolean deleteConfig(String key);
+
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java
index 0e4d1a3..ab2a50d 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java
@@ -37,4 +37,9 @@ public class ApolloConfiguration implements GovernanceConfiguration {
     public String getConfig(String key) {
         return null;
     }
+
+    @Override
+    public boolean deleteConfig(String key) {
+        return false;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java
index 5fca72b..5916ee1 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java
@@ -3,12 +3,14 @@ package org.apache.dubbo.admin.data.config.impl;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
 import org.apache.dubbo.common.URL;
 
 public class ZookeeperConfiguration implements GovernanceConfiguration {
     private CuratorFramework zkClient;
     private URL url;
+    private String root;
 
     @Override
     public void setUrl(URL url) {
@@ -23,16 +25,22 @@ public class ZookeeperConfiguration implements GovernanceConfiguration {
     @Override
     public void init() {
         zkClient = CuratorFrameworkFactory.newClient(url.getAddress(), new ExponentialBackoffRetry(1000, 3));
+        String group = url.getParameter(Constants.GROUP_KEY, Constants.DEFAULT_ROOT);
+        if (!group.startsWith(Constants.PATH_SEPARATOR)) {
+            group = Constants.PATH_SEPARATOR + group;
+        }
+        root = group;
         zkClient.start();
     }
 
     @Override
     public String setConfig(String key, String value) {
+        String path = getNodePath(key);
         try {
-            if (zkClient.checkExists().forPath(key) == null) {
-                zkClient.create().creatingParentsIfNeeded().forPath(key);
+            if (zkClient.checkExists().forPath(path) == null) {
+                zkClient.create().creatingParentsIfNeeded().forPath(path);
             }
-            zkClient.setData().forPath(key, value.getBytes());
+            zkClient.setData().forPath(path, value.getBytes());
             return value;
         } catch (Exception e) {
 
@@ -42,15 +50,37 @@ public class ZookeeperConfiguration implements GovernanceConfiguration {
 
     @Override
     public String getConfig(String key) {
+        String path = getNodePath(key);
 
         try {
-            if (zkClient.checkExists().forPath(key) == null) {
+            if (zkClient.checkExists().forPath(path) == null) {
                 return null;
             }
-            return new String(zkClient.getData().forPath(key));
+            return new String(zkClient.getData().forPath(path));
         } catch (Exception e) {
             e.printStackTrace();
         }
         return null;
     }
+
+    @Override
+    public boolean deleteConfig(String key) {
+        try {
+            zkClient.delete().forPath(key);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+
+    private String getNodePath(String path) {
+        return toRootDir() + path;
+    }
+
+    private String toRootDir() {
+        if (root.equals(Constants.PATH_SEPARATOR)) {
+            return root;
+        }
+        return root + Constants.PATH_SEPARATOR;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
index da980c7..0f9d084 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
@@ -3,13 +3,12 @@ package org.apache.dubbo.admin.data.metadata.impl;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
 import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
-import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
 
 public class ZookeeperMetaDataCollector implements MetaDataCollector {
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/ConditionRoute.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/ConditionRoute.java
new file mode 100644
index 0000000..aad6f91
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/ConditionRoute.java
@@ -0,0 +1,22 @@
+package org.apache.dubbo.admin.model.domain;
+
+public class ConditionRoute extends Route{
+    private String scope;
+    private String[] conditions;
+
+    public String getScope() {
+        return scope;
+    }
+
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+
+    public String[] getConditions() {
+        return conditions;
+    }
+
+    public void setConditions(String[] conditions) {
+        this.conditions = conditions;
+    }
+}
\ No newline at end of file
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java
index ee0a326..ef3b0b9 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java
@@ -54,7 +54,7 @@ public class Consumer extends Entity {
 
     private List<Override> overrides;
 
-    private List<Route> routes;
+    private List<ConditionRoute> conditionRoutes;
 
     private List<Provider> providers;
 
@@ -176,12 +176,12 @@ public class Consumer extends Entity {
         this.overrides = overrides;
     }
 
-    public List<Route> getRoutes() {
-        return routes;
+    public List<ConditionRoute> getConditionRoutes() {
+        return conditionRoutes;
     }
 
-    public void setRoutes(List<Route> routes) {
-        this.routes = routes;
+    public void setConditionRoutes(List<ConditionRoute> conditionRoutes) {
+        this.conditionRoutes = conditionRoutes;
     }
 
     public List<Provider> getProviders() {
@@ -196,7 +196,7 @@ public class Consumer extends Entity {
         return "Consumer [service=" + service + ", parameters=" + parameters + ", result=" + result
                 + ", address=" + address + ", registry=" + registry + ", application="
                 + application + ", username=" + username + ", statistics=" + statistics
-                + ", collected=" + collected + ", routes=" + routes + ", overrides=" + overrides
+                + ", collected=" + collected + ", conditionRoutes=" + conditionRoutes + ", overrides=" + overrides
                 + ", expired=" + expired + ", alived=" + alived + "]";
     }
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java
index e03a874..4a9e2ca 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java
@@ -28,7 +28,7 @@ public class Operation extends Entity {
 
     public static final String PROVIDER_TYPE = "Provider";
     public static final String CONSUMER_TYPE = "Consumer";
-    public static final String ROUTE_TYPE = "Route";
+    public static final String ROUTE_TYPE = "ConditionRoute";
     public static final String WEIGHT_TYPE = "Weight";
     public static final String CLUSTER_TYPE = "Cluster";
     public static final String DOCUMENT_TYPE = "Document";
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java
index ff79fad..9a2a4b7 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java
@@ -22,181 +22,51 @@ import org.apache.dubbo.common.utils.StringUtils;
 
 import java.util.Map;
 
-public class Override extends Entity {
-
-    private static final long serialVersionUID = 114828505391757846L;
-
-    private String service;
-
-    private String params;
-
-    private String application;
-
-    private String address;
-
-    private String username;
+public class Override {
 
+    private String apiVersion;
+    private String scope;
+    private String key;
     private boolean enabled;
+    private OverrideConfig[] configs;
 
-    public Override() {
-    }
-
-    public Override(long id) {
-        super(id);
-    }
-
-    public String getService() {
-        return service;
-    }
-
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-
-    public String getParams() {
-        return params;
-    }
-
-
-    public void setParams(String params) {
-        this.params = params;
-    }
-
-
-    public String getApplication() {
-        return application;
+    public String getApiVersion() {
+        return apiVersion;
     }
 
-
-    public void setApplication(String application) {
-        this.application = application;
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
     }
 
-
-    public String getAddress() {
-        return address;
+    public String getScope() {
+        return scope;
     }
 
-
-    public void setAddress(String address) {
-        this.address = address;
+    public void setScope(String scope) {
+        this.scope = scope;
     }
 
-    public String getUsername() {
-        return username;
+    public String getKey() {
+        return key;
     }
 
-    public void setUsername(String username) {
-        this.username = username;
+    public void setKey(String key) {
+        this.key = key;
     }
 
-
     public boolean isEnabled() {
         return enabled;
     }
 
-
     public void setEnabled(boolean enabled) {
         this.enabled = enabled;
     }
 
-    public String toString() {
-        return "Override [service=" + service + ", params=" + params + ", application="
-                + application + ", address=" + address + ", username=" + username + ", enabled=" + enabled + "]";
+    public OverrideConfig[] getConfigs() {
+        return configs;
     }
 
-    public boolean isDefault() {
-        return (getAddress() == null || getAddress().length() == 0 || Constants.ANY_VALUE.equals(getAddress()) || Constants.ANYHOST_VALUE.equals(getAddress()))
-                && (getApplication() == null || getApplication().length() == 0 || Constants.ANY_VALUE.equals(getApplication()));
+    public void setConfigs(OverrideConfig[] configs) {
+        this.configs = configs;
     }
-
-    public boolean isMatch(String service, String address, String application) {
-        return isEnabled() && getParams() != null && getParams().length() > 0
-                && service.equals(getService())
-                && (address == null || getAddress() == null || getAddress().length() == 0 || getAddress().equals(Constants.ANY_VALUE) || getAddress().equals(Constants.ANYHOST_VALUE) || getAddress().equals(address))
-                && (application == null || getApplication() == null || getApplication().length() == 0 || getApplication().equals(Constants.ANY_VALUE) || getApplication().equals(application));
-    }
-
-    public boolean isUniqueMatch(Provider provider) {
-        return isEnabled() && getParams() != null && getParams().length() > 0
-                && provider.getService().equals(getService())
-                && provider.getAddress().equals(getAddress());
-    }
-
-    public boolean isMatch(Provider provider) {
-        return isEnabled() && getParams() != null && getParams().length() > 0
-                && provider.getService().equals(getService())
-                && (getAddress() == null || getAddress().length() == 0 || getAddress().equals(Constants.ANY_VALUE) || getAddress().equals(Constants.ANYHOST_VALUE) || getAddress().equals(provider.getAddress()))
-                && (getApplication() == null || getApplication().length() == 0 || getApplication().equals(Constants.ANY_VALUE) || getApplication().equals(provider.getApplication()));
-    }
-
-    public boolean isUniqueMatch(Consumer consumer) {
-        return isEnabled() && getParams() != null && getParams().length() > 0
-                && consumer.getService().equals(getService())
-                && consumer.getAddress().equals(getAddress());
-    }
-
-    public boolean isMatch(Consumer consumer) {
-        return isEnabled() && getParams() != null && getParams().length() > 0
-                && consumer.getService().equals(getService())
-                && (getAddress() == null || getAddress().length() == 0 || getAddress().equals(Constants.ANY_VALUE) || getAddress().equals(Constants.ANYHOST_VALUE) || getAddress().equals(consumer.getAddress()))
-                && (getApplication() == null || getApplication().length() == 0 || getApplication().equals(Constants.ANY_VALUE) || getApplication().equals(consumer.getApplication()));
-    }
-
-    public Map<String, String> toParametersMap() {
-        Map<String, String> map = StringUtils.parseQueryString(getParams());
-        map.remove(Constants.INTERFACE_KEY);
-        map.remove(Constants.GROUP_KEY);
-        map.remove(Constants.VERSION_KEY);
-        map.remove(Constants.APPLICATION_KEY);
-        map.remove(Constants.CATEGORY_KEY);
-        map.remove(Constants.DYNAMIC_KEY);
-        map.remove(Constants.ENABLED_KEY);
-        return map;
-    }
-
-    public URL toUrl() {
-        String group = null;
-        String version = null;
-        String path = service;
-        int i = path.indexOf("/");
-        if (i > 0) {
-            group = path.substring(0, i);
-            path = path.substring(i + 1);
-        }
-        i = path.lastIndexOf(":");
-        if (i > 0) {
-            version = path.substring(i + 1);
-            path = path.substring(0, i);
-        }
-        StringBuilder sb = new StringBuilder();
-        sb.append(Constants.OVERRIDE_PROTOCOL);
-        sb.append("://");
-        if (!StringUtils.isBlank(address) && !Constants.ANY_VALUE.equals(address)) {
-            sb.append(address);
-        } else {
-            sb.append(Constants.ANYHOST_VALUE);
-        }
-        sb.append("/");
-        sb.append(path);
-        sb.append("?");
-        Map<String, String> param = StringUtils.parseQueryString(params);
-        param.put(Constants.CATEGORY_KEY, Constants.CONFIGURATORS_CATEGORY);
-        param.put(Constants.ENABLED_KEY, String.valueOf(isEnabled()));
-        param.put(Constants.DYNAMIC_KEY, "false");
-        if (!StringUtils.isBlank(application) && !Constants.ANY_VALUE.equals(application)) {
-            param.put(Constants.APPLICATION_KEY, application);
-        }
-        if (group != null) {
-            param.put(Constants.GROUP_KEY, group);
-        }
-        if (version != null) {
-            param.put(Constants.VERSION_KEY, version);
-        }
-        sb.append(StringUtils.toQueryString(param));
-        return URL.valueOf(sb.toString());
-    }
-
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/OverrideConfig.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/OverrideConfig.java
new file mode 100644
index 0000000..7998daa
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/OverrideConfig.java
@@ -0,0 +1,60 @@
+package org.apache.dubbo.admin.model.domain;
+
+import java.util.Map;
+
+public class OverrideConfig {
+    private String side;
+    private String[] addresses;
+    private String[] providerAddresses;
+    private Map<String, Object> parameters;
+    private String[] applications;
+    private String[] services;
+
+    public String getSide() {
+        return side;
+    }
+
+    public void setSide(String side) {
+        this.side = side;
+    }
+
+    public String[] getAddress() {
+        return addresses;
+    }
+
+    public void setAddress(String[] address) {
+        this.addresses = address;
+    }
+
+    public String[] getProviderAddresses() {
+        return providerAddresses;
+    }
+
+    public void setProviderAddresses(String[] providerAddresses) {
+        this.providerAddresses = providerAddresses;
+    }
+
+    public Map<String, Object> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map<String, Object> parameters) {
+        this.parameters = parameters;
+    }
+
+    public String[] getApplications() {
+        return applications;
+    }
+
+    public void setApplications(String[] applications) {
+        this.applications = applications;
+    }
+
+    public String[] getServices() {
+        return services;
+    }
+
+    public void setServices(String[] services) {
+        this.services = services;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java
index 0d57e90..d63139d 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java
@@ -1,137 +1,19 @@
-/*
- * 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.dubbo.admin.model.domain;
 
-import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.URL;
-
-import java.util.List;
-
-/**
- * Route
- *
- */
-public class Route extends Entity {
-
-    public static final String ALL_METHOD = "*";
-    public static final String KEY_METHOD = "method";
-
-    // WHEN KEY
-    public static final String KEY_CONSUMER_APPLICATION = "consumer.application";
-    public static final String KEY_CONSUMER_GROUP = "consumer.cluster";
-    public static final String KEY_CONSUMER_VERSION = "consumer.version";
-    public static final String KEY_CONSUMER_HOST = "host";
-    public static final String KEY_CONSUMER_METHODS = "consumer.methods";
-    public static final String KEY_PROVIDER_APPLICATION = "provider.application";
-
-    // THEN KEY
-    public static final String KEY_PROVIDER_GROUP = "provider.cluster";
-    public static final String KEY_PROVIDER_PROTOCOL = "provider.protocol";
-    public static final String KEY_PROVIDER_VERSION = "provider.version";
-    public static final String KEY_PROVIDER_HOST = "provider.host";
-    public static final String KEY_PROVIDER_PORT = "provider.port";
-    private static final long serialVersionUID = -7630589008164140656L;
-    private long parentId; //default 0
-
-    private String name;
-
-    private String service;
-
-    private String rule;
-
-    private String matchRule;
-
-    private String filterRule;
-
-    private int priority;
-
-    private String username;
-
-    private boolean enabled;
-
-    private boolean force;
-
-    private boolean dynamic;
+public abstract class Route {
 
+    private String key;
     private boolean runtime;
+    private boolean force;
+    private boolean enabled;
+    private int priority;
 
-    private List<Route> children;
-
-    public Route() {
-    }
-
-    public Route(Long id) {
-        super(id);
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public long getParentId() {
-        return parentId;
-    }
-
-    public void setParentId(long parentId) {
-        this.parentId = parentId;
-    }
-
-    public List<Route> getChildren() {
-        return children;
-    }
-
-    public void setChildren(List<Route> subRules) {
-        this.children = subRules;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    public void setEnabled(boolean enabled) {
-        this.enabled = enabled;
-    }
-
-    public boolean isDynamic() {
-        return dynamic;
+    public String getKey() {
+        return key;
     }
 
-    public void setDynamic(boolean dynamic) {
-        this.dynamic = dynamic;
+    public void setKey(String key) {
+        this.key = key;
     }
 
     public boolean isRuntime() {
@@ -150,86 +32,19 @@ public class Route extends Entity {
         this.force = force;
     }
 
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public String getRule() {
-        return rule;
-    }
-
-    public void setRule(String rule) {
-        this.rule = rule.trim();
-        String[] rules = rule.split("=>");
-        if (rules.length != 2) {
-            if (rule.endsWith("=>")) {
-                this.matchRule = rules[0].trim();
-                this.filterRule = "";
-            } else {
-                throw new IllegalArgumentException("Illegal Route Condition Rule");
-            }
-        } else {
-            this.matchRule = rules[0].trim();
-            this.filterRule = rules[1].trim();
-        }
-    }
-
-    public String getMatchRule() {
-        return matchRule;
-    }
-
-    public void setMatchRule(String matchRule) {
-        if (matchRule != null) {
-            this.matchRule = matchRule.trim();
-        } else {
-            this.matchRule = matchRule;
-        }
-    }
-
-    public String getFilterRule() {
-        return filterRule;
+    public boolean isEnabled() {
+        return enabled;
     }
 
-    public void setFilterRule(String filterRule) {
-        if (filterRule != null) {
-            this.filterRule = filterRule.trim();
-        } else {
-            this.filterRule = filterRule;
-        }
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
     }
 
-    @java.lang.Override
-    public String toString() {
-        return "Route [parentId=" + parentId + ", name=" + name
-                + ", serviceName=" + service + ", matchRule=" + matchRule
-                + ", filterRule=" + filterRule + ", priority=" + priority
-                + ", username=" + username + ", enabled=" + enabled + "]";
+    public int getPriority() {
+        return priority;
     }
 
-    public URL toUrl() {
-        String group = null;
-        String version = null;
-        String path = service;
-        int i = path.indexOf("/");
-        if (i > 0) {
-            group = path.substring(0, i);
-            path = path.substring(i + 1);
-        }
-        i = path.lastIndexOf(":");
-        if (i > 0) {
-            version = path.substring(i + 1);
-            path = path.substring(0, i);
-        }
-        return URL.valueOf(Constants.ROUTE_PROTOCOL + "://" + Constants.ANYHOST_VALUE + "/" + path
-                + "?" + Constants.CATEGORY_KEY + "=" + Constants.ROUTERS_CATEGORY
-                + "&router=condition&runtime=" + isRuntime() + "&enabled=" + isEnabled() + "&priority=" + getPriority() + "&force=" + isForce() + "&dynamic=" + isDynamic()
-                + "&name=" + getName() + "&" + Constants.RULE_KEY + "=" + URL.encode(getMatchRule() + " => " + getFilterRule())
-                + (group == null ? "" : "&" + Constants.GROUP_KEY + "=" + group)
-                + (version == null ? "" : "&" + Constants.VERSION_KEY + "=" + version));
+    public void setPriority(int priority) {
+        this.priority = priority;
     }
-
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Tag.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Tag.java
new file mode 100644
index 0000000..aed9abf
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Tag.java
@@ -0,0 +1,25 @@
+package org.apache.dubbo.admin.model.domain;
+
+/**
+ * @author zmx ON 2018/11/28
+ */
+public class Tag {
+    String name;
+    String[] address;
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String[] getAddress() {
+        return address;
+    }
+
+    public void setAddress(String[] address) {
+        this.address = address;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/TagRoute.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/TagRoute.java
new file mode 100644
index 0000000..40512dd
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/TagRoute.java
@@ -0,0 +1,15 @@
+package org.apache.dubbo.admin.model.domain;
+
+
+public class TagRoute extends Route{
+    private Tag[] tags;
+
+
+    public Tag[] getTags() {
+        return tags;
+    }
+
+    public void setTags(Tag[] tags) {
+        this.tags = tags;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConditionRouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConditionRouteDTO.java
new file mode 100644
index 0000000..e052ca1
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConditionRouteDTO.java
@@ -0,0 +1,22 @@
+package org.apache.dubbo.admin.model.dto;
+
+public class ConditionRouteDTO extends RouteDTO{
+    private String service;
+    private String[] conditions;
+
+    public String getService() {
+        return service;
+    }
+
+    public void setService(String service) {
+        this.service = service;
+    }
+
+    public String[] getConditions() {
+        return conditions;
+    }
+
+    public void setConditions(String[] conditions) {
+        this.conditions = conditions;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/OverrideDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/OverrideDTO.java
index 91f40ee..3497529 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/OverrideDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/OverrideDTO.java
@@ -17,17 +17,35 @@
 
 package org.apache.dubbo.admin.model.dto;
 
+import org.apache.dubbo.admin.model.domain.Config;
+import org.apache.dubbo.admin.model.domain.OverrideConfig;
+
 import java.util.Map;
 
 public class OverrideDTO extends BaseDTO{
 
-    String application;
-    String service;
-    String address;
-    boolean dynamic;
-    boolean enabled;
-    Map<String, Object>[] parameters;
-    Map<Object, String>[] mock;
+    private String application;
+    private String apiVersion;
+    private String service;
+    private boolean dynamic;
+    private boolean enabled;
+    private OverrideConfig[] configs;
+
+    public OverrideConfig[] getConfigs() {
+        return configs;
+    }
+
+    public void setConfigs(OverrideConfig[] configs) {
+        this.configs = configs;
+    }
+
+    public String getApiVersion() {
+        return apiVersion;
+    }
+
+    public void setApiVersion(String apiVersion) {
+        this.apiVersion = apiVersion;
+    }
 
     public String getApplication() {
         return application;
@@ -45,14 +63,6 @@ public class OverrideDTO extends BaseDTO{
         this.service = service;
     }
 
-    public String getAddress() {
-        return address;
-    }
-
-    public void setAddress(String address) {
-        this.address = address;
-    }
-
     public boolean isDynamic() {
         return dynamic;
     }
@@ -68,20 +78,4 @@ public class OverrideDTO extends BaseDTO{
     public void setEnabled(boolean enabled) {
         this.enabled = enabled;
     }
-
-    public Map<String, Object>[] getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(Map<String, Object>[] parameters) {
-        this.parameters = parameters;
-    }
-
-    public Map<Object, String>[] getMock() {
-        return mock;
-    }
-
-    public void setMock(Map<Object, String>[] mock) {
-        this.mock = mock;
-    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java
index 849e204..867ee8a 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java
@@ -17,31 +17,21 @@
 
 package org.apache.dubbo.admin.model.dto;
 
-public class RouteDTO extends BaseDTO{
-    private String app;
-    private String service;
+public abstract class RouteDTO extends BaseDTO{
     private boolean dynamic;
     private int priority;
     private boolean enabled;
     private boolean force;
     private boolean runtime;
-    private String[] conditions;
+    private String application;
 
 
-    public String getApp() {
-        return app;
+    public String getApplication() {
+        return application;
     }
 
-    public void setApp(String app) {
-        this.app = app;
-    }
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
+    public void setApplication(String application) {
+        this.application = application;
     }
 
     public boolean isDynamic() {
@@ -83,12 +73,4 @@ public class RouteDTO extends BaseDTO{
     public void setRuntime(boolean runtime) {
         this.runtime = runtime;
     }
-
-    public String[] getConditions() {
-        return conditions;
-    }
-
-    public void setConditions(String[] conditions) {
-        this.conditions = conditions;
-    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/TagRouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/TagRouteDTO.java
new file mode 100644
index 0000000..abf1100
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/TagRouteDTO.java
@@ -0,0 +1,16 @@
+package org.apache.dubbo.admin.model.dto;
+
+import org.apache.dubbo.admin.model.domain.Tag;
+
+public class TagRouteDTO extends RouteDTO{
+    private Tag[] tags;
+
+    public Tag[] getTags() {
+        return tags;
+    }
+
+    public void setTags(Tag[] tags) {
+        this.tags = tags;
+    }
+
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OverrideService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OverrideService.java
index 51b20f8..c61e18d 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OverrideService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OverrideService.java
@@ -32,18 +32,6 @@ public interface OverrideService {
 
     void disableOverride(String id);
 
-    List<Override> findByService(String service);
-
-    List<Override> findByAddress(String address);
-
-    List<Override> findByServiceAndAddress(String service, String address);
-
-    List<Override> findByApplication(String application);
-
-    List<Override> findByServiceAndApplication(String service, String application);
-
-    List<Override> findAll();
-
-    Override findById(String id);
+    Override findOverride(String service);
 
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
index 5bd69f9..b588008 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
@@ -29,13 +29,13 @@ public interface ProviderService {
 
     void create(Provider provider);
 
-    void enableProvider(String id);
+//    void enableProvider(String id);
 
-    void disableProvider(String id);
+//    void disableProvider(String id);
 
-    void doublingProvider(String id);
+//    void doublingProvider(String id);
 
-    void halvingProvider(String id);
+//    void halvingProvider(String id);
 
     void deleteStaticProvider(String id);
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
index bbb9c16..b92cfa9 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
@@ -16,9 +16,8 @@
  */
 package org.apache.dubbo.admin.service;
 
-import org.apache.dubbo.admin.model.domain.Route;
-
-import java.util.List;
+import org.apache.dubbo.admin.model.domain.ConditionRoute;
+import org.apache.dubbo.admin.model.domain.TagRoute;
 
 /**
  * RouteService
@@ -26,36 +25,36 @@ import java.util.List;
  */
 public interface RouteService {
 
-    void createRoute(Route route);
+    void createConditionRoute(ConditionRoute conditionRoute);
+
+    void updateConditionRoute(ConditionRoute conditionRoute);
+
+    void deleteConditionRoute(String id);
+
 
-    void updateRoute(Route route);
+    void enableConditionRoute(String id);
 
-    void deleteRoute(String id);
 
-    void enableRoute(String id);
+    void disableConditionRoute(String id);
 
-    void disableRoute(String id);
 
-    Route findRoute(String id);
+    ConditionRoute findConditionRoute(String serviceName);
 
-    List<Route> findAll();
+    void createTagRoute(TagRoute tagRoute);
 
-    List<Route> findByService(String serviceName);
+    void updateTagRoute(TagRoute tagRoute);
 
-    List<Route> findByApplication(String application);
+    void deleteTagRoute(String id);
 
-    List<Route> findByAddress(String address);
 
-    List<Route> findByServiceAndAddress(String service, String address);
+    void enableTagRoute(String id);
 
-    List<Route> findForceRouteByService(String service);
 
-    List<Route> findForceRouteByAddress(String address);
+    void disableTagRoute(String id);
 
-    List<Route> findForceRouteByServiceAndAddress(String service, String address);
 
-    List<Route> findAllForceRoute();
+    TagRoute findTagRoute(String serviceName);
 
-    Route getBlackwhitelistRouteByService(String service);
+    ConditionRoute getBlackwhitelistRouteByService(String service);
 
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
index d80fe40..7818dd0 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
@@ -16,17 +16,15 @@
  */
 package org.apache.dubbo.admin.service.impl;
 
-import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.URL;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.service.OverrideService;
-import org.apache.dubbo.admin.common.util.Pair;
-import org.apache.dubbo.admin.common.util.SyncUtils;
 import org.apache.dubbo.admin.model.domain.Override;
 import org.springframework.stereotype.Component;
+import org.yaml.snakeyaml.Yaml;
 
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
+
 
 /**
  * IbatisOverrideDAO.java
@@ -34,127 +32,81 @@ import java.util.Map;
  */
 @Component
 public class OverrideServiceImpl extends AbstractService implements OverrideService {
+    private String prefix = Constants.CONFIG_KEY;
+    Yaml yaml = new Yaml();
 
+    @java.lang.Override
     public void saveOverride(Override override) {
-        URL url = getUrlFromOverride(override);
-        registry.register(url);
+        String path = getPath(override.getKey());
+        dynamicConfiguration.setConfig(path, yaml.dump(override));
     }
 
+    @java.lang.Override
     public void updateOverride(Override override) {
-        String hash = override.getHash();
-        if (hash == null) {
-            throw new IllegalStateException("no override id");
-        }
-        URL oldOverride = findOverrideUrl(hash);
-        if (oldOverride == null) {
-            throw new IllegalStateException("Route was changed!");
+        String path = getPath(override.getKey());
+        if (dynamicConfiguration.getConfig(path) == null) {
+            //throw exception
         }
-        URL newOverride = getUrlFromOverride(override);
-
-        registry.unregister(oldOverride);
-        registry.register(newOverride);
-
+        dynamicConfiguration.setConfig(path, yaml.dump(override));
     }
 
+    @java.lang.Override
     public void deleteOverride(String id) {
-        URL oldOverride = findOverrideUrl(id);
-        if (oldOverride == null) {
-            throw new IllegalStateException("Route was changed!");
+        if (StringUtils.isEmpty(id)) {
+            // throw exception
         }
-        registry.unregister(oldOverride);
+        String path = getPath(id);
+        if (dynamicConfiguration.getConfig(path) == null) {
+            //throw exception
+        }
+        dynamicConfiguration.deleteConfig(path);
     }
 
+    @java.lang.Override
     public void enableOverride(String id) {
-        if (id == null) {
-            throw new IllegalStateException("no override id");
-        }
-
-        URL oldOverride = findOverrideUrl(id);
-        if (oldOverride == null) {
-            throw new IllegalStateException("Override was changed!");
+        if (StringUtils.isEmpty(id)) {
+            //throw exception
         }
-        if (oldOverride.getParameter("enabled", true)) {
-            return;
+        String path = getPath(id);
+        if (dynamicConfiguration.getConfig(path) == null) {
+            //throw exception
         }
-
-        URL newOverride = oldOverride.addParameter("enabled", true);
-        registry.unregister(oldOverride);
-        registry.register(newOverride);
-
+        String config = dynamicConfiguration.getConfig(path);
+        Override override = yaml.loadAs(config, Override.class);
+        override.setEnabled(true);
+        dynamicConfiguration.setConfig(path, yaml.dump(override));
     }
 
+    @java.lang.Override
     public void disableOverride(String id) {
-        if (id == null) {
-            throw new IllegalStateException("no override id");
-        }
-
-        URL oldProvider = findOverrideUrl(id);
-        if (oldProvider == null) {
-            throw new IllegalStateException("Override was changed!");
+        if (StringUtils.isEmpty(id)) {
+            //throw exception
         }
-        if (!oldProvider.getParameter("enabled", true)) {
-            return;
+        String path = getPath(id);
+        if (dynamicConfiguration.getConfig(path) == null) {
+            //throw exception
         }
-
-        URL newProvider = oldProvider.addParameter("enabled", false);
-        registry.unregister(oldProvider);
-        registry.register(newProvider);
-
+        String config = dynamicConfiguration.getConfig(path);
+        Override override = yaml.loadAs(config, Override.class);
+        override.setEnabled(false);
+        dynamicConfiguration.setConfig(path, yaml.dump(override));
     }
 
-    private Map<String, URL> findOverrideUrl(String service, String address, String application) {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.CONFIGURATORS_CATEGORY);
-        if (service != null && service.length() > 0) {
-            filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
-        }
-        if (address != null && address.length() > 0) {
-            filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
+    @java.lang.Override
+    public Override findOverride(String id) {
+        if (StringUtils.isEmpty(id)) {
+            //throw exception
         }
-        if (application != null && application.length() > 0) {
-            filter.put(Constants.APPLICATION_KEY, application);
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            return yaml.loadAs(config, Override.class);
         }
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public List<Override> findByAddress(String address) {
-        return SyncUtils.url2OverrideList(findOverrideUrl(null, address, null));
-    }
-
-    public List<Override> findByServiceAndAddress(String service, String address) {
-        return SyncUtils.url2OverrideList(findOverrideUrl(service, address, null));
-    }
-
-    public List<Override> findByApplication(String application) {
-        return SyncUtils.url2OverrideList(findOverrideUrl(null, null, application));
-    }
-
-    public List<Override> findByService(String service) {
-        return SyncUtils.url2OverrideList(findOverrideUrl(service, null, null));
-    }
-
-    public List<Override> findByServiceAndApplication(String service, String application) {
-        return SyncUtils.url2OverrideList(findOverrideUrl(service, null, application));
-    }
-
-    public List<Override> findAll() {
-        return SyncUtils.url2OverrideList(findOverrideUrl(null, null, null));
-    }
-
-    private Pair<String, URL> findOverrideUrlPair(String id) {
-        return SyncUtils.filterFromCategory(getRegistryCache(), Constants.CONFIGURATORS_CATEGORY, id);
-    }
-
-    public Override findById(String id) {
-        return SyncUtils.url2Override(findOverrideUrlPair(id));
-    }
-
-    private URL getUrlFromOverride(Override override) {
-        return override.toUrl();
+        return null;
     }
 
-    URL findOverrideUrl(String id) {
-        return getUrlFromOverride(findById(id));
+    private String getPath(String key) {
+        return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "configurators";
     }
 
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OwnerServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OwnerServiceImpl.java
index 8482dbe..38be229 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OwnerServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OwnerServiceImpl.java
@@ -1,159 +1,159 @@
-/*
- * 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.dubbo.admin.service.impl;
-
-import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.service.OverrideService;
-import org.apache.dubbo.admin.service.OwnerService;
-import org.apache.dubbo.admin.service.ProviderService;
-import org.apache.dubbo.admin.model.domain.Override;
-import org.apache.dubbo.admin.model.domain.Owner;
-import org.apache.dubbo.admin.model.domain.Provider;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-@Component
-public class OwnerServiceImpl extends AbstractService implements OwnerService {
-
-    @Autowired
-    ProviderService providerService;
-
-    @Autowired
-    OverrideService overrideService;
-
-    public List<String> findAllServiceNames() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public List<String> findServiceNamesByUsername(String username) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public List<String> findUsernamesByServiceName(String serviceName) {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    public List<Owner> findByService(String serviceName) {
-        List<Provider> pList = providerService.findByService(serviceName);
-        List<Override> cList = overrideService.findByServiceAndAddress(serviceName, Constants.ANYHOST_VALUE);
-        return toOverrideLiset(pList, cList);
-    }
-
-    public List<Owner> findAll() {
-        List<Provider> pList = providerService.findAll();
-        List<Override> cList = overrideService.findAll();
-        return toOverrideLiset(pList, cList);
-    }
-
-    public Owner findById(String id) {
-
-        return null;
-    }
-
-    private List<Owner> toOverrideLiset(List<Provider> pList, List<Override> cList) {
-        Map<String, Owner> oList = new HashMap<String, Owner>();
-        for (Provider p : pList) {
-            if (p.getUsername() != null) {
-                for (String username : Constants.COMMA_SPLIT_PATTERN.split(p.getUsername())) {
-                    Owner o = new Owner();
-                    o.setService(p.getService());
-                    o.setUsername(username);
-                    oList.put(o.getService() + "/" + o.getUsername(), o);
-                }
-            }
-        }
-        for (Override c : cList) {
-            Map<String, String> params = StringUtils.parseQueryString(c.getParams());
-            String usernames = params.get("owner");
-            if (usernames != null && usernames.length() > 0) {
-                for (String username : Constants.COMMA_SPLIT_PATTERN.split(usernames)) {
-                    Owner o = new Owner();
-                    o.setService(c.getService());
-                    o.setUsername(username);
-                    oList.put(o.getService() + "/" + o.getUsername(), o);
-                }
-            }
-        }
-        return new ArrayList<Owner>(oList.values());
-    }
-
-    public void saveOwner(Owner owner) {
-        List<Override> overrides = overrideService.findByServiceAndAddress(owner.getService(), Constants.ANYHOST_VALUE);
-        if (overrides == null || overrides.size() == 0) {
-            Override override = new Override();
-            override.setAddress(Constants.ANYHOST_VALUE);
-            override.setService(owner.getService());
-            override.setEnabled(true);
-            override.setParams("owner=" + owner.getUsername());
-            overrideService.saveOverride(override);
-        } else {
-            for (Override override : overrides) {
-                Map<String, String> params = StringUtils.parseQueryString(override.getParams());
-                String usernames = params.get("owner");
-                if (usernames == null || usernames.length() == 0) {
-                    usernames = owner.getUsername();
-                } else {
-                    usernames = usernames + "," + owner.getUsername();
-                }
-                params.put("owner", usernames);
-                override.setParams(StringUtils.toQueryString(params));
-                overrideService.updateOverride(override);
-            }
-        }
-    }
-
-    public void deleteOwner(Owner owner) {
-        List<Override> overrides = overrideService.findByServiceAndAddress(owner.getService(), Constants.ANYHOST_VALUE);
-        if (overrides == null || overrides.size() == 0) {
-            Override override = new Override();
-            override.setAddress(Constants.ANYHOST_VALUE);
-            override.setService(owner.getService());
-            override.setEnabled(true);
-            override.setParams("owner=" + owner.getUsername());
-            overrideService.saveOverride(override);
-        } else {
-            for (Override override : overrides) {
-                Map<String, String> params = StringUtils.parseQueryString(override.getParams());
-                String usernames = params.get("owner");
-                if (usernames != null && usernames.length() > 0) {
-                    if (usernames.equals(owner.getUsername())) {
-                        params.remove("owner");
-                    } else {
-                        usernames = usernames.replace(owner.getUsername() + ",", "").replace("," + owner.getUsername(), "");
-                        params.put("owner", usernames);
-                    }
-                    if (params.size() > 0) {
-                        override.setParams(StringUtils.toQueryString(params));
-                        overrideService.updateOverride(override);
-                    } else {
-                        overrideService.deleteOverride(override.getHash());
-                    }
-                }
-            }
-        }
-    }
-
-}
+///*
+// * 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.dubbo.admin.service.impl;
+//
+//import org.apache.dubbo.common.Constants;
+//import org.apache.dubbo.common.utils.StringUtils;
+//import org.apache.dubbo.admin.service.OverrideService;
+//import org.apache.dubbo.admin.service.OwnerService;
+//import org.apache.dubbo.admin.service.ProviderService;
+//import org.apache.dubbo.admin.model.domain.Override;
+//import org.apache.dubbo.admin.model.domain.Owner;
+//import org.apache.dubbo.admin.model.domain.Provider;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.stereotype.Component;
+//
+//import java.util.ArrayList;
+//import java.util.HashMap;
+//import java.util.List;
+//import java.util.Map;
+//
+//@Component
+//public class OwnerServiceImpl extends AbstractService implements OwnerService {
+//
+//    @Autowired
+//    ProviderService providerService;
+//
+//    @Autowired
+//    OverrideService overrideService;
+//
+//    public List<String> findAllServiceNames() {
+//        // TODO Auto-generated method stub
+//        return null;
+//    }
+//
+//    public List<String> findServiceNamesByUsername(String username) {
+//        // TODO Auto-generated method stub
+//        return null;
+//    }
+//
+//    public List<String> findUsernamesByServiceName(String serviceName) {
+//        // TODO Auto-generated method stub
+//        return null;
+//    }
+//
+//    public List<Owner> findByService(String serviceName) {
+//        List<Provider> pList = providerService.findByService(serviceName);
+//        List<Override> cList = overrideService.findByServiceAndAddress(serviceName, Constants.ANYHOST_VALUE);
+//        return toOverrideLiset(pList, cList);
+//    }
+//
+//    public List<Owner> findAll() {
+//        List<Provider> pList = providerService.findAll();
+//        List<Override> cList = overrideService.findAll();
+//        return toOverrideLiset(pList, cList);
+//    }
+//
+//    public Owner findById(String id) {
+//
+//        return null;
+//    }
+//
+//    private List<Owner> toOverrideLiset(List<Provider> pList, List<Override> cList) {
+//        Map<String, Owner> oList = new HashMap<String, Owner>();
+//        for (Provider p : pList) {
+//            if (p.getUsername() != null) {
+//                for (String username : Constants.COMMA_SPLIT_PATTERN.split(p.getUsername())) {
+//                    Owner o = new Owner();
+//                    o.setService(p.getService());
+//                    o.setUsername(username);
+//                    oList.put(o.getService() + "/" + o.getUsername(), o);
+//                }
+//            }
+//        }
+//        for (Override c : cList) {
+//            Map<String, String> params = StringUtils.parseQueryString(c.getParams());
+//            String usernames = params.get("owner");
+//            if (usernames != null && usernames.length() > 0) {
+//                for (String username : Constants.COMMA_SPLIT_PATTERN.split(usernames)) {
+//                    Owner o = new Owner();
+//                    o.setService(c.getService());
+//                    o.setUsername(username);
+//                    oList.put(o.getService() + "/" + o.getUsername(), o);
+//                }
+//            }
+//        }
+//        return new ArrayList<Owner>(oList.values());
+//    }
+//
+//    public void saveOwner(Owner owner) {
+//        List<Override> overrides = overrideService.findByServiceAndAddress(owner.getService(), Constants.ANYHOST_VALUE);
+//        if (overrides == null || overrides.size() == 0) {
+//            Override override = new Override();
+//            override.setAddress(Constants.ANYHOST_VALUE);
+//            override.setService(owner.getService());
+//            override.setEnabled(true);
+//            override.setParams("owner=" + owner.getUsername());
+//            overrideService.saveOverride(override);
+//        } else {
+//            for (Override override : overrides) {
+//                Map<String, String> params = StringUtils.parseQueryString(override.getParams());
+//                String usernames = params.get("owner");
+//                if (usernames == null || usernames.length() == 0) {
+//                    usernames = owner.getUsername();
+//                } else {
+//                    usernames = usernames + "," + owner.getUsername();
+//                }
+//                params.put("owner", usernames);
+//                override.setParams(StringUtils.toQueryString(params));
+//                overrideService.updateOverride(override);
+//            }
+//        }
+//    }
+//
+//    public void deleteOwner(Owner owner) {
+//        List<Override> overrides = overrideService.findByServiceAndAddress(owner.getService(), Constants.ANYHOST_VALUE);
+//        if (overrides == null || overrides.size() == 0) {
+//            Override override = new Override();
+//            override.setAddress(Constants.ANYHOST_VALUE);
+//            override.setService(owner.getService());
+//            override.setEnabled(true);
+//            override.setParams("owner=" + owner.getUsername());
+//            overrideService.saveOverride(override);
+//        } else {
+//            for (Override override : overrides) {
+//                Map<String, String> params = StringUtils.parseQueryString(override.getParams());
+//                String usernames = params.get("owner");
+//                if (usernames != null && usernames.length() > 0) {
+//                    if (usernames.equals(owner.getUsername())) {
+//                        params.remove("owner");
+//                    } else {
+//                        usernames = usernames.replace(owner.getUsername() + ",", "").replace("," + owner.getUsername(), "");
+//                        params.put("owner", usernames);
+//                    }
+//                    if (params.size() > 0) {
+//                        override.setParams(StringUtils.toQueryString(params));
+//                        overrideService.updateOverride(override);
+//                    } else {
+//                        overrideService.deleteOverride(override.getHash());
+//                    }
+//                }
+//            }
+//        }
+//    }
+//
+//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
index 3a81d2a..fbefeb6 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
@@ -52,149 +52,149 @@ public class ProviderServiceImpl extends AbstractService implements ProviderServ
         registry.register(url);
     }
 
-    public void enableProvider(String id) {
-        if (id == null) {
-            throw new IllegalStateException("no provider id");
-        }
-
-        Provider oldProvider = findProvider(id);
-
-        if (oldProvider == null) {
-            throw new IllegalStateException("Provider was changed!");
-        }
-        if (oldProvider.isDynamic()) {
-            // Make sure we only have one override configured disable property.
-            if (!oldProvider.isEnabled()) {
-                Override override = new Override();
-                override.setAddress(oldProvider.getAddress());
-                override.setService(oldProvider.getService());
-                override.setEnabled(true);
-                override.setParams(Constants.DISABLED_KEY + "=false");
-                overrideService.saveOverride(override);
-                return;
-            }
-            List<Override> oList = overrideService.findByServiceAndAddress(oldProvider.getService(), oldProvider.getAddress());
-
-            for (Override o : oList) {
-                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
-                if (params.containsKey(Constants.DISABLED_KEY)) {
-                    if (params.get(Constants.DISABLED_KEY).equals("true")) {
-                        overrideService.deleteOverride(o.getHash());
-                    }
-                }
-            }
-        } else {
-            oldProvider.setEnabled(true);
-            updateProvider(oldProvider);
-        }
-    }
+//    public void enableProvider(String id) {
+//        if (id == null) {
+//            throw new IllegalStateException("no provider id");
+//        }
+//
+//        Provider oldProvider = findProvider(id);
+//
+//        if (oldProvider == null) {
+//            throw new IllegalStateException("Provider was changed!");
+//        }
+//        if (oldProvider.isDynamic()) {
+//            // Make sure we only have one override configured disable property.
+//            if (!oldProvider.isEnabled()) {
+//                Override override = new Override();
+//                override.setAddress(oldProvider.getAddress());
+//                override.setService(oldProvider.getService());
+//                override.setEnabled(true);
+//                override.setParams(Constants.DISABLED_KEY + "=false");
+//                overrideService.saveOverride(override);
+//                return;
+//            }
+//            List<Override> oList = overrideService.findByServiceAndAddress(oldProvider.getService(), oldProvider.getAddress());
+//
+//            for (Override o : oList) {
+//                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
+//                if (params.containsKey(Constants.DISABLED_KEY)) {
+//                    if (params.get(Constants.DISABLED_KEY).equals("true")) {
+//                        overrideService.deleteOverride(o.getHash());
+//                    }
+//                }
+//            }
+//        } else {
+//            oldProvider.setEnabled(true);
+//            updateProvider(oldProvider);
+//        }
+//    }
 
     @java.lang.Override
     public String getProviderMetaData(ProviderMetadataIdentifier providerIdentifier) {
         return metaDataCollector.getProviderMetaData(providerIdentifier);
     }
 
-    public void disableProvider(String id) {
-        if (id == null) {
-            throw new IllegalStateException("no provider id");
-        }
-
-        Provider oldProvider = findProvider(id);
-        if (oldProvider == null) {
-            throw new IllegalStateException("Provider was changed!");
-        }
-
-        if (oldProvider.isDynamic()) {
-            // Make sure we only have one override configured disable property.
-            if (oldProvider.isEnabled()) {
-                Override override = new Override();
-                override.setAddress(oldProvider.getAddress());
-                override.setService(oldProvider.getService());
-                override.setEnabled(true);
-                override.setParams(Constants.DISABLED_KEY + "=true");
-                overrideService.saveOverride(override);
-                return;
-            }
-            List<Override> oList = overrideService.findByServiceAndAddress(oldProvider.getService(), oldProvider.getAddress());
-
-            for (Override o : oList) {
-                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
-                if (params.containsKey(Constants.DISABLED_KEY)) {
-                    if (params.get(Constants.DISABLED_KEY).equals("false")) {
-                        overrideService.deleteOverride(o.getHash());
-                    }
-                }
-            }
-        } else {
-            oldProvider.setEnabled(false);
-            updateProvider(oldProvider);
-        }
-
-    }
-
-    public void doublingProvider(String id) {
-        setWeight(id, 2F);
-    }
-
-    public void halvingProvider(String id) {
-        setWeight(id, 0.5F);
-    }
-
-    public void setWeight(String id, float factor) {
-        if (id == null) {
-            throw new IllegalStateException("no provider id");
-        }
-        Provider oldProvider = findProvider(id);
-        if (oldProvider == null) {
-            throw new IllegalStateException("Provider was changed!");
-        }
-        Map<String, String> map = StringUtils.parseQueryString(oldProvider.getParameters());
-        String weight = map.get(Constants.WEIGHT_KEY);
-        if (oldProvider.isDynamic()) {
-            // Make sure we only have one override configured disable property.
-            List<Override> overrides = overrideService.findByServiceAndAddress(oldProvider.getService(), oldProvider.getAddress());
-            if (overrides == null || overrides.size() == 0) {
-                int value = getWeight(weight, factor);
-                if (value != Constants.DEFAULT_WEIGHT) {
-                    Override override = new Override();
-                    override.setAddress(oldProvider.getAddress());
-                    override.setService(oldProvider.getService());
-                    override.setEnabled(true);
-                    override.setParams(Constants.WEIGHT_KEY + "=" + String.valueOf(value));
-                    overrideService.saveOverride(override);
-                }
-            } else {
-                for (Override override : overrides) {
-                    Map<String, String> params = StringUtils.parseQueryString(override.getParams());
-                    String overrideWeight = params.get(Constants.WEIGHT_KEY);
-                    if (overrideWeight == null || overrideWeight.length() == 0) {
-                        overrideWeight = weight;
-                    }
-                    int value = getWeight(overrideWeight, factor);
-                    if (value == getWeight(weight, 1)) {
-                        params.remove(Constants.WEIGHT_KEY);
-                    } else {
-                        params.put(Constants.WEIGHT_KEY, String.valueOf(value));
-                    }
-                    if (params.size() > 0) {
-                        override.setParams(StringUtils.toQueryString(params));
-                        overrideService.updateOverride(override);
-                    } else {
-                        overrideService.deleteOverride(override.getHash());
-                    }
-                }
-            }
-        } else {
-            int value = getWeight(weight, factor);
-            if (value == Constants.DEFAULT_WEIGHT) {
-                map.remove(Constants.WEIGHT_KEY);
-            } else {
-                map.put(Constants.WEIGHT_KEY, String.valueOf(value));
-            }
-            oldProvider.setParameters(StringUtils.toQueryString(map));
-            updateProvider(oldProvider);
-        }
-    }
+//    public void disableProvider(String id) {
+//        if (id == null) {
+//            throw new IllegalStateException("no provider id");
+//        }
+//
+//        Provider oldProvider = findProvider(id);
+//        if (oldProvider == null) {
+//            throw new IllegalStateException("Provider was changed!");
+//        }
+//
+//        if (oldProvider.isDynamic()) {
+//            // Make sure we only have one override configured disable property.
+//            if (oldProvider.isEnabled()) {
+//                Override override = new Override();
+//                override.setAddress(oldProvider.getAddress());
+//                override.setService(oldProvider.getService());
+//                override.setEnabled(true);
+//                override.setParams(Constants.DISABLED_KEY + "=true");
+//                overrideService.saveOverride(override);
+//                return;
+//            }
+//            List<Override> oList = overrideService.findByServiceAndAddress(oldProvider.getService(), oldProvider.getAddress());
+//
+//            for (Override o : oList) {
+//                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
+//                if (params.containsKey(Constants.DISABLED_KEY)) {
+//                    if (params.get(Constants.DISABLED_KEY).equals("false")) {
+//                        overrideService.deleteOverride(o.getHash());
+//                    }
+//                }
+//            }
+//        } else {
+//            oldProvider.setEnabled(false);
+//            updateProvider(oldProvider);
+//        }
+//
+//    }
+
+//    public void doublingProvider(String id) {
+//        setWeight(id, 2F);
+//    }
+//
+//    public void halvingProvider(String id) {
+//        setWeight(id, 0.5F);
+//    }
+
+//    public void setWeight(String id, float factor) {
+//        if (id == null) {
+//            throw new IllegalStateException("no provider id");
+//        }
+//        Provider oldProvider = findProvider(id);
+//        if (oldProvider == null) {
+//            throw new IllegalStateException("Provider was changed!");
+//        }
+//        Map<String, String> map = StringUtils.parseQueryString(oldProvider.getParameters());
+//        String weight = map.get(Constants.WEIGHT_KEY);
+//        if (oldProvider.isDynamic()) {
+//            // Make sure we only have one override configured disable property.
+//            List<Override> overrides = overrideService.findByServiceAndAddress(oldProvider.getService(), oldProvider.getAddress());
+//            if (overrides == null || overrides.size() == 0) {
+//                int value = getWeight(weight, factor);
+//                if (value != Constants.DEFAULT_WEIGHT) {
+//                    Override override = new Override();
+//                    override.setAddress(oldProvider.getAddress());
+//                    override.setService(oldProvider.getService());
+//                    override.setEnabled(true);
+//                    override.setParams(Constants.WEIGHT_KEY + "=" + String.valueOf(value));
+//                    overrideService.saveOverride(override);
+//                }
+//            } else {
+//                for (Override override : overrides) {
+//                    Map<String, String> params = StringUtils.parseQueryString(override.getParams());
+//                    String overrideWeight = params.get(Constants.WEIGHT_KEY);
+//                    if (overrideWeight == null || overrideWeight.length() == 0) {
+//                        overrideWeight = weight;
+//                    }
+//                    int value = getWeight(overrideWeight, factor);
+//                    if (value == getWeight(weight, 1)) {
+//                        params.remove(Constants.WEIGHT_KEY);
+//                    } else {
+//                        params.put(Constants.WEIGHT_KEY, String.valueOf(value));
+//                    }
+//                    if (params.size() > 0) {
+//                        override.setParams(StringUtils.toQueryString(params));
+//                        overrideService.updateOverride(override);
+//                    } else {
+//                        overrideService.deleteOverride(override.getHash());
+//                    }
+//                }
+//            }
+//        } else {
+//            int value = getWeight(weight, factor);
+//            if (value == Constants.DEFAULT_WEIGHT) {
+//                map.remove(Constants.WEIGHT_KEY);
+//            } else {
+//                map.put(Constants.WEIGHT_KEY, String.valueOf(value));
+//            }
+//            oldProvider.setParameters(StringUtils.toQueryString(map));
+//            updateProvider(oldProvider);
+//        }
+//    }
 
     private int getWeight(String value, float factor) {
         int weight = 100;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
index 91c5b0d..588d66b 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
@@ -16,18 +16,12 @@
  */
 package org.apache.dubbo.admin.service.impl;
 
-import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.admin.model.dto.AccessDTO;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.model.domain.ConditionRoute;
+import org.apache.dubbo.admin.model.domain.TagRoute;
 import org.apache.dubbo.admin.service.RouteService;
-import org.apache.dubbo.admin.common.util.Pair;
-import org.apache.dubbo.admin.common.util.SyncUtils;
-import org.apache.dubbo.admin.model.domain.Route;
 import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import org.yaml.snakeyaml.Yaml;
 
 /**
  * IbatisRouteService
@@ -36,149 +30,133 @@ import java.util.Map;
 @Component
 public class RouteServiceImpl extends AbstractService implements RouteService {
 
-    public void createRoute(Route route) {
-        registry.register(route.toUrl());
-    }
-
-    public void updateRoute(Route route) {
-        String hash = route.getHash();
-        if (hash == null) {
-            throw new IllegalStateException("no route hash");
-        }
-        URL oldRoute = findRouteUrl(hash);
-        if (oldRoute == null) {
-            throw new IllegalStateException("Route was changed!");
-        }
-
-        registry.unregister(oldRoute);
-        registry.register(route.toUrl());
-    }
+    private String prefix = Constants.CONFIG_KEY;
+    Yaml yaml = new Yaml();
 
-    public void deleteRoute(String id) {
-        URL oldRoute = findRouteUrl(id);
-        if (oldRoute == null) {
-            throw new IllegalStateException("Route was changed!");
-        }
-        registry.unregister(oldRoute);
+    @Override
+    public void createConditionRoute(ConditionRoute conditionRoute) {
+        String path = getPath(conditionRoute.getKey(),Constants.CONDITION_ROUTE);
+        dynamicConfiguration.setConfig(path, yaml.dump(conditionRoute));
     }
 
-    public void enableRoute(String id) {
-        if (id == null) {
-            throw new IllegalStateException("no route id");
-        }
-
-        URL oldRoute = findRouteUrl(id);
-        if (oldRoute == null) {
-            throw new IllegalStateException("Route was changed!");
-        }
-        if (oldRoute.getParameter("enabled", true)) {
-            return;
+    @Override
+    public void updateConditionRoute(ConditionRoute conditionRoute) {
+        String path = getPath(conditionRoute.getKey(), Constants.CONDITION_ROUTE);
+        if (dynamicConfiguration.getConfig(path) == null) {
+           //throw exception
         }
-
-        registry.unregister(oldRoute);
-        URL newRoute = oldRoute.addParameter("enabled", true);
-        registry.register(newRoute);
+        dynamicConfiguration.setConfig(path, yaml.dump(conditionRoute));
 
     }
 
-    public void disableRoute(String id) {
-        if (id == null) {
-            throw new IllegalStateException("no route id");
-        }
-
-        URL oldRoute = findRouteUrl(id);
-        if (oldRoute == null) {
-            throw new IllegalStateException("Route was changed!");
-        }
-        if (!oldRoute.getParameter("enabled", true)) {
-            return;
-        }
-
-        URL newRoute = oldRoute.addParameter("enabled", false);
-        registry.unregister(oldRoute);
-        registry.register(newRoute);
-
-    }
+    @Override
+    public void deleteConditionRoute(String serviceName) {
+        String path = getPath(serviceName, Constants.CONDITION_ROUTE);
+        dynamicConfiguration.deleteConfig(path);
 
-    public List<Route> findAll() {
-        return SyncUtils.url2RouteList(findAllUrl());
     }
 
-    private Map<String, URL> findAllUrl() {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.ROUTERS_CATEGORY);
 
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public Route findRoute(String id) {
-        return SyncUtils.url2Route(findRouteUrlPair(id));
+    @Override
+    public void enableConditionRoute(String serviceName) {
+        String path = getPath(serviceName, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            ConditionRoute conditionRoute = yaml.loadAs(config, ConditionRoute.class);
+            conditionRoute.setEnabled(true);
+            dynamicConfiguration.setConfig(path, yaml.dump(conditionRoute));
+        }
     }
 
-    public Pair<String, URL> findRouteUrlPair(String id) {
-        return SyncUtils.filterFromCategory(getRegistryCache(), Constants.ROUTERS_CATEGORY, id);
-    }
+    @Override
+    public void disableConditionRoute(String serviceName) {
+        String path = getPath(serviceName, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            ConditionRoute conditionRoute = yaml.loadAs(config, ConditionRoute.class);
+            conditionRoute.setEnabled(false);
+            dynamicConfiguration.setConfig(path, yaml.dump(conditionRoute));
+        }
 
-    private URL findRouteUrl(String id) {
-        return findRoute(id).toUrl();
     }
 
-    private Map<String, URL> findRouteUrl(String service, String address, boolean force) {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.ROUTERS_CATEGORY);
-        if (service != null && service.length() > 0) {
-            filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
-        }
-        if (address != null && address.length() > 0) {
-            filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
-        }
-        if (force) {
-            filter.put("force", "true");
+    @Override
+    public ConditionRoute findConditionRoute(String serviceName) {
+        String path = getPath(serviceName, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            return yaml.loadAs(config, ConditionRoute.class);
         }
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+        return null;
     }
 
     @Override
-    public List<Route> findByApplication(String application) {
-        return null;
+    public void createTagRoute(TagRoute tagRoute) {
+        String path = getPath(tagRoute.getKey(),Constants.TAG_ROUTE);
+        dynamicConfiguration.setConfig(path, yaml.dump(tagRoute));
     }
 
-    public List<Route> findByService(String serviceName) {
-        return SyncUtils.url2RouteList(findRouteUrl(serviceName, null, false));
-    }
+    @Override
+    public void updateTagRoute(TagRoute tagRoute) {
+        String path = getPath(tagRoute.getKey(), Constants.TAG_ROUTE);
+        if (dynamicConfiguration.getConfig(path) == null) {
+            //throw exception
+        }
+        dynamicConfiguration.setConfig(path, yaml.dump(tagRoute));
 
-    public List<Route> findByAddress(String address) {
-        return SyncUtils.url2RouteList(findRouteUrl(null, address, false));
     }
 
-    public List<Route> findByServiceAndAddress(String service, String address) {
-        return SyncUtils.url2RouteList(findRouteUrl(service, address, false));
+    @Override
+    public void deleteTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        dynamicConfiguration.deleteConfig(path);
     }
 
-    public List<Route> findForceRouteByService(String service) {
-        return SyncUtils.url2RouteList(findRouteUrl(service, null, true));
-    }
+    @Override
+    public void enableTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            TagRoute tagRoute = yaml.loadAs(config, TagRoute.class);
+            tagRoute.setEnabled(true);
+            dynamicConfiguration.setConfig(path, yaml.dump(tagRoute));
+        }
 
-    public List<Route> findForceRouteByAddress(String address) {
-        return SyncUtils.url2RouteList(findRouteUrl(null, address, true));
     }
 
-    public List<Route> findForceRouteByServiceAndAddress(String service, String address) {
-        return SyncUtils.url2RouteList(findRouteUrl(service, address, true));
+    @Override
+    public void disableTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            TagRoute tagRoute = yaml.loadAs(config, TagRoute.class);
+            tagRoute.setEnabled(false);
+            dynamicConfiguration.setConfig(path, yaml.dump(tagRoute));
+        }
+
     }
 
-    public List<Route> findAllForceRoute() {
-        return SyncUtils.url2RouteList(findRouteUrl(null, null, true));
+    @Override
+    public TagRoute findTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            return yaml.loadAs(config, TagRoute.class);
+        }
+        return null;
     }
 
-    public Route getBlackwhitelistRouteByService(String service) {
-        List<Route> routes = SyncUtils.url2RouteList(findRouteUrl(service, null, true));
-        for (Route route : routes) {
-            if (route.getName().endsWith(AccessDTO.KEY_BLACK_WHITE_LIST)) {
-                return route;
-            }
+    private String getPath(String key, String type) {
+        if (type.equals(Constants.CONDITION_ROUTE)) {
+            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "routers";
+        } else {
+            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "tagrouters";
         }
+    }
+    @Override
+    public ConditionRoute getBlackwhitelistRouteByService(String service) {
         return null;
     }
 
+
 }
diff --git a/dubbo-admin-frontend/src/api/menu.js b/dubbo-admin-frontend/src/api/menu.js
index 2aadcfc..6ea0773 100644
--- a/dubbo-admin-frontend/src/api/menu.js
+++ b/dubbo-admin-frontend/src/api/menu.js
@@ -23,6 +23,7 @@ const Menu = [
     group: 'governance',
     items: [
       { title: 'Routing Rule', path: '/governance/routingRule' },
+      { title: 'Tag Rule', path: '/governance/tagRule', badge: 'new'},
       { title: 'Dynamic Config', path: '/governance/config' },
       { title: 'Access Control', path: '/governance/access' },
       { title: 'Weight Adjust', path: '/governance/weight' },
diff --git a/dubbo-admin-frontend/src/components/ServiceSearch.vue b/dubbo-admin-frontend/src/components/ServiceSearch.vue
index f3c61c0..dd01cf5 100644
--- a/dubbo-admin-frontend/src/components/ServiceSearch.vue
+++ b/dubbo-admin-frontend/src/components/ServiceSearch.vue
@@ -36,24 +36,23 @@
                   :hint="hint"
                   label="Search Dubbo Services"
                 ></v-combobox>
-                  <v-menu class="hidden-xs-only">
-                    <v-btn slot="activator" large icon>
-                      <v-icon>unfold_more</v-icon>
-                    </v-btn>
+                <v-menu class="hidden-xs-only">
+                  <v-btn slot="activator" large icon>
+                    <v-icon>unfold_more</v-icon>
+                  </v-btn>
 
-                    <v-list>
-                      <v-list-tile
-                        v-for="(item, i) in items"
-                        :key="i"
-                        @click="selected = i">
-                        <v-list-tile-title>{{ item.title }}</v-list-tile-title>
-                      </v-list-tile>
-                    </v-list>
-                  </v-menu>
-                  <v-btn @click="submit" color="primary" large>Search</v-btn>
+                  <v-list>
+                    <v-list-tile
+                      v-for="(item, i) in items"
+                      :key="i"
+                      @click="selected = i">
+                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                    </v-list-tile>
+                  </v-list>
+                </v-menu>
+                <v-btn @click="submit" color="primary" large>Search</v-btn>
               </v-layout>
             </v-form>
-
           </v-card-text>
         </v-card>
       </v-flex>
diff --git a/dubbo-admin-frontend/src/components/governance/AccessControl.vue b/dubbo-admin-frontend/src/components/governance/AccessControl.vue
index 8284639..445c448 100644
--- a/dubbo-admin-frontend/src/components/governance/AccessControl.vue
+++ b/dubbo-admin-frontend/src/components/governance/AccessControl.vue
@@ -90,6 +90,12 @@
                           :rules="[required]"
                           :readonly="modal.id != null"
                           v-model="modal.service" />
+            <v-text-field
+              label="Application Name"
+              hint="Application name the service belongs to"
+              :readonly="modal.id != null"
+              v-model="modal.application"
+            ></v-text-field>
             <v-subheader class="pa-0 mt-3">BLACK/WHITE LIST CONTENT</v-subheader>
             <ace-editor v-model="modal.content" />
           </v-form>
@@ -159,6 +165,7 @@ export default {
       click: () => {},
       id: null,
       service: null,
+      application: null,
       content: '',
       template:
         'blacklist:\n' +
@@ -276,7 +283,7 @@ export default {
     }
   },
   mounted () {
-    let query = this.$route.query
+    let query = this.$conditionRoute.query
     if ('service' in query) {
       this.filter = query['service']
       this.search()
diff --git a/dubbo-admin-frontend/src/components/governance/LoadBalance.vue b/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
index 15b2dd0..8b5b7a3 100644
--- a/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
+++ b/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
@@ -68,6 +68,11 @@
             :rules="[required]"
             v-model="service"
           ></v-text-field>
+          <v-text-field
+            label="Application Name"
+            hint="Application name the service belongs to"
+            v-model="application"
+          ></v-text-field>
           <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
           <ace-editor v-model="ruleText" :readonly="readonly"/>
 
@@ -271,7 +276,7 @@
     },
     mounted: function () {
       this.ruleText = this.template
-      let query = this.$route.query
+      let query = this.$conditionRoute.query
       let service = null
       Object.keys(query).forEach(function (key) {
         if (key === 'service') {
diff --git a/dubbo-admin-frontend/src/components/governance/Overrides.vue b/dubbo-admin-frontend/src/components/governance/Overrides.vue
index 9c0c9e2..648cdce 100644
--- a/dubbo-admin-frontend/src/components/governance/Overrides.vue
+++ b/dubbo-admin-frontend/src/components/governance/Overrides.vue
@@ -18,8 +18,40 @@
 <template>
   <v-container grid-list-xl fluid >
     <v-layout row wrap>
-      <v-flex xs12 >
-        <search v-model="filter" :submit="submit" label="Search Dynamic Config by service name"></search>
+      <v-flex lg12>
+        <v-card flat color="transparent">
+          <v-card-text>
+            <v-form>
+              <v-layout row wrap>
+                <v-combobox
+                  id="serviceSearch"
+                  v-model="filter"
+                  flat
+                  append-icon=""
+                  hide-no-data
+                  :suffix="queryBy"
+                  label="Search Dynamic Config"
+                ></v-combobox>
+                <v-menu class="hidden-xs-only">
+                  <v-btn slot="activator" large icon>
+                    <v-icon>unfold_more</v-icon>
+                  </v-btn>
+
+                  <v-list>
+                    <v-list-tile
+                      v-for="(item, i) in items"
+                      :key="i"
+                      @click="selected = i">
+                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                    </v-list-tile>
+                  </v-list>
+                </v-menu>
+                <v-btn @click="submit" color="primary" large>Search</v-btn>
+
+              </v-layout>
+            </v-form>
+          </v-card-text>
+        </v-card>
       </v-flex>
     </v-layout>
 
@@ -31,10 +63,10 @@
           <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
         </v-toolbar>
 
-        <v-card-text class="pa-0">
+        <v-card-text class="pa-0" v-if="selected == 0">
           <v-data-table
-            :headers="headers"
-            :items="configs"
+            :headers="serviceHeaders"
+            :items="serviceConfigs"
             hide-actions
             class="elevation-0"
           >
@@ -51,6 +83,27 @@
             </template>
           </v-data-table>
         </v-card-text>
+
+        <v-card-text class="pa-0" v-if="selected == 1">
+          <v-data-table
+            :headers="appHeaders"
+            :items="appConfigs"
+            hide-actions
+            class="elevation-0"
+          >
+            <template slot="items" slot-scope="props">
+              <td class="text-xs-left">{{ props.item.application }}</td>
+              <td class="text-xs-center px-0">
+                <v-tooltip bottom v-for="op in operations" :key="op.id">
+                  <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon(props.item), props.item)">
+                    {{op.icon(props.item)}}
+                  </v-icon>
+                  <span>{{op.tooltip(props.item)}}</span>
+                </v-tooltip>
+              </td>
+            </template>
+          </v-data-table>
+        </v-card-text>
       </v-card>
     </v-flex>
 
@@ -63,9 +116,14 @@
           <v-text-field
             label="Service Unique ID"
             hint="A service ID in form of group/service:version, group and version are optional"
-            :rules="[required]"
             v-model="service"
           ></v-text-field>
+          <v-text-field
+            label="Application Name"
+            hint="Application name the service belongs to"
+            v-model="application"
+          ></v-text-field>
+
           <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
           <ace-editor v-model="ruleText" :readonly="readonly"/>
 
@@ -104,6 +162,11 @@
       Search
     },
     data: () => ({
+      items: [
+        {id: 0, title: 'service name', value: 'serviceName'},
+        {id: 1, title: 'application', value: 'application'}
+      ],
+      selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
       pattern: 'Service',
       filter: '',
@@ -117,24 +180,25 @@
       warnStatus: {},
       height: 0,
       operations: operations,
-      configs: [
+      serviceConfigs: [
+      ],
+      appConfigs: [
       ],
       required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
       template:
-        'application:  # consumer\'s application name, empty for all \n' +
-        'address: 192.168.0.1 # consumer\'s ip address, empty for all consumers\n' +
-        'dynamic: false\n' +
-        'enabled: true # enable this rule\n' +
-        'parameters:\n' +
-        '  - timeout: 100\n' +
-        '\n' +
-        'mock: \n' +
-        '  - 0: \'force: return null\'\n' +
-        '  - sayHello: \'force: return null\'\n' +
-        '  - test: \'fail: return empty\'',
+
+        'apiVersion: v2.7\n' +
+        'enabled: true\n' +
+        'runtime: true\n' +
+        'force: true\n' +
+        'configs: \n' +
+        '  - addresses: [0.0.0.0]  # 0.0.0.0 for all addresses\n' +
+        '    side: consumer        # effective side, consumer or provider\n' +
+        '    parameters: \n' +
+        '      timeout: 6000       # dynamic config parameter\n',
       ruleText: '',
       readonly: false,
-      headers: [
+      serviceHeaders: [
         {
           text: 'Service Name',
           value: 'service',
@@ -146,6 +210,19 @@
           sortable: false,
           width: '115px'
         }
+      ],
+      appHeaders: [
+        {
+          text: 'Application Name',
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
       ]
     }),
     methods: {
@@ -153,16 +230,23 @@
         this.search(this.filter, true)
       },
       search: function (filter, rewrite) {
-        this.$axios.get('/rules/override', {
-          params: {
-            service: filter
-          }
-        }).then(response => {
-          this.configs = response.data
-          if (rewrite) {
-            this.$router.push({path: 'config', query: {service: filter}})
-          }
-        })
+        let type = this.items[this.selected].value
+        let url = '/rules/override/?' + type + '=' + filter
+        this.$axios.get(url)
+          .then(response => {
+            if (this.selected === 0) {
+              this.serviceConfigs = response.data
+            } else {
+              this.appConfigs = response.data
+            }
+            if (rewrite) {
+              if (this.selected === 0) {
+                this.$router.push({path: 'config', query: {serviceName: filter}})
+              } else if (this.selected === 1) {
+                this.$router.push({path: 'config', query: {application: filter}})
+              }
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -186,10 +270,11 @@
       },
       saveItem: function () {
         let override = yaml.safeLoad(this.ruleText)
-        if (this.service === '') {
+        if (this.service === '' && this.application === '') {
           return
         }
         override.service = this.service
+        override.application = this.application
         if (this.updateId !== '') {
           if (this.updateId === 'close') {
             this.closeDialog()
@@ -217,9 +302,15 @@
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = ''
+        if (this.selected === 0) {
+          itemId = item.service
+        } else {
+          itemId = item.application
+        }
         switch (icon) {
           case 'visibility':
-            this.$axios.get('/rules/override/' + item.id)
+            this.$axios.get('/rules/override/' + itemId)
               .then(response => {
                 let config = response.data
                 this.handleConfig(config, true)
@@ -227,32 +318,34 @@
               })
             break
           case 'edit':
-            this.$axios.get('/rules/override/' + item.id)
+            this.$axios.get('/rules/override/' + itemId)
               .then(response => {
                 let config = response.data
                 this.handleConfig(config, false)
-                this.updateId = item.id
+                this.updateId = itemId
               })
             break
           case 'block':
             this.openWarn(' Are you sure to block Dynamic Config', 'service: ' + item.service)
             this.warnStatus.operation = 'disable'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
             break
           case 'check_circle_outline':
             this.openWarn(' Are you sure to enable Dynamic Config', 'service: ' + item.service)
             this.warnStatus.operation = 'enable'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
             break
           case 'delete':
             this.openWarn(' Are you sure to Delete Dynamic Config', 'service: ' + item.service)
             this.warnStatus.operation = 'delete'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
         }
       },
       handleConfig: function (config, readonly) {
         this.service = config.service
+        this.application = config.application
         delete config.service
+        delete config.application
         delete config.id
         this.ruleText = yaml.safeDump(config)
         this.readonly = readonly
@@ -297,18 +390,29 @@
     created () {
       this.setHeight()
     },
+    computed: {
+      queryBy () {
+        return 'by ' + this.items[this.selected].title
+      }
+    },
     mounted: function () {
       this.ruleText = this.template
       let query = this.$route.query
-      let service = null
+      let filter = null
+      let vm = this
       Object.keys(query).forEach(function (key) {
         if (key === 'service') {
-          service = query[key]
+          filter = query[key]
+          vm.selected = 0
+        }
+        if (key === 'application') {
+          filter = query[key]
+          vm.selected = 1
         }
       })
-      if (service !== null) {
-        this.filter = service
-        this.search(service, false)
+      if (filter !== null) {
+        this.filter = filter
+        this.search(filter, false)
       }
     }
   }
diff --git a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue b/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
index 6a3f279..7ebf979 100644
--- a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
+++ b/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
@@ -18,11 +18,42 @@
 <template>
   <v-container grid-list-xl fluid >
       <v-layout row wrap>
-        <v-flex xs12 >
-          <search v-model="filter" :submit="submit" label="Search Routing Rule by service name"></search>
+        <v-flex lg12>
+          <v-card flat color="transparent">
+            <v-card-text>
+              <v-form>
+                <v-layout row wrap>
+                  <v-combobox
+                    id="serviceSearch"
+                    v-model="filter"
+                    flat
+                    append-icon=""
+                    hide-no-data
+                    :suffix="queryBy"
+                    label="Search Routing Rule"
+                  ></v-combobox>
+                  <v-menu class="hidden-xs-only">
+                    <v-btn slot="activator" large icon>
+                      <v-icon>unfold_more</v-icon>
+                    </v-btn>
+
+                    <v-list>
+                      <v-list-tile
+                        v-for="(item, i) in items"
+                        :key="i"
+                        @click="selected = i">
+                        <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      </v-list-tile>
+                    </v-list>
+                  </v-menu>
+                  <v-btn @click="submit" color="primary" large>Search</v-btn>
+
+                </v-layout>
+              </v-form>
+            </v-card-text>
+          </v-card>
         </v-flex>
       </v-layout>
-
     <v-flex lg12>
       <v-card>
         <v-toolbar flat color="transparent" class="elevation-0">
@@ -31,10 +62,10 @@
           <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
         </v-toolbar>
 
-        <v-card-text class="pa-0">
+        <v-card-text class="pa-0" v-if="selected == 0">
           <v-data-table
-            :headers="headers"
-            :items="routingRules"
+            :headers="serviceHeaders"
+            :items="serviceRoutingRules"
             hide-actions
             class="elevation-0"
           >
@@ -54,6 +85,28 @@
             </template>
           </v-data-table>
         </v-card-text>
+        <v-card-text class="pa-0" v-if="selected == 1">
+          <v-data-table
+            :headers="appHeaders"
+            :items="appRoutingRules"
+            hide-actions
+            class="elevation-0"
+          >
+            <template slot="items" slot-scope="props">
+              <td class="text-xs-left">{{ props.item.application }}</td>
+              <td class="text-xs-left">{{ props.item.priority }}</td>
+              <td class="text-xs-left">{{ props.item.enabled }}</td>
+              <td class="text-xs-center px-0">
+                <v-tooltip bottom v-for="op in operations" :key="op.id">
+                  <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon(props.item), props.item)">
+                    {{op.icon(props.item)}}
+                  </v-icon>
+                  <span>{{op.tooltip(props.item)}}</span>
+                </v-tooltip>
+              </td>
+            </template>
+          </v-data-table>
+        </v-card-text>
       </v-card>
     </v-flex>
 
@@ -66,7 +119,6 @@
           <v-text-field
             label="Service Unique ID"
             hint="A service ID in form of group/service:version, group and version are optional"
-            :rules="[required]"
             v-model="service"
           ></v-text-field>
           <v-text-field
@@ -105,14 +157,17 @@
 <script>
   import yaml from 'js-yaml'
   import AceEditor from '@/components/public/AceEditor'
-  import Search from '@/components/public/Search'
   import operations from '@/api/operation'
   export default {
     components: {
-      AceEditor,
-      Search
+      AceEditor
     },
     data: () => ({
+      items: [
+        {id: 0, title: 'service name', value: 'serviceName'},
+        {id: 1, title: 'application', value: 'application'}
+      ],
+      selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
       ruleKeys: ['enabled', 'force', 'dynamic', 'runtime', 'group', 'version', 'rule', 'priority'],
       pattern: 'Service',
@@ -127,24 +182,44 @@
       warnStatus: {},
       height: 0,
       operations: operations,
-      routingRules: [
+      serviceRoutingRules: [
+      ],
+      appRoutingRules: [
       ],
       required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
       template:
-        'enabled: true/false\n' +
-        'priority:\n' +
-        'runtime: false/true\n' +
-        'force: true/false\n' +
-        'dynamic: true/false\n' +
+        'enabled: true\n' +
+        'priority: 100\n' +
+        'runtime: false\n' +
+        'force: true\n' +
         'conditions:\n' +
-        ' - \'=> host != 172.22.3.91\'\n' +
-        ' - \'host != 10.20.153.10,10.20.153.11 =>\'\n' +
-        ' - \'host = 10.20.153.10,10.20.153.11 =>\'\n' +
-        ' - \'application != kylin => host != 172.22.3.95,172.22.3.96\'\n' +
-        ' - \'method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96\'',
+        ' - \'=> host != 172.22.3.91\'\n',
       ruleText: '',
       readonly: false,
-      headers: [
+      appHeaders: [
+        {
+          text: 'Application Name',
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: 'Priority',
+          value: 'priority',
+          sortable: false
+        },
+        {
+          text: 'Enabled',
+          value: 'enabled',
+          sortable: false
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
+      ],
+      serviceHeaders: [
         {
           text: 'Service Name',
           value: 'service',
@@ -179,16 +254,23 @@
         this.search(this.filter, true)
       },
       search: function (filter, rewrite) {
-        this.$axios.get('/rules/route/', {
-          params: {
-            service: filter
-          }
-        }).then(response => {
-          this.routingRules = response.data
-          if (rewrite) {
-            this.$router.push({path: 'routingRule', query: {service: filter}})
-          }
-        })
+        let type = this.items[this.selected].value
+        let url = '/rules/route/condition/?' + type + '=' + filter
+        this.$axios.get(url)
+          .then(response => {
+            if (this.selected === 0) {
+              this.serviceRoutingRules = response.data
+            } else {
+              this.appRoutingRules = response.data
+            }
+            if (rewrite) {
+              if (this.selected === 0) {
+                this.$router.push({path: 'routingRule', query: {serviceName: filter}})
+              } else if (this.selected === 1) {
+                this.$router.push({path: 'routingRule', query: {application: filter}})
+              }
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -213,16 +295,17 @@
       },
       saveItem: function () {
         let rule = yaml.safeLoad(this.ruleText)
-        if (rule.service === '') {
+        if (this.service === '' && this.application === '') {
           return
         }
         rule.service = this.service
+        rule.application = this.application
         if (this.updateId !== '') {
           if (this.updateId === 'close') {
             this.closeDialog()
           } else {
             rule.id = this.updateId
-            this.$axios.put('/rules/route/' + rule.id, rule)
+            this.$axios.put('/rules/route/condition' + rule.id, rule)
               .then(response => {
                 if (response.status === 200) {
                   this.search(this.service, true)
@@ -232,7 +315,7 @@
               })
           }
         } else {
-          this.$axios.post('/rules/route/', rule)
+          this.$axios.post('/rules/route/condition/', rule)
             .then(response => {
               if (response.status === 201) {
                 this.search(this.service, true)
@@ -247,48 +330,56 @@
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = ''
+        if (this.selected === 0) {
+          itemId = item.service
+        } else {
+          itemId = item.application
+        }
         switch (icon) {
           case 'visibility':
-            this.$axios.get('/rules/route/' + item.id)
+            this.$axios.get('/rules/route/condition/' + itemId)
               .then(response => {
-                let route = response.data
-                this.handleBalance(route, true)
+                let conditionRoute = response.data
+                this.handleBalance(conditionRoute, true)
                 this.updateId = 'close'
               })
             break
           case 'edit':
             let id = {}
-            id.id = item.id
-            this.$axios.get('/rules/route/' + item.id)
+            id.id = itemId
+            this.$axios.get('/rules/route/condition/' + itemId)
               .then(response => {
-                let route = response.data
-                this.handleBalance(route, false)
-                this.updateId = item.id
+                let conditionRoute = response.data
+                this.handleBalance(conditionRoute, false)
+                this.updateId = itemId
               })
             break
           case 'block':
             this.openWarn(' Are you sure to block Routing Rule', 'service: ' + item.service)
             this.warnStatus.operation = 'disable'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
             break
           case 'check_circle_outline':
             this.openWarn(' Are you sure to enable Routing Rule', 'service: ' + item.service)
             this.warnStatus.operation = 'enable'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
             break
           case 'delete':
             this.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + item.service)
             this.warnStatus.operation = 'delete'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
         }
       },
-      handleBalance: function (route, readonly) {
-        this.service = route.service
-        delete route.service
-        delete route.id
-        delete route.app
-        delete route.group
-        this.ruleText = yaml.safeDump(route)
+      handleBalance: function (conditionRoute, readonly) {
+        this.service = conditionRoute.service
+        this.application = conditionRoute.application
+        delete conditionRoute.service
+        delete conditionRoute.id
+        delete conditionRoute.app
+        delete conditionRoute.group
+        delete conditionRoute.application
+        this.ruleText = yaml.safeDump(conditionRoute)
         this.readonly = readonly
         this.dialog = true
       },
@@ -299,7 +390,7 @@
         let id = warnStatus.id
         let operation = warnStatus.operation
         if (operation === 'delete') {
-          this.$axios.delete('/rules/route/' + id)
+          this.$axios.delete('/rules/route/condition/' + id)
             .then(response => {
               if (response.status === 200) {
                 this.warn = false
@@ -308,7 +399,7 @@
               }
             })
         } else if (operation === 'disable') {
-          this.$axios.put('/rules/route/disable/' + id)
+          this.$axios.put('/rules/route/condition/disable/' + id)
             .then(response => {
               if (response.status === 200) {
                 this.warn = false
@@ -317,7 +408,7 @@
               }
             })
         } else if (operation === 'enable') {
-          this.$axios.put('/rules/route/enable/' + id)
+          this.$axios.put('/rules/route/condition/enable/' + id)
             .then(response => {
               if (response.status === 200) {
                 this.warn = false
@@ -331,18 +422,29 @@
     created () {
       this.setHeight()
     },
+    computed: {
+      queryBy () {
+        return 'by ' + this.items[this.selected].title
+      }
+    },
     mounted: function () {
       this.ruleText = this.template
       let query = this.$route.query
-      let service = null
+      let filter = null
+      let vm = this
       Object.keys(query).forEach(function (key) {
         if (key === 'service') {
-          service = query[key]
+          filter = query[key]
+          vm.selected = 0
+        }
+        if (key === 'application') {
+          filter = query[key]
+          vm.selected = 1
         }
       })
-      if (service !== null) {
-        this.filter = service
-        this.search(service, false)
+      if (filter !== null) {
+        this.filter = filter
+        this.search(filter, false)
       }
     }
 
diff --git a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue b/dubbo-admin-frontend/src/components/governance/TagRule.vue
similarity index 78%
copy from dubbo-admin-frontend/src/components/governance/RoutingRule.vue
copy to dubbo-admin-frontend/src/components/governance/TagRule.vue
index 6a3f279..9e08eee 100644
--- a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
+++ b/dubbo-admin-frontend/src/components/governance/TagRule.vue
@@ -17,12 +17,11 @@
 
 <template>
   <v-container grid-list-xl fluid >
-      <v-layout row wrap>
-        <v-flex xs12 >
-          <search v-model="filter" :submit="submit" label="Search Routing Rule by service name"></search>
-        </v-flex>
-      </v-layout>
-
+    <v-layout row wrap>
+      <v-flex xs12 >
+        <search v-model="filter" :submit="submit" label="Search Routing Rule by service name"></search>
+      </v-flex>
+    </v-layout>
     <v-flex lg12>
       <v-card>
         <v-toolbar flat color="transparent" class="elevation-0">
@@ -31,10 +30,10 @@
           <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
         </v-toolbar>
 
-        <v-card-text class="pa-0">
+        <v-card-text class="pa-0" >
           <v-data-table
             :headers="headers"
-            :items="routingRules"
+            :items="tagRoutingRules"
             hide-actions
             class="elevation-0"
           >
@@ -66,7 +65,6 @@
           <v-text-field
             label="Service Unique ID"
             hint="A service ID in form of group/service:version, group and version are optional"
-            :rules="[required]"
             v-model="service"
           ></v-text-field>
           <v-text-field
@@ -105,8 +103,9 @@
 <script>
   import yaml from 'js-yaml'
   import AceEditor from '@/components/public/AceEditor'
-  import Search from '@/components/public/Search'
   import operations from '@/api/operation'
+  import Search from '@/components/public/Search'
+
   export default {
     components: {
       AceEditor,
@@ -127,34 +126,26 @@
       warnStatus: {},
       height: 0,
       operations: operations,
-      routingRules: [
+      tagRoutingRules: [
       ],
       required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
       template:
-        'enabled: true/false\n' +
-        'priority:\n' +
-        'runtime: false/true\n' +
-        'force: true/false\n' +
-        'dynamic: true/false\n' +
-        'conditions:\n' +
-        ' - \'=> host != 172.22.3.91\'\n' +
-        ' - \'host != 10.20.153.10,10.20.153.11 =>\'\n' +
-        ' - \'host = 10.20.153.10,10.20.153.11 =>\'\n' +
-        ' - \'application != kylin => host != 172.22.3.95,172.22.3.96\'\n' +
-        ' - \'method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96\'',
+        'force: false\n' +
+        'enabled: true\n' +
+        'runtime: false\n' +
+        'priority: 100\n' +
+        'tags:\n' +
+        ' - name: tag1\n' +
+        '   addresses: [192.168.0.1:20881]\n' +
+        ' - name: tag2\n' +
+        '   addresses: [192.168.0.2:20882]\n',
       ruleText: '',
       readonly: false,
       headers: [
         {
-          text: 'Service Name',
-          value: 'service',
-          align: 'left'
-        },
-        {
-          text: 'Group',
-          value: 'group',
+          text: 'Application Name',
+          value: 'application',
           align: 'left'
-
         },
         {
           text: 'Priority',
@@ -179,16 +170,14 @@
         this.search(this.filter, true)
       },
       search: function (filter, rewrite) {
-        this.$axios.get('/rules/route/', {
-          params: {
-            service: filter
-          }
-        }).then(response => {
-          this.routingRules = response.data
-          if (rewrite) {
-            this.$router.push({path: 'routingRule', query: {service: filter}})
-          }
-        })
+        let url = '/rules/route/tag/?application' + '=' + filter
+        this.$axios.get(url)
+          .then(response => {
+            this.tagRoutingRules = response.data
+            if (rewrite) {
+              this.$router.push({path: 'routingRule', query: {application: filter}})
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -213,16 +202,17 @@
       },
       saveItem: function () {
         let rule = yaml.safeLoad(this.ruleText)
-        if (rule.service === '') {
+        if (this.service === '' && this.application === '') {
           return
         }
         rule.service = this.service
+        rule.application = this.application
         if (this.updateId !== '') {
           if (this.updateId === 'close') {
             this.closeDialog()
           } else {
             rule.id = this.updateId
-            this.$axios.put('/rules/route/' + rule.id, rule)
+            this.$axios.put('/rules/route/tag/' + rule.id, rule)
               .then(response => {
                 if (response.status === 200) {
                   this.search(this.service, true)
@@ -232,7 +222,7 @@
               })
           }
         } else {
-          this.$axios.post('/rules/route/', rule)
+          this.$axios.post('/rules/route/tag/', rule)
             .then(response => {
               if (response.status === 201) {
                 this.search(this.service, true)
@@ -247,48 +237,51 @@
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = item.application
         switch (icon) {
           case 'visibility':
-            this.$axios.get('/rules/route/' + item.id)
+            this.$axios.get('/rules/route/tag/' + itemId)
               .then(response => {
-                let route = response.data
-                this.handleBalance(route, true)
+                let conditionRoute = response.data
+                this.handleBalance(conditionRoute, true)
                 this.updateId = 'close'
               })
             break
           case 'edit':
             let id = {}
-            id.id = item.id
-            this.$axios.get('/rules/route/' + item.id)
+            id.id = itemId
+            this.$axios.get('/rules/route/tag/' + itemId)
               .then(response => {
-                let route = response.data
-                this.handleBalance(route, false)
-                this.updateId = item.id
+                let conditionRoute = response.data
+                this.handleBalance(conditionRoute, false)
+                this.updateId = itemId
               })
             break
           case 'block':
             this.openWarn(' Are you sure to block Routing Rule', 'service: ' + item.service)
             this.warnStatus.operation = 'disable'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
             break
           case 'check_circle_outline':
             this.openWarn(' Are you sure to enable Routing Rule', 'service: ' + item.service)
             this.warnStatus.operation = 'enable'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
             break
           case 'delete':
             this.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + item.service)
             this.warnStatus.operation = 'delete'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
         }
       },
-      handleBalance: function (route, readonly) {
-        this.service = route.service
-        delete route.service
-        delete route.id
-        delete route.app
-        delete route.group
-        this.ruleText = yaml.safeDump(route)
+      handleBalance: function (conditionRoute, readonly) {
+        this.service = conditionRoute.service
+        this.application = conditionRoute.application
+        delete conditionRoute.service
+        delete conditionRoute.id
+        delete conditionRoute.app
+        delete conditionRoute.group
+        delete conditionRoute.application
+        this.ruleText = yaml.safeDump(conditionRoute)
         this.readonly = readonly
         this.dialog = true
       },
@@ -299,7 +292,7 @@
         let id = warnStatus.id
         let operation = warnStatus.operation
         if (operation === 'delete') {
-          this.$axios.delete('/rules/route/' + id)
+          this.$axios.delete('/rules/tag/' + id)
             .then(response => {
               if (response.status === 200) {
                 this.warn = false
@@ -308,7 +301,7 @@
               }
             })
         } else if (operation === 'disable') {
-          this.$axios.put('/rules/route/disable/' + id)
+          this.$axios.put('/rules/tag/disable/' + id)
             .then(response => {
               if (response.status === 200) {
                 this.warn = false
@@ -317,7 +310,7 @@
               }
             })
         } else if (operation === 'enable') {
-          this.$axios.put('/rules/route/enable/' + id)
+          this.$axios.put('/rules/tag/enable/' + id)
             .then(response => {
               if (response.status === 200) {
                 this.warn = false
@@ -334,15 +327,16 @@
     mounted: function () {
       this.ruleText = this.template
       let query = this.$route.query
-      let service = null
+      let filter = null
+      let vm = this
       Object.keys(query).forEach(function (key) {
-        if (key === 'service') {
-          service = query[key]
+        if (key === 'application') {
+          filter = query[key]
         }
       })
-      if (service !== null) {
-        this.filter = service
-        this.search(service, false)
+      if (filter !== null) {
+        this.filter = filter
+        this.search(filter, false)
       }
     }
 
diff --git a/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue b/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
index 0112c22..e936bb8 100644
--- a/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
+++ b/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
@@ -68,6 +68,11 @@
             :rules="[required]"
             v-model="service"
           ></v-text-field>
+          <v-text-field
+            label="Application Name"
+            hint="Application name the service belongs to"
+            v-model="application"
+          ></v-text-field>
           <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
 
           <ace-editor v-model="ruleText" :readonly="readonly"></ace-editor>
@@ -272,7 +277,7 @@
     },
     mounted: function () {
       this.ruleText = this.template
-      let query = this.$route.query
+      let query = this.$conditionRoute.query
       let service = null
       Object.keys(query).forEach(function (key) {
         if (key === 'service') {
diff --git a/dubbo-admin-frontend/src/router/index.js b/dubbo-admin-frontend/src/router/index.js
index 86d1026..38dc6f0 100644
--- a/dubbo-admin-frontend/src/router/index.js
+++ b/dubbo-admin-frontend/src/router/index.js
@@ -20,6 +20,7 @@ import Router from 'vue-router'
 import ServiceSearch from '@/components/ServiceSearch'
 import ServiceDetail from '@/components/ServiceDetail'
 import RoutingRule from '@/components/governance/RoutingRule'
+import TagRule from '@/components/governance/TagRule'
 import AccessControl from '@/components/governance/AccessControl'
 import LoadBalance from '@/components/governance/LoadBalance'
 import WeightAdjust from '@/components/governance/WeightAdjust'
@@ -45,6 +46,11 @@ export default new Router({
       component: RoutingRule
     },
     {
+      path: '/governance/tagRule',
+      name: 'TagRule',
+      component: TagRule
+    },
+    {
       path: '/governance/access',
       name: 'AccessControl',
       component: AccessControl
diff --git a/pom.xml b/pom.xml
index 2fb41e1..c87b23f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,11 +64,17 @@
 		<jacoco-version>0.8.2</jacoco-version>
 		<jedis-version>2.9.0</jedis-version>
         <apollo-version>1.1.2</apollo-version>
+		<snakeyaml-version>1.19</snakeyaml-version>
 	</properties>
 
 	<dependencyManagement>
         <dependencies>
 			<dependency>
+				<groupId>org.yaml</groupId>
+				<artifactId>snakeyaml</artifactId>
+				<version>${snakeyaml-version}</version>
+			</dependency>
+			<dependency>
 				<groupId>redis.clients</groupId>
 				<artifactId>jedis</artifactId>
 				<version>${jedis-version}</version>