Merge branch 'develop' of github.com:apache/incubator-dubbo-ops into develop
diff --git a/README.md b/README.md
index 30b4081..fe04835 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,8 @@
 ### Backend
 
 * Standard spring boot project
+* **NOTICE** this branch is based on Dubbo 2.7-SNAPSHOT, since this version is not published yet, so if you find a dependency error, please clear the dubbo2.7 related files in the local library
+* force update under root path(incubator-dubbo-ops) for the first building: `mvn -Dmaven.test.skip=true clean -U package`
 
 
 ### Production Setup
diff --git a/README_ZH.md b/README_ZH.md
index fe448c4..0ff5d76 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -19,7 +19,9 @@
 
 ### 后端部分
 
-* 标准spring boot工程  
+* 标准spring boot工程
+* **注意** 本分支依赖Dubbo2.7-SNAPSHOT版本,该Dubbo版本还未正式发布,因此如果发现依赖方面的错误,请清空本地库中的dubbo2.7相关文件
+* 在项目根目录(incubator-dubbo-ops)第一次构建需要强制更新: `mvn -Dmaven.test.skip=true clean -U package`   
 
 
 ### 生产环境配置  
diff --git a/dubbo-admin-backend/README.md b/dubbo-admin-backend/README.md
new file mode 100644
index 0000000..49d5c21
--- /dev/null
+++ b/dubbo-admin-backend/README.md
@@ -0,0 +1,6 @@
+## Dubbo Admin后端配置
+当前版本的的Dubbo Aadmin支持Dubbo2.7的新特性(元数据展示,应用级别的配置),同时也兼容Dubbo2.6的用法,两个版本的配置不同,具体介绍如下:  
+* application.properties配置
+  * dubbo.config.center: 2.7的配置,推荐用法,填写配置中心的地址,并且在配置中心的相应目录下配置注册中心和元数据中心的地址,Dubbo Admin会根据相应的协议,初始化对应的客户端,实现对配置中心,元数据中心的访问
+  * dubbo.registry.address: 2.6的配置,只配置注册中心的地址。采用此配置,Dubbo Admin会把配置,元数据相关的内容也写入注册中心的不同目录下
+  * 两种配置,都可以兼容Dubbo2.6和2.7的版本,即使配置了dubbo.config.center,对于2.6版本的客户端,也会收到对应版本的路由,动态配置规则,并且按照规则内容生效
diff --git a/dubbo-admin-backend/pom.xml b/dubbo-admin-backend/pom.xml
index 0cf43c5..7986fbd 100644
--- a/dubbo-admin-backend/pom.xml
+++ b/dubbo-admin-backend/pom.xml
@@ -53,14 +53,28 @@
         </dependency>
 
         <dependency>
-            <groupId>com.alibaba</groupId>
+            <groupId>redis.clients</groupId>
+            <artifactId>jedis</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ctrip.framework.apollo</groupId>
+            <artifactId>apollo-openapi</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.yaml</groupId>
+            <artifactId>snakeyaml</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>netty</artifactId>
-                    <groupId>org.jboss.netty</groupId>
-                </exclusion>
-            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-metadata-report-api</artifactId>
         </dependency>
 
         <dependency>
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java
index fe4d601..11be510 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/DubboAdminApplication.java
@@ -26,7 +26,6 @@
 
 	public static void main(String[] args) {
 		ApplicationContext act = SpringApplication.run(DubboAdminApplication.class, args);
-		SpringUtil.setApplicationContext(act);
 
 
 	}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/SpringUtil.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/SpringUtil.java
deleted file mode 100644
index 237f6a7..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/SpringUtil.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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;
-
-
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import org.springframework.context.ApplicationContext;
-
-public class SpringUtil {
-
-    public static final Logger logger = LoggerFactory.getLogger(SpringUtil.class);
-    private static ApplicationContext applicationContext = null;
-
-    public static void setApplicationContext(ApplicationContext applicationContext){
-        if(SpringUtil.applicationContext == null){
-            logger.info("set applicationcontext");
-            SpringUtil.applicationContext  = applicationContext;
-        }
-
-    }
-
-    //获取applicationContext
-    public static ApplicationContext getApplicationContext() {
-        return applicationContext;
-    }
-
-    //通过name获取 Bean.
-    public static Object getBean(String name){
-        return getApplicationContext().getBean(name);
-
-    }
-
-    //通过class获取Bean.
-    public static <T> T getBean(Class<T> clazz){
-        return getApplicationContext().getBean(clazz);
-    }
-
-    //通过name,以及Clazz返回指定的Bean
-    public static <T> T getBean(String name,Class<T> clazz){
-        return getApplicationContext().getBean(name, clazz);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/ChangeListener.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/exception/ConfigurationException.java
similarity index 79%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/ChangeListener.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/exception/ConfigurationException.java
index 661f146..89fbb0b 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/ChangeListener.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/exception/ConfigurationException.java
@@ -14,15 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common;
 
-public interface ChangeListener {
+package org.apache.dubbo.admin.common.exception;
 
-    /**
-     * Invoked when data changed
-     *
-     * @param type     data type
-     */
-    void onChanged(String type);
+public class ConfigurationException extends RuntimeException{
 
+    public ConfigurationException(String message) {
+        super(message);
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BaseDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/exception/VersionValidationException.java
similarity index 69%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BaseDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/exception/VersionValidationException.java
index 3bb2252..a660948 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BaseDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/exception/VersionValidationException.java
@@ -14,21 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.dto;
 
-/**
- * BaseDTO
- *
- * For receive ID parameter with @RequestBody
- */
-public abstract class BaseDTO {
-    private String id;
+package org.apache.dubbo.admin.common.exception;
 
-    public String getId() {
-        return id;
-    }
 
-    public void setId(String id) {
-        this.id = id;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(value = HttpStatus.BAD_REQUEST)
+public class VersionValidationException extends SystemException{
+
+    public VersionValidationException(String message) {
+        super(message);
     }
 }
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
new file mode 100644
index 0000000..6d54b0a
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -0,0 +1,51 @@
+/*
+ * 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 java.util.HashSet;
+import java.util.Set;
+
+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 PROVIDER_SIDE = "provider";
+    public static final String CONSUMER_SIDE = "consumer";
+    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 CONFIGURATOR = "configurators";
+    public static final String TAG_ROUTE = "tag_route";
+    public static final String COMPATIBLE_CONFIG = "compatible_config";
+    public static final String WEIGHT = "weight";
+    public static final String BALANCING = "balancing";
+    public static final String SERVICE = "service";
+    public static final String APPLICATION = "application";
+    public static final Set<String> CONFIGS = new HashSet<>();
+
+    static {
+        CONFIGS.add(WEIGHT);
+        CONFIGS.add(BALANCING);
+    }
+
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ConvertUtil.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ConvertUtil.java
new file mode 100644
index 0000000..d7b85d4
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ConvertUtil.java
@@ -0,0 +1,98 @@
+/*
+ * 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.dto.BaseDTO;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.utils.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ConvertUtil {
+    private ConvertUtil() {
+    }
+
+    public static Map<String, String> serviceName2Map(String serviceName) {
+        String group = null;
+        String version = null;
+        int i = serviceName.indexOf("/");
+        if (i > 0) {
+            group = serviceName.substring(0, i);
+            serviceName = serviceName.substring(i + 1);
+        }
+        i = serviceName.lastIndexOf(":");
+        if (i > 0) {
+            version = serviceName.substring(i + 1);
+            serviceName = serviceName.substring(0, i);
+        }
+
+        Map<String, String> ret = new HashMap<String, String>();
+        if (!StringUtils.isEmpty(serviceName)) {
+            ret.put(Constants.INTERFACE_KEY, serviceName);
+        }
+        if (!StringUtils.isEmpty(version)) {
+            ret.put(Constants.VERSION_KEY, version);
+        }
+        if (!StringUtils.isEmpty(group)) {
+            ret.put(Constants.GROUP_KEY, group);
+        }
+
+        return ret;
+    }
+
+    public static String getIdFromDTO(BaseDTO baseDTO) {
+        String id;
+        if (StringUtils.isNotEmpty(baseDTO.getApplication())) {
+            id = baseDTO.getApplication();
+        } else {
+            id = baseDTO.getService();
+        }
+        return id;
+    }
+
+    public static String getScopeFromDTO(BaseDTO baseDTO) {
+        if (StringUtils.isNotEmpty(baseDTO.getApplication())) {
+            return org.apache.dubbo.admin.common.util.Constants.APPLICATION;
+        } else {
+            return org.apache.dubbo.admin.common.util.Constants.SERVICE;
+        }
+    }
+
+//    public static <T extends BaseDTO> T convertDTOtoStore(T dto) {
+//        if (StringUtils.isNotEmpty(dto.getApplication())) {
+//            dto.setScope("application");
+//            dto.setKey(dto.getApplication());
+//        } else {
+//            dto.setScope("service");
+//            dto.setKey(dto.getService());
+//        }
+//        return dto;
+//    }
+//
+//    public static <T extends BaseDTO> T convertDTOtoDisplay(T dto) {
+//        if (dto == null) {
+//            return null;
+//        }
+//        if(dto.getScope().equals("application")) {
+//            dto.setApplication(dto.getKey());
+//        } else {
+//            dto.setService(dto.getKey());
+//        }
+//        return dto;
+//    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/util/MD5Util.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/util/MD5Util.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
index bc6e561..a44a849 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/util/MD5Util.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.util;
+package org.apache.dubbo.admin.common.util;
 
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
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
new file mode 100644
index 0000000..cdad836
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/OverrideUtils.java
@@ -0,0 +1,233 @@
+/*
+ * 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.*;
+import org.apache.dubbo.admin.model.domain.Override;
+import org.apache.dubbo.admin.model.dto.BalancingDTO;
+import org.apache.dubbo.admin.model.dto.DynamicConfigDTO;
+import org.apache.dubbo.admin.model.dto.WeightDTO;
+import org.apache.dubbo.admin.model.store.OverrideConfig;
+import org.apache.dubbo.admin.model.store.OverrideDTO;
+import org.apache.dubbo.common.utils.StringUtils;
+
+import java.util.*;
+
+/**
+ * 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 OverrideConfig weightDTOtoConfig(WeightDTO weightDTO) {
+        OverrideConfig overrideConfig = new OverrideConfig();
+        overrideConfig.setType(Constants.WEIGHT);
+        overrideConfig.setEnabled(true);
+        overrideConfig.setSide(Constants.PROVIDER_SIDE);
+        overrideConfig.setAddresses(weightDTO.getAddresses());
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put(Constants.WEIGHT, weightDTO.getWeight());
+        overrideConfig.setParameters(parameters);
+        return overrideConfig;
+    }
+
+    public static DynamicConfigDTO createFromOverride(OverrideDTO overrideDTO) {
+        DynamicConfigDTO dynamicConfigDTO = new DynamicConfigDTO();
+        dynamicConfigDTO.setConfigVersion(overrideDTO.getConfigVersion());
+        List<OverrideConfig> configs = new ArrayList<>();
+        for (OverrideConfig overrideConfig : overrideDTO.getConfigs()) {
+            if (overrideConfig.getType() == null) {
+                configs.add(overrideConfig);
+            }
+        }
+        if (configs.size() == 0) {
+            return null;
+        }
+        dynamicConfigDTO.setConfigs(configs);
+        if (overrideDTO.getScope().equals(Constants.APPLICATION)) {
+            dynamicConfigDTO.setApplication(overrideDTO.getKey());
+        } else {
+            dynamicConfigDTO.setService(overrideDTO.getKey());
+        }
+        dynamicConfigDTO.setEnabled(overrideDTO.isEnabled());
+        return dynamicConfigDTO;
+    }
+    public static OverrideDTO createFromDynamicConfig(DynamicConfigDTO dynamicConfigDTO) {
+        OverrideDTO overrideDTO = new OverrideDTO();
+        if (StringUtils.isNotEmpty(dynamicConfigDTO.getApplication())) {
+            overrideDTO.setScope(Constants.APPLICATION);
+            overrideDTO.setKey(dynamicConfigDTO.getApplication());
+        } else {
+            overrideDTO.setScope(Constants.SERVICE);
+            overrideDTO.setKey(dynamicConfigDTO.getService());
+        }
+        overrideDTO.setConfigVersion(dynamicConfigDTO.getConfigVersion());
+        overrideDTO.setConfigs(dynamicConfigDTO.getConfigs());
+        return overrideDTO;
+    }
+
+    public static OverrideConfig balanceDTOtoConfig(BalancingDTO balancingDTO) {
+        OverrideConfig overrideConfig = new OverrideConfig();
+        overrideConfig.setType(Constants.BALANCING);
+        overrideConfig.setEnabled(true);
+        overrideConfig.setSide(Constants.CONSUMER_SIDE);
+        Map<String, Object> parameters = new HashMap<>();
+        if (balancingDTO.getMethodName().equals("*")) {
+            parameters.put("loadbalance", balancingDTO.getStrategy());
+        } else {
+            parameters.put(balancingDTO.getMethodName() + ".loadbalance", balancingDTO.getStrategy());
+        }
+        overrideConfig.setParameters(parameters);
+        return overrideConfig;
+    }
+
+    public static WeightDTO configtoWeightDTO(OverrideConfig config, String scope, String key) {
+        WeightDTO weightDTO = new WeightDTO();
+        if (scope.equals(Constants.APPLICATION)) {
+            weightDTO.setApplication(key);
+        } else {
+            weightDTO.setService(key);
+        }
+        weightDTO.setWeight((int)config.getParameters().get(Constants.WEIGHT));
+        weightDTO.setAddresses(config.getAddresses());
+        return weightDTO;
+    }
+
+    public static BalancingDTO configtoBalancingDTO(OverrideConfig config, String scope, String key) {
+        BalancingDTO balancingDTO = new BalancingDTO();
+        if (scope.equals(Constants.APPLICATION)) {
+            balancingDTO.setApplication(key);
+        } else {
+            balancingDTO.setService(key);
+        }
+        for (Map.Entry<String, Object> entry : config.getParameters().entrySet()) {
+            String k = entry.getKey();
+            String method;
+            if (k.contains(".")) {
+                method = k.split("\\.")[0];
+            } else {
+                method = "*";
+            }
+            balancingDTO.setMethodName(method);
+            balancingDTO.setStrategy((String)entry.getValue());
+        }
+        return balancingDTO;
+    }
+
+    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<>();
+        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/governance/sync/util/Pair.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Pair.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/util/Pair.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Pair.java
index 872df67..0910118 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/util/Pair.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Pair.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.sync.util;
+package org.apache.dubbo.admin.common.util;
 
 import java.util.Map;
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/ParseUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ParseUtils.java
similarity index 98%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/ParseUtils.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ParseUtils.java
index 53f3cac..13035db 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/ParseUtils.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/ParseUtils.java
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.route;
+package org.apache.dubbo.admin.common.util;
 
-import com.alibaba.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.utils.StringUtils;
 
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteRule.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
similarity index 73%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteRule.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
index ab8f3f7..7c48e14 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteRule.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
@@ -14,10 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.route;
+package org.apache.dubbo.admin.common.util;
 
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.registry.common.domain.Route;
+import org.apache.dubbo.admin.model.domain.Route;
+import org.apache.dubbo.admin.model.dto.AccessDTO;
+import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
+import org.apache.dubbo.admin.model.dto.TagRouteDTO;
+import org.apache.dubbo.admin.model.store.BlackWhiteList;
+import org.apache.dubbo.admin.model.store.RoutingRule;
+import org.apache.dubbo.admin.model.store.TagRoute;
+import org.apache.dubbo.common.utils.StringUtils;
 
 import java.text.ParseException;
 import java.util.*;
@@ -33,7 +39,7 @@
  * 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>
+ * 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>
@@ -143,15 +149,15 @@
      * <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);
+    public static RouteRule parse(Route conditionRoute) throws ParseException {
+        if (conditionRoute == null)
+            throw new ParseException("null conditionRoute!", 0);
 
-        if (route.getMatchRule() == null && route.getFilterRule() == null) {
-            return parse(route.getRule());
+        if (conditionRoute.getMatchRule() == null && conditionRoute.getFilterRule() == null) {
+            return parse(conditionRoute.getRule());
         }
 
-        return parse(route == null ? null : route.getMatchRule(), route == null ? null : route.getFilterRule());
+        return parse(conditionRoute == null ? null : conditionRoute.getMatchRule(), conditionRoute == null ? null : conditionRoute.getFilterRule());
     }
 
     public static RouteRule parse(String whenRule, String thenRule) throws ParseException {
@@ -181,14 +187,162 @@
      * @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) {
+    public static RouteRule parseQuitely(Route conditionRoute) {
         try {
-            return parse(route);
+            return parse(conditionRoute);
         } catch (ParseException e) {
             throw new RuntimeException(e);
         }
     }
 
+    public static TagRoute convertTagroutetoStore(TagRouteDTO tagRoute) {
+        TagRoute store = new TagRoute();
+        store.setKey(tagRoute.getApplication());
+        store.setEnabled(tagRoute.isEnabled());
+        store.setForce(tagRoute.isForce());
+        store.setPriority(tagRoute.getPriority());
+        store.setRuntime(tagRoute.isRuntime());
+        store.setTags(tagRoute.getTags());
+        return store;
+    }
+
+    public static TagRouteDTO convertTagroutetoDisplay(TagRoute tagRoute) {
+        TagRouteDTO tagRouteDTO = new TagRouteDTO();
+        tagRouteDTO.setApplication(tagRoute.getKey());
+        tagRouteDTO.setRuntime(tagRoute.isRuntime());
+        tagRouteDTO.setPriority(tagRoute.getPriority());
+        tagRouteDTO.setTags(tagRoute.getTags());
+        tagRouteDTO.setForce(tagRoute.isForce());
+        tagRouteDTO.setEnabled(tagRoute.isEnabled());
+        return tagRouteDTO;
+    }
+
+    public static RoutingRule insertConditionRule(RoutingRule existRule, ConditionRouteDTO conditionRoute) {
+        if (existRule == null) {
+            existRule = new RoutingRule();
+            if (StringUtils.isNotEmpty(conditionRoute.getApplication())) {
+                existRule.setKey(conditionRoute.getApplication());
+                existRule.setScope(Constants.APPLICATION);
+            } else {
+                existRule.setKey(conditionRoute.getService());
+                existRule.setScope(Constants.SERVICE);
+            }
+        }
+        existRule.setConditions(conditionRoute.getConditions());
+        existRule.setEnabled(conditionRoute.isEnabled());
+        existRule.setForce(conditionRoute.isForce());
+        existRule.setRuntime(conditionRoute.isRuntime());
+        existRule.setPriority(conditionRoute.getPriority());
+        return existRule;
+    }
+    public static BlackWhiteList convertToBlackWhiteList(AccessDTO accessDTO) {
+        if (accessDTO == null) {
+            return null;
+        }
+        BlackWhiteList blackWhiteList = new BlackWhiteList();
+//        if (StringUtils.isNoneEmpty(accessDTO.getApplication())) {
+//            blackWhiteList.set
+//        }
+//        AccessDTO storeDTO = ConvertUtil.convertDTOtoStore(accessDTO);
+
+        Set<String> whiteList = accessDTO.getWhitelist();
+        Set<String> blackList = accessDTO.getBlacklist();
+        List<String> conditions = new ArrayList<>();
+        if (whiteList != null && whiteList.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("host != ");
+            for (String white : whiteList) {
+                sb.append(white).append(",");
+            }
+            sb.deleteCharAt(sb.length() - 1);
+            sb.append(" =>");
+            conditions.add(sb.toString());
+        }
+        if (blackList != null && blackList.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("host = ");
+            for (String black : blackList) {
+                sb.append(black).append(",");
+            }
+            sb.deleteCharAt(sb.length() - 1);
+            sb.append(" =>");
+            conditions.add(sb.toString());
+        }
+        blackWhiteList.setConditions(conditions);
+        return blackWhiteList;
+    }
+
+    public static AccessDTO convertToAccessDTO(BlackWhiteList blackWhiteList, String scope, String key) {
+        if (blackWhiteList == null) {
+            return null;
+        }
+        AccessDTO accessDTO = new AccessDTO();
+        if (scope.equals(Constants.APPLICATION)) {
+            accessDTO.setApplication(key);
+        } else {
+            accessDTO.setService(key);
+        }
+        if (blackWhiteList.getConditions() != null) {
+            for (String condition : blackWhiteList.getConditions()) {
+                if (condition.contains("host != ")) {
+                    //white list
+                    condition = org.apache.commons.lang3.StringUtils.substringBetween(condition, "host !=", " =>").trim();
+                    accessDTO.setWhitelist(new HashSet<>(Arrays.asList(condition.split(","))));
+                }
+                if (condition.contains("host = ")) {
+                    //black list
+                    condition = org.apache.commons.lang3.StringUtils.substringBetween(condition, "host =", " =>").trim();
+                    accessDTO.setBlacklist(new HashSet<>(Arrays.asList(condition.split(","))));
+                }
+            }
+        }
+        return accessDTO;
+    }
+
+    public static Route convertAccessDTOtoRoute(AccessDTO accessDTO) {
+        Route route = new Route();
+        route.setService(accessDTO.getService());
+        route.setForce(true);
+        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());
+        return route;
+    }
+
+    public static ConditionRouteDTO createConditionRouteFromRule(RoutingRule routingRule) {
+        ConditionRouteDTO conditionRouteDTO = new ConditionRouteDTO();
+        if (routingRule.getScope().equals(Constants.SERVICE)) {
+            conditionRouteDTO.setService(routingRule.getKey());
+        } else {
+            conditionRouteDTO.setApplication(routingRule.getKey());
+        }
+        conditionRouteDTO.setConditions(routingRule.getConditions());
+        conditionRouteDTO.setPriority(routingRule.getPriority());
+        conditionRouteDTO.setEnabled(routingRule.isEnabled());
+        conditionRouteDTO.setForce(routingRule.isForce());
+        conditionRouteDTO.setRuntime(routingRule.isRuntime());
+        return conditionRouteDTO;
+    }
+
+    public static Route convertBlackWhiteListtoRoute(BlackWhiteList blackWhiteList, String scope, String key) {
+        AccessDTO accessDTO = convertToAccessDTO(blackWhiteList, scope, key);
+        return convertAccessDTOtoRoute(accessDTO);
+    }
+
     static Map<String, MatchPair> parseNameAndValueListString2Condition(Map<String, String> params, Map<String, String> notParams) {
         Map<String, MatchPair> condition = new HashMap<String, MatchPair>();
 
@@ -376,6 +530,7 @@
         }
     }
 
+
     public boolean isWhenContainValue(String key, String value) {
         MatchPair matchPair = whenCondition.get(key);
         if (null == matchPair) {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/util/SyncUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
similarity index 63%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/util/SyncUtils.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
index 418b112..840d046 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/util/SyncUtils.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/SyncUtils.java
@@ -14,15 +14,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.sync.util;
+package org.apache.dubbo.admin.common.util;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
-import org.apache.dubbo.admin.registry.common.domain.Route;
+import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -102,79 +99,6 @@
         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 +109,6 @@
         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/common/util/Tool.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Tool.java
new file mode 100644
index 0000000..602263c
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Tool.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+/**
+ * Tool
+ *
+ */
+public class Tool {
+
+    public static String getInterface(String service) {
+        if (service != null && service.length() > 0) {
+            int i = service.indexOf('/');
+            if (i >= 0) {
+                service = service.substring(i + 1);
+            }
+            i = service.lastIndexOf(':');
+            if (i >= 0) {
+                service = service.substring(0, i);
+            }
+        }
+        return service;
+    }
+
+    public static String getGroup(String service) {
+        if (service != null && service.length() > 0) {
+            int i = service.indexOf('/');
+            if (i >= 0) {
+                return service.substring(0, i);
+            }
+        }
+        return null;
+    }
+
+    public static String getVersion(String service) {
+        if (service != null && service.length() > 0) {
+            int i = service.lastIndexOf(':');
+            if (i >= 0) {
+                return service.substring(i + 1);
+            }
+        }
+        return null;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/UrlUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/UrlUtils.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/UrlUtils.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/UrlUtils.java
index fdd1b40..a45509b 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/UrlUtils.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/UrlUtils.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.util;
+package org.apache.dubbo.admin.common.util;
 
 import java.util.Map;
 import java.util.Map.Entry;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
new file mode 100644
index 0000000..7406e47
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/YamlParser.java
@@ -0,0 +1,52 @@
+/*
+ * 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.yaml.snakeyaml.Yaml;
+import org.yaml.snakeyaml.introspector.Property;
+import org.yaml.snakeyaml.nodes.NodeTuple;
+import org.yaml.snakeyaml.nodes.Tag;
+import org.yaml.snakeyaml.representer.Representer;
+
+public class YamlParser {
+
+    private static Yaml yaml;
+
+    static {
+        Representer representer = new Representer() {
+
+            protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
+                if (propertyValue == null) {
+                    return null;
+                }
+                else {
+                    return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
+                }
+            }
+        };
+        yaml = new Yaml(representer);
+    }
+
+    public static String dumpObject(Object object) {
+        return yaml.dumpAsMap(object);
+    }
+
+    public static <T> T loadObject(String content, Class<T> type) {
+        return yaml.loadAs(content, type);
+    }
+}
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
new file mode 100644
index 0000000..31af96f
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -0,0 +1,142 @@
+/*
+ * 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.config;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.dubbo.admin.common.exception.ConfigurationException;
+import org.apache.dubbo.admin.common.exception.ParamValidationException;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
+import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.admin.data.metadata.impl.NoOpMetadataCollector;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.registry.RegistryFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+
+import java.util.Arrays;
+
+
+@Configuration
+public class ConfigCenter {
+
+
+    @Value("${dubbo.configcenter:}")
+    private String configCenter;
+
+    @Value("${dubbo.registry.address:}")
+    private String registryAddress;
+
+    private static String globalConfigPath = "config/dubbo/dubbo.properties";
+
+    @Value("${dubbo.registry.group:}")
+    private String group;
+
+
+    private URL configCenterUrl;
+    private URL registryUrl;
+    private URL metadataUrl;
+
+
+    /*
+     * generate dynamic configuration client
+     */
+    @Bean("governanceConfiguration")
+    GovernanceConfiguration getDynamicConfiguration() {
+        GovernanceConfiguration dynamicConfiguration = null;
+
+        if (StringUtils.isNotEmpty(configCenter)) {
+            configCenterUrl = formUrl(configCenter, group);
+            dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(configCenterUrl.getProtocol());
+            dynamicConfiguration.setUrl(configCenterUrl);
+            dynamicConfiguration.init();
+            String config = dynamicConfiguration.getConfig(globalConfigPath);
+
+            if (StringUtils.isNotEmpty(config)) {
+                Arrays.stream(config.split("\n")).forEach( s -> {
+                    if(s.startsWith(Constants.REGISTRY_ADDRESS)) {
+                        registryUrl = formUrl(s.split("=")[1].trim(), group);
+                    } else if (s.startsWith(Constants.METADATA_ADDRESS)) {
+                        metadataUrl = formUrl(s.split("=")[1].trim(), group);
+                    }
+                });
+            }
+        }
+        if (dynamicConfiguration == null) {
+            if (StringUtils.isNotEmpty(registryAddress)) {
+                registryUrl = formUrl(registryAddress, group);
+                dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(registryUrl.getProtocol());
+                dynamicConfiguration.setUrl(registryUrl);
+                dynamicConfiguration.init();
+            } else {
+                throw new ConfigurationException("Either configcenter or registry address is needed");
+                //throw exception
+            }
+        }
+        return dynamicConfiguration;
+    }
+
+    /*
+     * generate registry client
+     */
+    @Bean
+    @DependsOn("governanceConfiguration")
+    Registry getRegistry() {
+        Registry registry = null;
+        if (registryUrl == null) {
+            if (StringUtils.isNotEmpty(registryAddress)) {
+                throw new ConfigurationException("Either configcenter or registry address is needed");
+            }
+            registryUrl = formUrl(registryAddress, group);
+        }
+        RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
+        registry = registryFactory.getRegistry(registryUrl);
+        return registry;
+    }
+
+    /*
+     * generate metadata client
+     */
+    @Bean
+    @DependsOn("governanceConfiguration")
+    MetaDataCollector getMetadataCollector() {
+        MetaDataCollector metaDataCollector = new NoOpMetadataCollector();
+        if (metadataUrl != null) {
+            metaDataCollector = ExtensionLoader.getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol());
+            metaDataCollector.setUrl(metadataUrl);
+            metaDataCollector.init();
+        }
+        return metaDataCollector;
+    }
+
+    private URL formUrl(String config, String group) {
+        String protocol = config.split("://")[0];
+        String address = config.split("://")[1];
+        String port = address.split(":")[1];
+        String host = address.split(":")[0];
+        URL url = new URL(protocol, host, Integer.parseInt(port));
+        if (StringUtils.isNotEmpty(group)) {
+            url.addParameter(org.apache.dubbo.common.Constants.GROUP_KEY, group);
+        }
+        return url;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/I18nConfig.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/I18nConfig.java
deleted file mode 100644
index a2016ac..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/I18nConfig.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.config;
-
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.ComponentScan;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.LocaleResolver;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
-import org.springframework.web.servlet.i18n.SessionLocaleResolver;
-
-import java.util.Locale;
-
-
-@Configuration
-@EnableAutoConfiguration
-@ComponentScan
-public class I18nConfig implements WebMvcConfigurer {
-
-    @Bean
-    public LocaleResolver localeResolver() {
-        SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver();
-        sessionLocaleResolver.setDefaultLocale(Locale.CHINA);
-        return sessionLocaleResolver;
-
-    }
-
-    @Bean
-    public LocaleChangeInterceptor localeChangeInterceptor() {
-        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
-        lci.setParamName("lang");
-        return lci;
-    }
-
-    @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-        registry.addInterceptor(localeChangeInterceptor());
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/SwaggerConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/SwaggerConfiguration.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java
index 2a416ec..5814927 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/SwaggerConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/SwaggerConfiguration.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin;
+package org.apache.dubbo.admin.config;
 
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/XmlConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/XmlConfiguration.java
deleted file mode 100644
index 92f3460..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/XmlConfiguration.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.config;
-
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportResource;
-
-
-@Configuration
-@ImportResource({"classpath*:dubbo-admin.xml"})
-public class XmlConfiguration {
-
-}
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 5cce05e..e815669 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
@@ -16,15 +16,15 @@
  */
 package org.apache.dubbo.admin.controller;
 
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.admin.common.util.RouteRule;
+import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
+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.dto.AccessDTO;
-import org.apache.dubbo.admin.governance.service.RouteService;
-import org.apache.dubbo.admin.registry.common.domain.Route;
-import org.apache.dubbo.admin.registry.common.route.RouteRule;
+import org.apache.dubbo.admin.model.dto.AccessDTO;
+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.*;
@@ -45,119 +45,73 @@
     }
 
     @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);
-            }
+    public List<AccessDTO> searchAccess(@RequestParam(required = false) String service,
+                                        @RequestParam(required = false) String application,
+                                        @PathVariable String env) throws ParseException {
+        if (StringUtils.isBlank(service) && StringUtils.isBlank(application)) {
+            throw new ParamValidationException("Either service or application is required");
+        }
+        List<AccessDTO> accessDTOS = new ArrayList<>();
+        AccessDTO accessDTO;
+        if (StringUtils.isNotBlank(application)) {
+            accessDTO = routeService.findAccess(application);
         } else {
-            routes = routeService.findAllForceRoute();
+            accessDTO = routeService.findAccess(service);
         }
-
-        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);
-            }
+        if (accessDTO != null) {
+            accessDTO.setEnabled(true);
+            accessDTOS.add(accessDTO);
         }
-        return result;
+        return accessDTOS;
     }
 
     @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;
-        }
+        id = id.replace("*", "/");
+        AccessDTO accessDTO = routeService.findAccess(id);
+        return accessDTO;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public void deleteAccess(@PathVariable String id, @PathVariable String env) {
-        routeService.deleteRoute(id);
+        id = id.replace("*", "/");
+        routeService.deleteAccess(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 (StringUtils.isBlank(accessDTO.getService()) && StringUtils.isBlank(accessDTO.getApplication())) {
+            throw new ParamValidationException("Either Service or application 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);
+        routeService.createAccess(accessDTO);
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
     public void updateAccess(@PathVariable String id, @RequestBody AccessDTO accessDTO, @PathVariable String env) {
-        Route route = routeService.findRoute(id);
+
+        id = id.replace("*", "/");
+        ConditionRouteDTO route = routeService.findConditionRoute(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);
+        routeService.updateAccess(accessDTO);
     }
+
+//    private ConditionRouteDTO routeCopy(ConditionRouteDTO old) {
+//        ConditionRouteDTO newRoute = new ConditionRouteDTO();
+//        newRoute.setKey(old.getKey());
+//        newRoute.setScope(old.getScope());
+//        newRoute.setConditions(old.getConditions());
+//        newRoute.setRuntime(old.isRuntime());
+//        newRoute.setEnabled(old.isEnabled());
+//        newRoute.setDynamic(old.isDynamic());
+//        newRoute.setForce(old.isForce());
+//        newRoute.setPriority(old.getPriority());
+//        newRoute.setBlackWhiteList(null);
+//        return newRoute;
+//    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
new file mode 100644
index 0000000..a5849e0
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ConditionRoutesController.java
@@ -0,0 +1,121 @@
+/*
+ * 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.common.exception.VersionValidationException;
+import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
+import org.apache.dubbo.admin.service.ProviderService;
+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.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/{env}/rules/route/condition")
+public class ConditionRoutesController {
+
+    private final RouteService routeService;
+    private final ProviderService providerService;
+
+    @Autowired
+    public ConditionRoutesController(RouteService routeService, ProviderService providerService) {
+        this.routeService = routeService;
+        this.providerService = providerService;
+    }
+
+    @RequestMapping(method = RequestMethod.POST)
+    @ResponseStatus(HttpStatus.CREATED)
+    public boolean createRule(@RequestBody ConditionRouteDTO routeDTO, @PathVariable String env) {
+        String serviceName = routeDTO.getService();
+        String app = routeDTO.getApplication();
+        if (StringUtils.isEmpty(serviceName) && StringUtils.isEmpty(app)) {
+            throw new ParamValidationException("serviceName and app is Empty!");
+        }
+        if (StringUtils.isNotEmpty(app) && providerService.findVersionInApplication(app).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support application scope routing rule");
+        }
+        routeService.createConditionRoute(routeDTO);
+        return true;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+    public boolean updateRule(@PathVariable String id, @RequestBody ConditionRouteDTO newConditionRoute, @PathVariable String env) {
+        id = id.replace("*", "/");
+        ConditionRouteDTO oldConditionRoute = routeService.findConditionRoute(id);
+        if (oldConditionRoute == null) {
+            throw new ResourceNotFoundException("can not find route rule for: " + id);
+        }
+        routeService.updateConditionRoute(newConditionRoute);
+        return true;
+    }
+
+    @RequestMapping(method = RequestMethod.GET)
+    public List<ConditionRouteDTO> searchRoutes(@RequestParam(required = false) String application,
+                                                @RequestParam(required = false) String service, @PathVariable String env) {
+        ConditionRouteDTO conditionRoute = null;
+        List<ConditionRouteDTO> result = new ArrayList<>();
+        if (StringUtils.isNotEmpty(application)) {
+            conditionRoute = routeService.findConditionRoute(application);
+        }
+        if (StringUtils.isNotEmpty(service)) {
+            conditionRoute = routeService.findConditionRoute(service);
+        }
+        if (conditionRoute != null && conditionRoute.getConditions() != null) {
+            result.add(conditionRoute);
+        }
+        return result;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+    public ConditionRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        ConditionRouteDTO conditionRoute = routeService.findConditionRoute(id);
+        if (conditionRoute == null || conditionRoute.getConditions() == null) {
+            throw new ResourceNotFoundException("Unknown ID!");
+        }
+        return conditionRoute;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+    public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        routeService.deleteConditionRoute(id);
+        return true;
+    }
+
+    @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
+    public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        routeService.enableConditionRoute(id);
+        return true;
+    }
+
+    @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
+    public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        routeService.disableConditionRoute(id);
+        return true;
+    }
+
+}
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 004bc15..3d1221e 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
@@ -20,11 +20,8 @@
 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.dto.BalancingDTO;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.registry.common.domain.LoadBalance;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.util.OverrideUtils;
+import org.apache.dubbo.admin.model.dto.BalancingDTO;
+import org.apache.dubbo.admin.service.OverrideService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
@@ -32,7 +29,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import static org.apache.dubbo.admin.registry.common.util.OverrideUtils.overrideToLoadBalance;
 
 @RestController
 @RequestMapping("/api/{env}/rules/balancing")
@@ -48,87 +44,83 @@
     @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!");
+        if (StringUtils.isBlank(balancingDTO.getService()) && StringUtils.isBlank(balancingDTO.getApplication())) {
+            throw new ParamValidationException("Either Service or application is required.");
         }
-        LoadBalance loadBalance = new LoadBalance();
-        loadBalance.setService(serviceName);
-        loadBalance.setMethod(formatMethodName(balancingDTO.getMethodName()));
-        loadBalance.setStrategy(balancingDTO.getStrategy());
-        overrideService.saveOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
+        overrideService.saveBalance(balancingDTO);
+//        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) {
+        if (id == null) {
+            throw new ParamValidationException("Unknown ID!");
+        }
+        id = id.replace("*", "/");
+        BalancingDTO balancing = overrideService.findBalance(id);
+        if (balancing == 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));
+
+        overrideService.saveBalance(balancingDTO);
         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();
+    public List<BalancingDTO> searchLoadbalances(@RequestParam(required = false) String service,
+                                                 @RequestParam(required = false) String application,
+                                                 @PathVariable String env) {
+
+        if (StringUtils.isBlank(service) && StringUtils.isBlank(application)) {
+            throw new ParamValidationException("Either service or application is required");
+        }
+        BalancingDTO balancingDTO;
+        if (StringUtils.isNotBlank(application)) {
+            balancingDTO = overrideService.findBalance(application);
         } else {
-            overrides = overrideService.findByService(service);
+            balancingDTO = overrideService.findBalance(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);
-                }
-            }
+        List<BalancingDTO> balancingDTOS = new ArrayList<>();
+        if (balancingDTO != null) {
+            balancingDTOS.add(balancingDTO);
         }
-        return loadBalances;
+        return balancingDTOS;
     }
 
     @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) {
+        id = id.replace("*", "/");
+        BalancingDTO balancingDTO = overrideService.findBalance(id);
+        if (balancingDTO == 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;
+
+//        LoadBalance loadBalance = OverrideUtils.overrideToLoadBalance(override);
+//        BalancingDTO balancingDTO = new BalancingDTO();
+//        balancingDTO.setService(loadBalance.getService());
+//        balancingDTO.setMethodName(loadBalance.getMethod());
+//        balancingDTO.setStrategy(loadBalance.getStrategy());
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteLoadBalance(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
         if (id == null) {
             throw new IllegalArgumentException("Argument of id is null!");
         }
-        overrideService.deleteOverride(id);
+        overrideService.deleteBalance(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 f4a6e7d..96cb8dd 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,106 +17,90 @@
 
 package org.apache.dubbo.admin.controller;
 
-import com.alibaba.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;
-import org.apache.dubbo.admin.dto.OverrideDTO;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.registry.common.domain.Override;
+import org.apache.dubbo.admin.common.exception.VersionValidationException;
+import org.apache.dubbo.admin.model.dto.DynamicConfigDTO;
+import org.apache.dubbo.admin.service.OverrideService;
+import org.apache.dubbo.admin.service.ProviderService;
 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;
 
 @RestController
 @RequestMapping("/api/{env}/rules/override")
 public class OverridesController {
 
     private final OverrideService overrideService;
+    private final ProviderService providerService;
 
     @Autowired
-    public OverridesController(OverrideService overrideService) {
+    public OverridesController(OverrideService overrideService, ProviderService providerService) {
         this.overrideService = overrideService;
+        this.providerService = providerService;
     }
 
     @RequestMapping(method = RequestMethod.POST)
     @ResponseStatus(HttpStatus.CREATED)
-    public boolean createOverride(@RequestBody OverrideDTO overrideDTO, @PathVariable String env) {
+    public boolean createOverride(@RequestBody DynamicConfigDTO 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);
-        overrideService.saveOverride(override);
+        if (StringUtils.isNotEmpty(application) && providerService.findVersionInApplication(application).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support application scope dynamic config");
+        }
+        overrideService.saveOverride(overrideDTO);
         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);
+    public boolean updateOverride(@PathVariable String id, @RequestBody DynamicConfigDTO overrideDTO, @PathVariable String env) {
+        id = id.replace("*", "/");
+        DynamicConfigDTO 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);
-        overrideService.updateOverride(override);
+        overrideService.updateOverride(overrideDTO);
         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<DynamicConfigDTO> searchOverride(@RequestParam(required = false) String service,
+                                                 @RequestParam(required = false) String application,
+                                                 @PathVariable String env) {
+        DynamicConfigDTO override = null;
+        List<DynamicConfigDTO> result = new ArrayList<>();
+        if (StringUtils.isNotEmpty(service)) {
+            override = overrideService.findOverride(service);
+        } else if(StringUtils.isNotEmpty(application)){
+            override = overrideService.findOverride(application);
         }
-        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);
-            result.add(overrideDTO);
+        if (override != null) {
+            result.add(override);
         }
         return result;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
-    public OverrideDTO detailOverride(@PathVariable String id, @PathVariable String env) {
-        Override override = overrideService.findById(id);
+    public DynamicConfigDTO detailOverride(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        DynamicConfigDTO 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);
-        return overrideDTO;
+
+        return override;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteOverride(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
         overrideService.deleteOverride(id);
         return true;
     }
@@ -124,86 +108,16 @@
     @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
     public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
 
+        id = id.replace("*", "/");
         overrideService.enableOverride(id);
         return true;
     }
 
     @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
     public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
 
         overrideService.disableOverride(id);
         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("&");
-                }
-            }
-        }
-        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/RoutesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/RoutesController.java
deleted file mode 100644
index 1ec2edb..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/RoutesController.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.dto.RouteDTO;
-import org.apache.dubbo.admin.governance.service.RouteService;
-import org.apache.dubbo.admin.registry.common.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.List;
-
-@RestController
-@RequestMapping("/api/{env}/rules/route")
-public class RoutesController {
-
-    private final RouteService routeService;
-
-    @Autowired
-    public RoutesController(RouteService routeService) {
-        this.routeService = routeService;
-    }
-
-    @RequestMapping(method = RequestMethod.POST)
-    @ResponseStatus(HttpStatus.CREATED)
-    public boolean createRule(@RequestBody RouteDTO routeDTO, @PathVariable String env) {
-        String serviceName = routeDTO.getService();
-        String app = routeDTO.getApp();
-        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
-        }
-        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!");
-        }
-        routeDTO.setService(route.getService());
-        Route newRoute = convertRouteDTOtoRoute(routeDTO, id);
-        routeService.updateRoute(newRoute);
-        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
-        }
-        if (StringUtils.isNotEmpty(service)) {
-            routes = routeService.findByService(service);
-        } else {
-            routes = routeService.findAll();
-        }
-        List<RouteDTO> routeDTOS = new ArrayList<>();
-        for (Route route : routes) {
-            RouteDTO routeDTO = convertRoutetoRouteDTO(route, route.getHash());
-            routeDTOS.add(routeDTO);
-        }
-        return routeDTOS;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
-    public RouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
-        Route route = routeService.findRoute(id);
-        if (route == null) {
-            throw new ResourceNotFoundException("Unknown ID!");
-        }
-        RouteDTO routeDTO = convertRoutetoRouteDTO(route, id);
-        return routeDTO;
-    }
-
-    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
-    public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
-        routeService.deleteRoute(id);
-        return true;
-    }
-
-    @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
-    public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
-
-        routeService.enableRoute(id);
-        return true;
-    }
-
-    @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
-    public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
-
-        routeService.disableRoute(id);
-        return true;
-    }
-
-    private String parseCondition(String[] conditions) {
-        StringBuilder when = new StringBuilder();
-        StringBuilder then = new StringBuilder();
-        for (String condition : conditions) {
-            condition = condition.trim();
-            if (condition.contains("=>")) {
-                String[] array = condition.split("=>", 2);
-                String consumer = array[0].trim();
-                String provider = array[1].trim();
-                if (consumer != "") {
-                    if (when.length() != 0) {
-                        when.append(" & ").append(consumer);
-                    } else {
-                        when.append(consumer);
-                    }
-                }
-                if (provider != "") {
-                    if (then.length() != 0) {
-                        then.append(" & ").append(provider);
-                    } else {
-                        then.append(provider);
-                    }
-                }
-            }
-        }
-        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);
-        }
-        return route;
-    }
-
-    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());
-        }
-        return routeDTO;
-    }
-}
\ No newline at end of file
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
index b21f72d..d080f2e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/ServiceController.java
@@ -17,14 +17,18 @@
 
 package org.apache.dubbo.admin.controller;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.dto.ServiceDTO;
-import org.apache.dubbo.admin.dto.ServiceDetailDTO;
-import org.apache.dubbo.admin.governance.service.ConsumerService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
+import com.google.gson.Gson;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.admin.model.dto.ServiceDTO;
+import org.apache.dubbo.admin.model.dto.ServiceDetailDTO;
+import org.apache.dubbo.admin.service.ConsumerService;
+import org.apache.dubbo.admin.service.ProviderService;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
@@ -54,14 +58,14 @@
         if (!filter.contains("*") && !filter.contains("?")) {
             if (pattern.equals("ip")) {
                 providers = providerService.findByAddress(filter);
-            } else if (pattern.equals("serviceName")) {
+            } else if (pattern.equals("service")) {
                 providers = providerService.findByService(filter);
             } else if (pattern.equals("application")) {
                 providers = providerService.findByApplication(filter);
             }
         } else {
             List<String> candidates = Collections.emptyList();
-            if (pattern.equals("serviceName")) {
+            if (pattern.equals("service")) {
                candidates = providerService.findServices();
             } else if (pattern.equals("application")) {
                 candidates = providerService.findApplications();
@@ -74,7 +78,7 @@
             for (String candidate : candidates) {
                 Matcher matcher = regex.matcher(candidate);
                 if (matcher.matches() || matcher.lookingAt()) {
-                    if (pattern.equals("serviceName")) {
+                    if (pattern.equals("service")) {
                         providers.addAll(providerService.findByService(candidate));
                     } else {
                         providers.addAll(providerService.findByApplication(candidate));
@@ -107,9 +111,23 @@
 
         List<Consumer> consumers = consumerService.findByService(service);
 
+        Map<String, String> info = ConvertUtil.serviceName2Map(service);
+        String application = null;
+        if (providers != null && providers.size() > 0) {
+            application = providers.get(0).getApplication();
+        }
+        MetadataIdentifier identifier = new MetadataIdentifier(info.get(Constants.INTERFACE_KEY),
+                                                                      info.get(Constants.VERSION_KEY),
+                                                                      info.get(Constants.GROUP_KEY), Constants.PROVIDER_SIDE, application);
+        String metadata = providerService.getProviderMetaData(identifier);
         ServiceDetailDTO serviceDetailDTO = new ServiceDetailDTO();
-        serviceDetailDTO.setConsumers(consumers);
-        serviceDetailDTO.setProviders(providers);
+        if (metadata != null) {
+            Gson gson = new Gson();
+            FullServiceDefinition serviceDefinition = gson.fromJson(metadata, FullServiceDefinition.class);
+            serviceDetailDTO.setConsumers(consumers);
+            serviceDetailDTO.setProviders(providers);
+            serviceDetailDTO.setMetadata(serviceDefinition);
+        }
         return serviceDetailDTO;
     }
 }
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..40b81bf
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/controller/TagRoutesController.java
@@ -0,0 +1,132 @@
+/*
+ * 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.common.exception.VersionValidationException;
+import org.apache.dubbo.admin.model.dto.TagRouteDTO;
+import org.apache.dubbo.admin.service.ProviderService;
+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.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/{env}/rules/route/tag")
+public class TagRoutesController {
+
+
+    private final RouteService routeService;
+    private final ProviderService providerService;
+
+    @Autowired
+    public TagRoutesController(RouteService routeService, ProviderService providerService) {
+        this.routeService = routeService;
+        this.providerService = providerService;
+    }
+
+    @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!");
+        }
+        if (providerService.findVersionInApplication(app).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support tag route");
+        }
+        routeService.createTagRoute(routeDTO);
+        return true;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
+    public boolean updateRule(@PathVariable String id, @RequestBody TagRouteDTO routeDTO, @PathVariable String env) {
+
+        id = id.replace("*", "/");
+        String app = routeDTO.getApplication();
+        if (providerService.findVersionInApplication(app).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support tag route");
+        }
+        if (routeService.findConditionRoute(id) == null) {
+            throw new ResourceNotFoundException("can not find tag route, Id: " + id);
+        }
+        routeService.updateTagRoute(routeDTO);
+        return true;
+
+    }
+
+    @RequestMapping(method = RequestMethod.GET)
+    public List<TagRouteDTO> searchRoutes(@RequestParam String application, @PathVariable String env) {
+        List<TagRouteDTO> result = new ArrayList<>();
+        String version = "2.6";
+        try {
+            version = providerService.findVersionInApplication(application);
+        } catch (ParamValidationException e) {
+            //ignore
+        }
+        if (version.equals("2.6")) {
+            return result;
+        }
+
+        TagRouteDTO tagRoute = null;
+        if (StringUtils.isNotEmpty(application)) {
+            tagRoute = routeService.findTagRoute(application);
+        }
+        if (tagRoute != null) {
+            result.add(tagRoute);
+        }
+        return result;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
+    public TagRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        TagRouteDTO tagRoute = routeService.findTagRoute(id);
+        if (tagRoute == null) {
+            throw new ResourceNotFoundException("Unknown ID!");
+        }
+        return tagRoute;
+    }
+
+    @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
+    public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        routeService.deleteTagRoute(id);
+        return true;
+    }
+
+    @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
+    public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        routeService.enableTagRoute(id);
+        return true;
+    }
+
+    @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
+    public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
+        id = id.replace("*", "/");
+        routeService.disableTagRoute(id);
+        return true;
+    }
+}
+
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 cc679f9..11ce807 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
@@ -20,11 +20,13 @@
 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.dto.WeightDTO;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.domain.Weight;
-import org.apache.dubbo.admin.registry.common.util.OverrideUtils;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.model.dto.AccessDTO;
+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.*;
@@ -46,14 +48,18 @@
     @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));
+        if (StringUtils.isBlank(weightDTO.getService()) && StringUtils.isBlank(weightDTO.getApplication())) {
+            throw new ParamValidationException("Either Service or application is required.");
         }
+        overrideService.saveWeight(weightDTO);
+//        List<String> addresses = weightDTO.getAddresses();
+//        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;
     }
 
@@ -62,61 +68,73 @@
         if (id == null) {
             throw new ParamValidationException("Unknown ID!");
         }
-        Override override = overrideService.findById(id);
-        if (override == null) {
+        id = id.replace("*", "/");
+        WeightDTO weight = overrideService.findWeight(id);
+        if (weight == 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));
+//        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));
+        overrideService.updateWeight(weightDTO);
         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();
+    public List<WeightDTO> searchWeight(@RequestParam(required = false) String service,
+                                        @RequestParam(required = false) String application,
+                                        @PathVariable String env) {
+        if (StringUtils.isBlank(service) && StringUtils.isBlank(application)) {
+            throw new ParamValidationException("Either service or application is required");
+        }
+        WeightDTO weightDTO;
+        if (StringUtils.isNotBlank(application)) {
+            weightDTO = overrideService.findWeight(application);
         } else {
-            overrides = overrideService.findByService(service);
+            weightDTO = overrideService.findWeight(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);
-            }
+        if (weightDTO != null) {
+            weightDTOS.add(weightDTO);
         }
+
+//        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.setAddresses(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;
+        id = id.replace("*", "/");
+        WeightDTO weightDTO = overrideService.findWeight(id);
+        if (weightDTO == null) {
+            throw new ResourceNotFoundException("Unknown ID!");
         }
-        return null;
+        return weightDTO;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteWeight(@PathVariable String id, @PathVariable String env) {
-        overrideService.deleteOverride(id);
+        id = id.replace("*", "/");
+        overrideService.deleteWeight(id);
         return true;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OwnerService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
similarity index 60%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OwnerService.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
index e079edb..8fb75ab 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OwnerService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
@@ -14,28 +14,30 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service;
 
-import org.apache.dubbo.admin.registry.common.domain.Owner;
+package org.apache.dubbo.admin.data.config;
 
-import java.util.List;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
 
-public interface OwnerService {
 
-    List<String> findAllServiceNames();
+@SPI("zookeeper")
+public interface GovernanceConfiguration {
+    void init();
 
-    List<String> findServiceNamesByUsername(String username);
+    void setUrl(URL url);
 
-    List<String> findUsernamesByServiceName(String serviceName);
+    URL getUrl();
+    String setConfig(String key, String value);
 
-    List<Owner> findByService(String serviceName);
+    String getConfig(String key);
 
-    List<Owner> findAll();
+    boolean deleteConfig(String key);
 
-    Owner findById(String id);
+    String setConfig(String group, String key, String value);
 
-    void saveOwner(Owner owner);
+    String getConfig(String group, String key);
 
-    void deleteOwner(Owner owner);
+    boolean deleteConfig(String group, 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
new file mode 100644
index 0000000..2bc0f90
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java
@@ -0,0 +1,112 @@
+/*
+ * 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.data.config.impl;
+
+import com.ctrip.framework.apollo.openapi.client.ApolloOpenApiClient;
+import com.ctrip.framework.apollo.openapi.dto.OpenItemDTO;
+import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+import org.springframework.beans.factory.annotation.Value;
+
+@SPI("apollo")
+public class ApolloConfiguration implements GovernanceConfiguration {
+
+    @Value("${dubbo.apollo.token}")
+    private String token;
+
+    @Value("${dubbo.apollo.cluster}")
+    private String cluster;
+
+    @Value("${dubbo.apollo.namespace}")
+    private String namespace;
+
+    @Value("${dubbo.apollo.env}")
+    private String env;
+
+    @Value("${dubbo.apollo.appId}")
+    private String appId;
+
+    private URL url;
+    private ApolloOpenApiClient client;
+
+
+    @Override
+    public void setUrl(URL url) {
+       this.url = url;
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    @Override
+    public void init() {
+        client = ApolloOpenApiClient.newBuilder().withPortalUrl(url.getAddress()).withToken(token).build();
+    }
+
+    @Override
+    public String setConfig(String key, String value) {
+        return setConfig(null, key, value);
+    }
+
+    @Override
+    public String getConfig(String key) {
+        return getConfig(null, key);
+    }
+
+    @Override
+    public boolean deleteConfig(String key) {
+        return deleteConfig(null, key);
+    }
+
+    @Override
+    public String setConfig(String group, String key, String value) {
+        if (group == null) {
+            group = namespace;
+        }
+        OpenItemDTO openItemDTO = new OpenItemDTO();
+        openItemDTO.setKey(key);
+        openItemDTO.setValue(value);
+        client.createItem(appId, env, cluster, group, openItemDTO);
+        return value;
+    }
+
+    @Override
+    public String getConfig(String group, String key) {
+        if (group == null) {
+            group = namespace;
+        }
+        OpenItemDTO openItemDTO =  client.getItem(appId, env, cluster, group, key);
+        if (openItemDTO != null) {
+            return openItemDTO.getValue();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean deleteConfig(String group, String key) {
+        if (group == null) {
+            group = namespace;
+        }
+        //TODO user login user name as the operator
+        client.removeItem(appId, env, cluster, group, key, "admin");
+        return true;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/NoOpConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/NoOpConfiguration.java
new file mode 100644
index 0000000..08cb489
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/NoOpConfiguration.java
@@ -0,0 +1,69 @@
+/*
+ * 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.data.config.impl;
+
+import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
+import org.apache.dubbo.common.URL;
+
+public class NoOpConfiguration implements GovernanceConfiguration {
+
+    @Override
+    public void init() {
+
+    }
+
+    @Override
+    public void setUrl(URL url) {
+
+    }
+
+    @Override
+    public URL getUrl() {
+        return null;
+    }
+
+    @Override
+    public String setConfig(String key, String value) {
+        return null;
+    }
+
+    @Override
+    public String getConfig(String key) {
+        return null;
+    }
+
+    @Override
+    public boolean deleteConfig(String key) {
+        return false;
+    }
+
+    @Override
+    public String setConfig(String group, String key, String value) {
+        return null;
+    }
+
+    @Override
+    public String getConfig(String group, String key) {
+        return null;
+    }
+
+    @Override
+    public boolean deleteConfig(String group, 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
new file mode 100644
index 0000000..95e7988
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java
@@ -0,0 +1,128 @@
+/*
+ * 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.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;
+
+import javax.swing.*;
+
+public class ZookeeperConfiguration implements GovernanceConfiguration {
+    private CuratorFramework zkClient;
+    private URL url;
+    private String root;
+
+    @Override
+    public void setUrl(URL url) {
+       this.url = url;
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    @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) {
+        return setConfig(null, key, value);
+    }
+
+    @Override
+    public String getConfig(String key) {
+        return getConfig(null, key);
+    }
+
+    @Override
+    public boolean deleteConfig(String key) {
+        return deleteConfig(null, key);
+    }
+
+    @Override
+    public String setConfig(String group, String key, String value) {
+        String path = getNodePath(key, group);
+        try {
+            if (zkClient.checkExists().forPath(path) == null) {
+                zkClient.create().creatingParentsIfNeeded().forPath(path);
+            }
+            zkClient.setData().forPath(path, value.getBytes());
+            return value;
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+    @Override
+    public String getConfig(String group, String key) {
+        String path = getNodePath(key, group);
+
+        try {
+            if (zkClient.checkExists().forPath(path) == null) {
+                return null;
+            }
+            return new String(zkClient.getData().forPath(path));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean deleteConfig(String group, String key) {
+        String path = getNodePath(key, group);
+        try {
+            zkClient.delete().forPath(path);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return true;
+    }
+
+    private String getNodePath(String path, String group) {
+        return toRootDir(group) + path;
+    }
+
+    private String toRootDir(String group) {
+        if (group != null) {
+            if (!group.startsWith(Constants.PATH_SEPARATOR)) {
+                root = Constants.PATH_SEPARATOR + group;
+            } else {
+                root = group;
+            }
+        }
+        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/web/mvc/common/i18n/LocaleUtil.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
similarity index 65%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/common/i18n/LocaleUtil.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
index e48d2bc..5b5e802 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/common/i18n/LocaleUtil.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
@@ -14,23 +14,23 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.web.mvc.common.i18n;
 
-import java.util.Locale;
+package org.apache.dubbo.admin.data.metadata;
 
-public class LocaleUtil {
-    private static ThreadLocal<Locale> userLocale = new ThreadLocal<Locale>();
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 
-    public static void cleanLocale() {
-        userLocale.remove();
-    }
+@SPI("zookeeper")
+public interface MetaDataCollector {
 
-    public static Locale getLocale() {
-        return userLocale.get();
-    }
+    void setUrl(URL url);
 
-    public static void setLocale(Locale locale) {
-        userLocale.set(locale);
-    }
+    URL getUrl();
 
+    void init();
+
+    String getProviderMetaData(MetadataIdentifier key);
+
+    String getConsumerMetaData(MetadataIdentifier key);
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/NoOpMetadataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/NoOpMetadataCollector.java
new file mode 100644
index 0000000..8e561a6
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/NoOpMetadataCollector.java
@@ -0,0 +1,50 @@
+/*
+ * 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.data.metadata.impl;
+
+import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+
+public class NoOpMetadataCollector implements MetaDataCollector {
+
+    @Override
+    public void setUrl(URL url) {
+
+    }
+
+    @Override
+    public URL getUrl() {
+        return null;
+    }
+
+    @Override
+    public void init() {
+
+    }
+
+    @Override
+    public String getProviderMetaData(MetadataIdentifier key) {
+        return null;
+    }
+
+    @Override
+    public String getConsumerMetaData(MetadataIdentifier key) {
+        return null;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java
new file mode 100644
index 0000000..b00238a
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java
@@ -0,0 +1,64 @@
+/*
+ * 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.data.metadata.impl;
+
+
+import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+public class RedisMetaDataCollector implements MetaDataCollector {
+
+    private  URL url;
+    private JedisPool pool;
+    private static final String META_DATA_SOTRE_TAG = ".metaData";
+    @Override
+    public void setUrl(URL url) {
+        this.url = url;
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    @Override
+    public void init() {
+        pool = new JedisPool(new JedisPoolConfig(), url.getHost(), url.getPort());
+    }
+
+    @Override
+    public String getProviderMetaData(MetadataIdentifier key) {
+        return doGetMetaData(key);
+    }
+
+    @Override
+    public String getConsumerMetaData(MetadataIdentifier key) {
+        return doGetMetaData(key);
+    }
+
+    private String doGetMetaData(MetadataIdentifier identifier) {
+        //TODO error handing
+        Jedis jedis = pool.getResource();
+        String result = jedis.get(identifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY) + META_DATA_SOTRE_TAG);
+        return result;
+    }
+}
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
new file mode 100644
index 0000000..0ecab02
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
@@ -0,0 +1,93 @@
+/*
+ * 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.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.URL;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+
+public class ZookeeperMetaDataCollector implements MetaDataCollector {
+
+    private CuratorFramework client;
+    private URL url;
+    private String root;
+    private final static String METADATA_NODE_NAME = "service.data";
+    private final static String DEFAULT_ROOT = "dubbo";
+
+    @Override
+    public void setUrl(URL url) {
+        this.url = url;
+    }
+
+    @Override
+    public URL getUrl() {
+        return url;
+    }
+
+    @Override
+    public void init() {
+        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
+        if (!group.startsWith(Constants.PATH_SEPARATOR)) {
+            group = Constants.PATH_SEPARATOR + group;
+        }
+        root = group;
+        client = CuratorFrameworkFactory.newClient(url.getAddress(), new ExponentialBackoffRetry(1000, 3));
+        client.start();
+    }
+
+
+    @Override
+    public String getProviderMetaData(MetadataIdentifier key) {
+        return doGetMetadata(key);
+    }
+
+    @Override
+    public String getConsumerMetaData(MetadataIdentifier key) {
+        return doGetMetadata(key);
+    }
+
+    private String getNodePath(MetadataIdentifier metadataIdentifier) {
+        return toRootDir() + metadataIdentifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.PATH) +
+                Constants.PATH_SEPARATOR + METADATA_NODE_NAME;
+    }
+
+    private String toRootDir() {
+        if (root.equals(Constants.PATH_SEPARATOR)) {
+            return root;
+        }
+        return root + Constants.PATH_SEPARATOR;
+    }
+
+    private String doGetMetadata(MetadataIdentifier identifier) {
+        //TODO error handing
+        try {
+            String path = getNodePath(identifier);
+            if (client.checkExists().forPath(path) == null) {
+                return null;
+            }
+            return new String(client.getData().forPath(path));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/OverrideDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/OverrideDTO.java
deleted file mode 100644
index 812cdfa..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/OverrideDTO.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.dto;
-
-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;
-
-    public String getApplication() {
-        return application;
-    }
-
-    public void setApplication(String application) {
-        this.application = application;
-    }
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public String getAddress() {
-        return address;
-    }
-
-    public void setAddress(String address) {
-        this.address = address;
-    }
-
-    public boolean isDynamic() {
-        return dynamic;
-    }
-
-    public void setDynamic(boolean dynamic) {
-        this.dynamic = dynamic;
-    }
-
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    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/filter/LoginFilter.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/filter/LoginFilter.java
deleted file mode 100644
index 127b5fa..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/filter/LoginFilter.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.filter;
-
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.governance.service.UserService;
-import org.apache.dubbo.admin.governance.util.WebConstants;
-import org.apache.dubbo.admin.registry.common.domain.User;
-import org.apache.dubbo.admin.registry.common.util.Coder;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import javax.servlet.*;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-//@Component
-public class LoginFilter implements Filter{
-
-    private static final Logger logger = LoggerFactory.getLogger(LoginFilter.class);
-    private static Pattern PARAMETER_PATTERN = Pattern.compile("(\\w+)=[\"]?([^,\"]+)[\"]?[,]?\\s*");
-    private static final String BASIC_CHALLENGE = "Basic";
-    private static final String DIGEST_CHALLENGE = "Digest";
-    private static final String CHALLENGE = BASIC_CHALLENGE;
-    private static final String REALM = User.REALM;
-
-    @Autowired
-    private UserService userService;
-    private String logout = "/logout";
-    private String logoutCookie = "logout";
-
-    static Map<String, String> parseParameters(String query) {
-        Matcher matcher = PARAMETER_PATTERN.matcher(query);
-        Map<String, String> map = new HashMap<String, String>();
-        while (matcher.find()) {
-            String key = matcher.group(1);
-            String value = matcher.group(2);
-            map.put(key, value);
-        }
-        return map;
-    }
-
-    static byte[] readToBytes(InputStream in) throws IOException {
-        byte[] buf = new byte[in.available()];
-        in.read(buf);
-        return buf;
-    }
-
-    @Override
-    public void init(FilterConfig filterConfig) throws ServletException {
-
-    }
-
-    @Override
-    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
-        throws IOException, ServletException {
-
-        HttpServletRequest req = (HttpServletRequest)request;
-        HttpServletResponse resp = (HttpServletResponse) response;
-        if (logger.isInfoEnabled()) {
-            logger.info("AuthorizationValve of uri: " + req.getRequestURI());
-        }
-        String uri = req.getRequestURI();
-        String contextPath = req.getContextPath();
-        if (contextPath != null && contextPath.length() > 0 && !"/".equals(contextPath)) {
-            uri = uri.substring(contextPath.length());
-        }
-        if (uri.equals(logout)) {
-            if (!isLogout(req)) {
-                setLogout(true, resp);
-                showLoginForm(resp);
-            } else {
-                setLogout(false, resp);
-                resp.sendRedirect(contextPath == null || contextPath.length() == 0 ? "/" : contextPath);
-            }
-            return;
-        }
-        User user = null;
-        String authType = null;
-        String authorization = req.getHeader("Authorization");
-        if (authorization != null && authorization.length() > 0) {
-            int i = authorization.indexOf(' ');
-            if (i >= 0) {
-                authType = authorization.substring(0, i);
-                String authPrincipal = authorization.substring(i + 1);
-                if (BASIC_CHALLENGE.equalsIgnoreCase(authType)) {
-                    user = loginByBase(authPrincipal);
-                } else if (DIGEST_CHALLENGE.equalsIgnoreCase(authType)) {
-                    user = loginByDigest(authPrincipal, req);
-                }
-            }
-        }
-        if (user == null || user.getUsername() == null || user.getUsername().length() == 0) {
-            showLoginForm(resp);
-            return;
-            //pipelineContext.breakPipeline(1);
-        }
-        if (user != null && StringUtils.isNotEmpty(user.getUsername())) {
-            req.getSession().setAttribute(WebConstants.CURRENT_USER_KEY, user);
-            chain.doFilter(request, response);
-        }
-
-    }
-
-    @Override
-    public void destroy() {
-
-    }
-
-    private void showLoginForm(HttpServletResponse response) throws IOException {
-        if (DIGEST_CHALLENGE.equals(CHALLENGE)) {
-            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\", qop=\"auth\", nonce=\""
-                + UUID.randomUUID().toString().replace("-", "") + "\", opaque=\""
-                + Coder.encodeMd5(REALM) + "\"");
-        } else {
-            response.setHeader("WWW-Authenticate", CHALLENGE + " realm=\"" + REALM + "\"");
-        }
-        response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
-        response.setHeader("Content-Type", "text/html; charset=iso-8859-1");
-        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
-    }
-
-    private User getUser(String username) {
-        return userService.findUser(username);
-    }
-
-    private User loginByBase(String authorization) {
-        authorization = Coder.decodeBase64(authorization);
-        int i = authorization.indexOf(':');
-        String username = authorization.substring(0, i);
-        if (username != null && username.length() > 0) {
-            String password = authorization.substring(i + 1);
-            if (password != null && password.length() > 0) {
-                String passwordDigest = Coder.encodeMd5(username + ":" + REALM + ":" + password);
-                User user = getUser(username);
-                if (user != null) {
-                    String pwd = user.getPassword();
-                    if (pwd != null && pwd.length() > 0) {
-                        if (passwordDigest.equals(pwd)) {
-                            return user;
-                        }
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    private User loginByDigest(String value, HttpServletRequest request) throws IOException {
-        Map<String, String> params = parseParameters(value);
-        String username = params.get("username");
-        if (username != null && username.length() > 0) {
-            String passwordDigest = params.get("response");
-            if (passwordDigest != null && passwordDigest.length() > 0) {
-                User user = getUser(username);
-                if (user != null) {
-                    String pwd = user.getPassword();
-                    // A valid user, validate password
-                    if (pwd != null && pwd.length() > 0) {
-                        String uri = params.get("uri");
-                        String nonce = params.get("nonce");
-                        String nc = params.get("nc");
-                        String cnonce = params.get("cnonce");
-                        String qop = params.get("qop");
-                        String method = request.getMethod();
-                        String a1 = pwd;
-
-                        String a2 = "auth-int".equals(qop)
-                            ? Coder.encodeMd5(method + ":" + uri + ":" + Coder.encodeMd5(readToBytes(request.getInputStream())))
-                            : Coder.encodeMd5(method + ":" + uri);
-                        String digest = "auth".equals(qop) || "auth-int".equals(qop)
-                            ? Coder.encodeMd5(a1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + a2)
-                            : Coder.encodeMd5(a1 + ":" + nonce + ":" + a2);
-                        if (digest.equals(passwordDigest)) {
-                            return user;
-                        }
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    private boolean isLogout(HttpServletRequest request) {
-        Cookie[] cookies = request.getCookies();
-        if (cookies != null && cookies.length > 0) {
-            for (Cookie cookie : cookies) {
-                if (cookie != null && logoutCookie.equals(cookie.getName())) {
-                    return "true".equals(cookie.getValue());
-                }
-            }
-        }
-        return false;
-    }
-
-    private void setLogout(boolean logoutValue, HttpServletResponse response) {
-        response.addCookie(new Cookie(logoutCookie, String.valueOf(logoutValue)));
-    }
-}
-
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/biz/common/i18n/MessageResourceService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/biz/common/i18n/MessageResourceService.java
deleted file mode 100644
index cb527ab..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/biz/common/i18n/MessageResourceService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.governance.biz.common.i18n;
-
-public interface MessageResourceService {
-
-    public String get(String key, Object... args);
-
-    public String getMessage(String key, Object... args);
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/biz/common/i18n/impl/MessageResourceServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/biz/common/i18n/impl/MessageResourceServiceImpl.java
deleted file mode 100644
index a352778..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/biz/common/i18n/impl/MessageResourceServiceImpl.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.governance.biz.common.i18n.impl;
-
-
-import org.apache.dubbo.admin.governance.biz.common.i18n.MessageResourceService;
-import org.apache.dubbo.admin.web.mvc.common.i18n.LocaleUtil;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.MessageSource;
-import org.springframework.context.NoSuchMessageException;
-import org.springframework.stereotype.Component;
-
-@Component
-public class MessageResourceServiceImpl implements MessageResourceService {
-
-    @Autowired
-    private MessageSource messageSource;
-
-    public void setMessageSource(MessageSource messageSource) {
-        this.messageSource = messageSource;
-    }
-
-    public String get(String key, Object... args) {
-        try {
-            if (messageSource != null) {
-                return messageSource.getMessage(key, args, key, LocaleUtil.getLocale());
-            }
-            return key;
-        } catch (NoSuchMessageException e) {
-            return key;
-        }
-    }
-
-    public String getMessage(String key, Object... args) {
-        return get(key, args);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OverrideService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OverrideService.java
deleted file mode 100644
index e00ebc6..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OverrideService.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.governance.service;
-
-import org.apache.dubbo.admin.registry.common.domain.Override;
-
-import java.util.List;
-
-public interface OverrideService {
-
-    void saveOverride(Override override);
-
-    void updateOverride(Override override);
-
-    void deleteOverride(String id);
-
-    void enableOverride(String id);
-
-    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);
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/RouteService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/RouteService.java
deleted file mode 100644
index 4aa5cc6..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/RouteService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.governance.service;
-
-import org.apache.dubbo.admin.registry.common.domain.Route;
-
-import java.util.List;
-
-/**
- * RouteService
- *
- */
-public interface RouteService {
-
-    void createRoute(Route route);
-
-    void updateRoute(Route route);
-
-    void deleteRoute(String id);
-
-    void enableRoute(String id);
-
-    void disableRoute(String id);
-
-    Route findRoute(String id);
-
-    List<Route> findAll();
-
-    List<Route> findByService(String serviceName);
-
-    List<Route> findByAddress(String address);
-
-    List<Route> findByServiceAndAddress(String service, String address);
-
-    List<Route> findForceRouteByService(String service);
-
-    List<Route> findForceRouteByAddress(String address);
-
-    List<Route> findForceRouteByServiceAndAddress(String service, String address);
-
-    List<Route> findAllForceRoute();
-
-    Route getBlackwhitelistRouteByService(String service);
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/UserService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/UserService.java
deleted file mode 100644
index 21bab2d..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/UserService.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.governance.service;
-
-import org.apache.dubbo.admin.registry.common.domain.User;
-
-import java.util.List;
-
-/**
- * UserService
- *
- */
-public interface UserService {
-
-    List<User> findAllUsers();
-
-    User findUser(String username);
-
-    User findById(Long id);
-
-    void createUser(User user);
-
-    void updateUser(User user);
-
-    void modifyUser(User user);
-
-    boolean updatePassword(User user, String oldPassword);
-
-    void resetPassword(User user);
-
-    void enableUser(User user);
-
-    void disableUser(User user);
-
-    void deleteUser(User user);
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ConfigServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ConfigServiceImpl.java
deleted file mode 100644
index 9cfa0d6..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ConfigServiceImpl.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.governance.service.impl;
-
-import org.apache.dubbo.admin.governance.service.ConfigService;
-import org.apache.dubbo.admin.registry.common.domain.Config;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * TODO Comment of IbatisConfigDAO
- *
- */
-public class ConfigServiceImpl extends AbstractService implements ConfigService {
-
-    /* (non-Javadoc)
-     * @see com.alibaba.dubbo.governance.service.ConfigService#update(java.util.List)
-     */
-    public void update(List<Config> configs) {
-        // TODO Auto-generated method stub
-
-    }
-
-    /* (non-Javadoc)
-     * @see com.alibaba.dubbo.governance.service.ConfigService#findAllConfigsMap()
-     */
-    public Map<String, String> findAllConfigsMap() {
-        // TODO Auto-generated method stub
-        return null;
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/OverrideServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/OverrideServiceImpl.java
deleted file mode 100644
index f1d80e1..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/OverrideServiceImpl.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.governance.service.impl;
-
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.governance.sync.util.Pair;
-import org.apache.dubbo.admin.governance.sync.util.SyncUtils;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * IbatisOverrideDAO.java
- *
- */
-@Component
-public class OverrideServiceImpl extends AbstractService implements OverrideService {
-
-    public void saveOverride(Override override) {
-        URL url = getUrlFromOverride(override);
-        registryService.register(url);
-    }
-
-    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!");
-        }
-        URL newOverride = getUrlFromOverride(override);
-
-        registryService.unregister(oldOverride);
-        registryService.register(newOverride);
-
-    }
-
-    public void deleteOverride(String id) {
-        URL oldOverride = findOverrideUrl(id);
-        if (oldOverride == null) {
-            throw new IllegalStateException("Route was changed!");
-        }
-        registryService.unregister(oldOverride);
-    }
-
-    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 (oldOverride.getParameter("enabled", true)) {
-            return;
-        }
-
-        URL newOverride = oldOverride.addParameter("enabled", true);
-        registryService.unregister(oldOverride);
-        registryService.register(newOverride);
-
-    }
-
-    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 (!oldProvider.getParameter("enabled", true)) {
-            return;
-        }
-
-        URL newProvider = oldProvider.addParameter("enabled", false);
-        registryService.unregister(oldProvider);
-        registryService.register(newProvider);
-
-    }
-
-    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);
-        }
-        if (application != null && application.length() > 0) {
-            filter.put(Constants.APPLICATION_KEY, application);
-        }
-        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();
-        /*Map<String, String> params = ConvertUtil.serviceName2Map(override.getService());
-        if(!params.containsKey(Constants.INTERFACE_KEY)) {
-            throw new IllegalArgumentException("No interface info");
-        }
-        if(!params.containsKey(Constants.VERSION_KEY)) {
-            throw new IllegalArgumentException("No version info");
-        }
-        
-        boolean enabled = override.isEnabled();
-        if(!enabled) {
-            params.put("enabled", "false");
-        }
-        String application = override.getApplication();
-        if(!StringUtils.isEmpty(application)) {
-            params.put("application", application);
-        }
-        String address = override.getAddress();
-        if(!StringUtils.isEmpty(address)) {
-            params.put("address", address);
-        }
-        
-        String overrideAddress = override.getOverrideAddress();
-        if(StringUtils.isEmpty(overrideAddress)) {
-            overrideAddress = "0.0.0.0";
-        }
-        params.put(Constants.CATEGORY_KEY, Constants.CONFIGURATORS_CATEGORY);
-        
-        URL url = new URL("override", overrideAddress, -1, params);
-        url = url.addParameterString(override.getParams());
-        return url;*/
-    }
-
-    URL findOverrideUrl(String id) {
-        return getUrlFromOverride(findById(id));
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/OwnerServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/OwnerServiceImpl.java
deleted file mode 100644
index e80e149..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/OwnerServiceImpl.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.governance.service.impl;
-
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.governance.service.OwnerService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.domain.Owner;
-import org.apache.dubbo.admin.registry.common.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/governance/service/impl/ProviderServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ProviderServiceImpl.java
deleted file mode 100644
index 04ebe31..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ProviderServiceImpl.java
+++ /dev/null
@@ -1,473 +0,0 @@
-/*
- * 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.governance.service.impl;
-
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.governance.sync.util.Pair;
-import org.apache.dubbo.admin.governance.sync.util.SyncUtils;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
-import org.apache.dubbo.admin.registry.common.route.ParseUtils;
-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;
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * IbatisProviderService
- *
- */
-@Component
-public class ProviderServiceImpl extends AbstractService implements ProviderService {
-
-    @Autowired
-    OverrideService overrideService;
-
-    public void create(Provider provider) {
-        URL url = provider.toUrl();
-        registryService.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 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;
-        if (value != null && value.length() > 0) {
-            weight = Integer.parseInt(value);
-        }
-        weight = (int) (weight * factor);
-        if (weight < 1) weight = 1;
-        if (weight == 2) weight = 3;
-        if (weight == 24) weight = 25;
-        return weight;
-    }
-
-    public void deleteStaticProvider(String id) {
-        URL oldProvider = findProviderUrl(id);
-        if (oldProvider == null) {
-            throw new IllegalStateException("Provider was changed!");
-        }
-        registryService.unregister(oldProvider);
-    }
-
-    public void updateProvider(Provider provider) {
-        String hash = provider.getHash();
-        if (hash == null) {
-            throw new IllegalStateException("no provider id");
-        }
-
-        URL oldProvider = findProviderUrl(hash);
-        if (oldProvider == null) {
-            throw new IllegalStateException("Provider was changed!");
-        }
-        URL newProvider = provider.toUrl();
-
-        registryService.unregister(oldProvider);
-        registryService.register(newProvider);
-    }
-
-    public Provider findProvider(String id) {
-        return SyncUtils.url2Provider(findProviderUrlPair(id));
-    }
-
-    public Pair<String, URL> findProviderUrlPair(String id) {
-        return SyncUtils.filterFromCategory(getRegistryCache(), Constants.PROVIDERS_CATEGORY, id);
-    }
-
-    public List<String> findServices() {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls != null) ret.addAll(providerUrls.keySet());
-        return ret;
-    }
-
-    public List<String> findAddresses() {
-        List<String> ret = new ArrayList<String>();
-
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (null == providerUrls) return ret;
-
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> e2 : value.entrySet()) {
-                URL u = e2.getValue();
-                String app = u.getAddress();
-                if (app != null) ret.add(app);
-            }
-        }
-
-        return ret;
-    }
-
-    public List<String> findAddressesByApplication(String application) {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> e2 : value.entrySet()) {
-                URL u = e2.getValue();
-                if (application.equals(u.getParameter(Constants.APPLICATION_KEY))) {
-                    String addr = u.getAddress();
-                    if (addr != null) ret.add(addr);
-                }
-            }
-        }
-
-        return ret;
-    }
-
-    public List<String> findAddressesByService(String service) {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (null == providerUrls) return ret;
-
-        for (Map.Entry<String, URL> e2 : providerUrls.get(service).entrySet()) {
-            URL u = e2.getValue();
-            String app = u.getAddress();
-            if (app != null) ret.add(app);
-        }
-
-        return ret;
-    }
-
-    public List<String> findApplicationsByServiceName(String service) {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (null == providerUrls) return ret;
-
-        Map<String, URL> value = providerUrls.get(service);
-        if (value == null) {
-            return ret;
-        }
-        for (Map.Entry<String, URL> e2 : value.entrySet()) {
-            URL u = e2.getValue();
-            String app = u.getParameter(Constants.APPLICATION_KEY);
-            if (app != null) ret.add(app);
-        }
-
-        return ret;
-    }
-
-    public List<Provider> findByService(String serviceName) {
-        return SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
-    }
-
-    public List<Provider> findByAppandService(String app, String serviceName) {
-        return SyncUtils.url2ProviderList(findProviderUrlByAppandService(app, serviceName));
-    }
-
-    private Map<String, URL> findProviderUrlByService(String service) {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
-
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public List<Provider> findAll() {
-        return SyncUtils.url2ProviderList(findAllProviderUrl());
-    }
-
-    private Map<String, URL> findAllProviderUrl() {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public List<Provider> findByAddress(String providerAddress) {
-        return SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
-    }
-
-    public Map<String, URL> findProviderUrlByAddress(String address) {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
-
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public List<String> findServicesByAddress(String address) {
-        List<String> ret = new ArrayList<String>();
-
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null || address == null || address.length() == 0) return ret;
-
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> e2 : value.entrySet()) {
-                URL u = e2.getValue();
-                if (address.equals(u.getAddress())) {
-                    ret.add(e1.getKey());
-                    break;
-                }
-            }
-        }
-
-        return ret;
-    }
-
-    public List<String> findApplications() {
-        List<String> ret = new ArrayList<String>();
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null) return ret;
-
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> e2 : value.entrySet()) {
-                URL u = e2.getValue();
-                String app = u.getParameter(Constants.APPLICATION_KEY);
-                if (app != null) ret.add(app);
-            }
-        }
-
-        return ret;
-    }
-
-    public List<Provider> findByApplication(String application) {
-        return SyncUtils.url2ProviderList(findProviderUrlByApplication(application));
-    }
-
-    private Map<String, URL> findProviderUrlByAppandService(String app, String service) {
-        Map<String, String> filter = new HashMap<>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        filter.put(Constants.APPLICATION_KEY, app);
-        filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-
-    private Map<String, URL> findProviderUrlByApplication(String application) {
-        Map<String, String> filter = new HashMap<>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        filter.put(Constants.APPLICATION_KEY, application);
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public List<String> findServicesByApplication(String application) {
-        List<String> ret = new ArrayList<String>();
-
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null || application == null || application.length() == 0) return ret;
-
-        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
-            Map<String, URL> value = e1.getValue();
-            for (Map.Entry<String, URL> e2 : value.entrySet()) {
-                URL u = e2.getValue();
-                if (application.equals(u.getParameter(Constants.APPLICATION_KEY))) {
-                    ret.add(e1.getKey());
-                    break;
-                }
-            }
-        }
-
-        return ret;
-    }
-
-    public List<String> findMethodsByService(String service) {
-        List<String> ret = new ArrayList<String>();
-
-        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
-        if (providerUrls == null || service == null || service.length() == 0) return ret;
-
-        Map<String, URL> providers = providerUrls.get(service);
-        if (null == providers || providers.isEmpty()) return ret;
-
-        Entry<String, URL> p = providers.entrySet().iterator().next();
-        String value = p.getValue().getParameter("methods");
-        if (value == null || value.length() == 0) {
-            return ret;
-        }
-        String[] methods = value.split(ParseUtils.METHOD_SPLIT);
-        if (methods == null || methods.length == 0) {
-            return ret;
-        }
-
-        for (String m : methods) {
-            ret.add(m);
-        }
-        return ret;
-    }
-
-    private URL findProviderUrl(String id) {
-        return findProvider(id).toUrl();
-    }
-
-    public Provider findByServiceAndAddress(String service, String address) {
-        return SyncUtils.url2Provider(findProviderUrl(service, address));
-    }
-
-    private Pair<String, URL> findProviderUrl(String service, String address) {
-        Map<String, String> filter = new HashMap<String, String>();
-        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-        filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
-
-        Map<String, URL> ret = SyncUtils.filterFromCategory(getRegistryCache(), filter);
-        if (ret.isEmpty()) {
-            return null;
-        } else {
-            String key = ret.entrySet().iterator().next().getKey();
-            return new Pair<String, URL>(key, ret.get(key));
-        }
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/RouteServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/RouteServiceImpl.java
deleted file mode 100644
index 6c9a9a1..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/RouteServiceImpl.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * 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.governance.service.impl;
-
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import org.apache.dubbo.admin.dto.AccessDTO;
-import org.apache.dubbo.admin.governance.service.RouteService;
-import org.apache.dubbo.admin.governance.sync.util.Pair;
-import org.apache.dubbo.admin.governance.sync.util.SyncUtils;
-import org.apache.dubbo.admin.registry.common.domain.Route;
-import org.springframework.stereotype.Component;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * IbatisRouteService
- *
- */
-@Component
-public class RouteServiceImpl extends AbstractService implements RouteService {
-
-    public void createRoute(Route route) {
-        registryService.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!");
-        }
-
-        registryService.unregister(oldRoute);
-        registryService.register(route.toUrl());
-    }
-
-    public void deleteRoute(String id) {
-        URL oldRoute = findRouteUrl(id);
-        if (oldRoute == null) {
-            throw new IllegalStateException("Route was changed!");
-        }
-        registryService.unregister(oldRoute);
-    }
-
-    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;
-        }
-
-        registryService.unregister(oldRoute);
-        URL newRoute = oldRoute.addParameter("enabled", true);
-        registryService.register(newRoute);
-
-    }
-
-    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);
-        registryService.unregister(oldRoute);
-        registryService.register(newRoute);
-
-    }
-
-    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));
-    }
-
-    public Pair<String, URL> findRouteUrlPair(String id) {
-        return SyncUtils.filterFromCategory(getRegistryCache(), Constants.ROUTERS_CATEGORY, id);
-    }
-
-    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");
-        }
-        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
-    }
-
-    public List<Route> findByService(String serviceName) {
-        return SyncUtils.url2RouteList(findRouteUrl(serviceName, null, false));
-    }
-
-    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));
-    }
-
-    public List<Route> findForceRouteByService(String service) {
-        return SyncUtils.url2RouteList(findRouteUrl(service, null, true));
-    }
-
-    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));
-    }
-
-    public List<Route> findAllForceRoute() {
-        return SyncUtils.url2RouteList(findRouteUrl(null, null, true));
-    }
-
-    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;
-            }
-        }
-        return null;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/UserServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/UserServiceImpl.java
deleted file mode 100644
index 01a6b24..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/UserServiceImpl.java
+++ /dev/null
@@ -1,133 +0,0 @@
-///*
-// * 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.governance.service.impl;
-//
-//import org.apache.dubbo.admin.governance.service.UserService;
-//import org.apache.dubbo.admin.registry.common.domain.User;
-//import org.apache.dubbo.admin.registry.common.util.Coder;
-//import org.springframework.beans.factory.annotation.Value;
-//import org.springframework.stereotype.Component;
-//
-//import java.util.List;
-//import java.util.Map;
-//
-///**
-// * IBatisUserService
-// *
-// */
-//@Component
-//public class UserServiceImpl extends AbstractService implements UserService {
-//
-////    @Value("${spring.root.password}")
-////    private String rootPassword;
-////    @Value("${spring.guest.password}")
-////    private String guestPassword;
-//
-//    public void setRootPassword(String password) {
-//        this.rootPassword = (password == null ? "" : password);
-//    }
-//
-//    public void setGuestPassword(String password) {
-//        this.guestPassword = (password == null ? "" : password);
-//    }
-//
-//    public User findUser(String username) {
-//        if ("guest".equals(username)) {
-//            User user = new User();
-//            user.setUsername(username);
-//            user.setPassword(Coder.encodeMd5(username + ":" + User.REALM + ":" + guestPassword));
-//            user.setName(username);
-//            user.setRole(User.GUEST);
-//            user.setEnabled(true);
-//            user.setLocale("zh");
-//            user.setServicePrivilege("");
-//            return user;
-//        } else if ("root".equals(username)) {
-//            User user = new User();
-//            user.setUsername(username);
-//            user.setPassword(Coder.encodeMd5(username + ":" + User.REALM + ":" + rootPassword));
-//            user.setName(username);
-//            user.setRole(User.ROOT);
-//            user.setEnabled(true);
-//            user.setLocale("zh");
-//            user.setServicePrivilege("*");
-//            return user;
-//        }
-//        return null;
-//    }
-//
-//    public List<User> findAllUsers() {
-//        // TODO Auto-generated method stub
-//        return null;
-//    }
-//
-//    public Map<String, User> findAllUsersMap() {
-//        // TODO Auto-generated method stub
-//        return null;
-//    }
-//
-//    public User findById(Long id) {
-//        // TODO Auto-generated method stub
-//        return null;
-//    }
-//
-//    public void createUser(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public void updateUser(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public void modifyUser(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public boolean updatePassword(User user, String oldPassword) {
-//        // TODO Auto-generated method stub
-//        return false;
-//    }
-//
-//    public void resetPassword(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public void enableUser(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public void disableUser(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public void deleteUser(User user) {
-//        // TODO Auto-generated method stub
-//
-//    }
-//
-//    public List<User> findUsersByServiceName(String serviceName) {
-//        // TODO Auto-generated method stub
-//        return null;
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/GovernanceWarmup.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/GovernanceWarmup.java
deleted file mode 100644
index b41e1ac..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/GovernanceWarmup.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.governance.util;
-
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import com.alibaba.dubbo.common.status.StatusChecker;
-import org.apache.dubbo.admin.registry.common.StatusManager;
-import org.springframework.beans.factory.InitializingBean;
-
-public class GovernanceWarmup implements InitializingBean {
-
-    private static final Logger logger = LoggerFactory.getLogger(GovernanceWarmup.class);
-
-    private StatusChecker memoryStatusChecker;
-
-    private StatusChecker threadPoolStatusChecker;
-
-    private StatusChecker cacheStatusChecker;
-
-    private StatusChecker databaseStatusChecker;
-
-    private StatusChecker failureStatusChecker;
-
-    private StatusChecker loadStatusChecker;
-
-    private StatusChecker SocketStatusChecker;
-
-    private StatusChecker timerStatusChecker;
-
-    private StatusChecker warmupStatusChecker;
-
-    public void afterPropertiesSet() throws Exception {
-        logger.info("Registry Console warn up.");
-
-        StatusManager statusManager = StatusManager.getInstance();
-
-        statusManager.addStatusHandler("memory", memoryStatusChecker);
-        statusManager.addStatusHandler("load", loadStatusChecker);
-//        statusManager.addStatusHandler("database",databaseStatusChecker);
-//        statusManager.addStatusHandler("cache",cacheStatusChecker);
-//        statusManager.addStatusHandler("threadpool",threadPoolStatusChecker);
-//        statusManager.addStatusHandler("failure",failureStatusChecker);
-//        statusManager.addStatusHandler("socket",SocketStatusChecker);
-//        statusManager.addStatusHandler("threadpool",threadPoolStatusChecker);
-//        statusManager.addStatusHandler("timer",timerStatusChecker);
-//        statusManager.addStatusHandler("warmup",warmupStatusChecker);
-    }
-
-    public void setMemoryStatusChecker(StatusChecker memoryStatusChecker) {
-        this.memoryStatusChecker = memoryStatusChecker;
-    }
-
-
-    public void setThreadPoolStatusChecker(StatusChecker threadPoolStatusChecker) {
-        this.threadPoolStatusChecker = threadPoolStatusChecker;
-    }
-
-
-    public void setCacheStatusChecker(StatusChecker cacheStatusChecker) {
-        this.cacheStatusChecker = cacheStatusChecker;
-    }
-
-
-    public void setDatabaseStatusChecker(StatusChecker databaseStatusChecker) {
-        this.databaseStatusChecker = databaseStatusChecker;
-    }
-
-
-    public void setFailureStatusChecker(StatusChecker failureStatusChecker) {
-        this.failureStatusChecker = failureStatusChecker;
-    }
-
-
-    public void setLoadStatusChecker(StatusChecker loadStatusChecker) {
-        this.loadStatusChecker = loadStatusChecker;
-    }
-
-
-    public void setSocketStatusChecker(StatusChecker socketStatusChecker) {
-        SocketStatusChecker = socketStatusChecker;
-    }
-
-
-    public void setTimerStatusChecker(StatusChecker timerStatusChecker) {
-        this.timerStatusChecker = timerStatusChecker;
-    }
-
-    public void setWarmupStatusChecker(StatusChecker warmupStatusChecker) {
-        this.warmupStatusChecker = warmupStatusChecker;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/Paginator.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/Paginator.java
deleted file mode 100644
index 3e4c122..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/Paginator.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.governance.util;
-
-import java.io.Serializable;
-
-/**
- * TODO Comment of Paginator
- *
- */
-public class Paginator implements Serializable, Cloneable {
-
-    private static final long serialVersionUID = 3688506614705500726L;
-
-    // The default number of items per page; default is 10
-    int itemsPerPage = 10;
-
-    // Sliding window default size; default: 7
-    int sliderSize = 7;
-
-    // The current page.
-    int currentPage;
-
-    // The current page.
-    String path;
-
-    // total mumber of items
-    int totalItems;
-
-    // total number of pages
-    int totalPage;
-
-    /**
-     * The most simple paging constructor.
-     *
-     * @param currentPage
-     * @param totalItems
-     * @param path
-     */
-    public Paginator(int currentPage, int totalItems, String path) {
-        initPagination(currentPage, totalItems, 0, 0, path);
-    }
-
-    public Paginator(String currentPage, int totalItems, String path) {
-        int currentPageTemp = 1;
-        if (!(currentPage == null || currentPage.equals(""))) {
-            currentPageTemp = Integer.parseInt(currentPage);
-        }
-        initPagination(currentPageTemp, totalItems, 0, 0, path);
-    }
-
-    /**
-     * Complete paging constructor.
-     *
-     * @param currentPageT
-     * @param totalItemsT
-     * @param sliderSizeT
-     * @param itemsPerPageT
-     * @param path
-     */
-    public void initPagination(int currentPageT, int totalItemsT, int sliderSizeT, int itemsPerPageT, String path) {
-        this.totalItems = (totalItemsT > 0) ? totalItemsT : 0;
-        this.sliderSize = (sliderSizeT > 0) ? sliderSizeT : sliderSize;
-        this.itemsPerPage = (itemsPerPageT > 0) ? itemsPerPageT : itemsPerPage;
-        this.totalPage = totalItems / itemsPerPage + (totalItems % itemsPerPage == 0 ? 0 : 1);
-        this.currentPage = (currentPageT > 0) ? currentPageT : 1;
-        this.currentPage = currentPage < totalPage ? currentPage : totalPage;
-        this.currentPage = (currentPage == 0) ? 1 : currentPage;
-        this.path = path;
-    }
-
-    public int getItemsPerPage() {
-        return this.itemsPerPage;
-    }
-
-    /**
-     * Get a sliding window of fixed size, and the current page should lie in the middle of the sliding window.
-     * For example: a total of 13 pages, the current page is page 5, a size of 5 sliding window should consists of 3,4,5,6,7, page 5 is placed in the middle. If the current page is 12, the return page number should be 9, 10, 11, 12, 13.
-     *
-     * @return An array containing page numbers, or an empty array if the specified sliding window size is less than 1 or the total number of pages is zero.
-     */
-    public int[] getSlider() {
-        int width = sliderSize;
-        if ((totalItems < 1)) {
-            return new int[0];
-
-        } else {
-            if (width > totalPage) {
-                width = totalPage;
-            }
-
-            int[] slider = new int[width];
-
-            int startPage = currentPage - ((width - 1) / 2);
-
-            if (startPage < 1) {
-                startPage = 1;
-            }
-
-            if (((startPage + width) - 1) > totalPage) {
-                startPage = totalPage - width + 1;
-            }
-
-            for (int i = 0; i < width; i++) {
-                slider[i] = startPage + i;
-            }
-            return slider;
-        }
-    }
-
-    /**
-     * Construction pagination toolbar
-     */
-    public String getPaginatorBar() {
-
-        StringBuffer str = new StringBuffer("<div class=\"page\">");
-        str.append("<script type=\"text/javascript\">function gotoPage(page){window.location.href=\"/" + path
-                + "/pages/\" + page;}</script>");
-
-        // generate flip section
-        // The total number of records
-        str.append("total items: " + this.totalItems + "&nbsp;&nbsp;");
-
-        // 2. Pages: current page / total pages
-        str.append("page " + this.currentPage + " of " + this.totalPage + "nbsp;&nbsp;");
-
-        // 3. Home, Previous
-        if (this.currentPage > 1) {
-            str.append("<a class=\"prev\" href=\"#\" onclick=\"gotoPage(1);\">Home</a>");
-            str.append("<a class=\"prev\" href=\"#\" onclick=\"gotoPage(" + (this.currentPage - 1) + ");\">Previous</a>");
-        } else {
-            str.append("<a class=\"prev\" href=\"#\">Home</a>");
-            str.append("<a class=\"prev\" href=\"#\">Previous</a>");
-        }
-
-        // 4. Activity block
-        int[] slider = getSlider();
-        for (int i = 0; i < slider.length; i++) {
-            if (slider[i] == this.currentPage) {
-                str.append("<a class=\"num current_num\" href=\"#\">");
-            } else {
-                str.append("<a class=\"num\" href=\"#\" onclick=\"gotoPage(" + slider[i] + ");\">");
-            }
-            str.append(slider[i] + "</a>");
-        }
-
-        // 5. Next page
-        if (this.currentPage < this.totalPage) {
-            str.append("<a class=\"prev\" href=\"#\" onclick=\"gotoPage(" + (this.currentPage + 1) + ");\">");
-        } else {
-            str.append("<a class=\"prev\" href=\"#\">");
-        }
-        str.append("Next</a>&nbsp;&nbsp;");
-
-        // 6. Jump section
-        str.append("jump to page ");
-        str.append("<SELECT size=1 onchange=\"gotoPage(this.value);\">");
-        for (int i = 1; i < this.totalPage + 1; i++) {
-            if (i == this.currentPage) {
-                str.append("<OPTION value=" + i + " selected>" + i + "</OPTION>");
-            } else {
-                str.append("<OPTION value=" + i + ">" + i + "</OPTION>");
-            }
-        }
-        str.append("</SELECT>");
-
-        // 7. Implicit conditions
-        str.append("</div>");
-        return str.toString();
-    }
-
-    /**
-     * Get the initial record
-     *
-     * @return
-     */
-    public int getStartIndex() {
-        return (this.currentPage - 1) * this.itemsPerPage + 1;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/WebConstants.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/WebConstants.java
deleted file mode 100644
index aebaaf6..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/util/WebConstants.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.governance.util;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Contains the constants used in the web layer
- *
- */
-public class WebConstants {
-
-    /**
-     * In the session to save the current user object's key.
-     */
-    public static final String CURRENT_USER_KEY = "currentUser";
-    /**
-     * The current registered server address
-     */
-    public static final String REGISTRY_ADDRESS = "registryAddress";
-    /**
-     * Service exposed address
-     */
-    public static final String SERVICE_URL = "serviceUrl";
-    /**
-     * Service name
-     */
-    public static final String SERVICE_NAME = "serviceName";
-    /**
-     * Service name
-     */
-    public static final String ENTRY = "entry";
-    /**
-     * buc sso logout
-     */
-    public static final String SSO_LOGOUT_URL = "SSO_LOGOUT_URL";
-    /**
-     * buc sso logon
-     */
-    public static final String BUC_SSO_USERNAME = "buc_sso_username";
-    /**
-     * Operation record page The default page record shows the number of records
-     */
-    public static final Integer OPRATION_RECORDS_PAGE_SIZE = 100;
-
-    /**
-     * Help Url
-     */
-    public static final String HELP_URL="https://github.com/apache/incubator-dubbo-ops";
-    Map<String, Object> context;
-
-    public static final Map<String, String> mapper = new HashMap<>();
-
-    static {
-        mapper.put("providers", "providersController");
-        mapper.put("consumers", "consumersController");
-        mapper.put("applications", "applicationsController");
-        mapper.put("routes", "routesController");
-        mapper.put("overrides", "overridesController");
-        mapper.put("accesses", "accessesController");
-        mapper.put("loadbalances", "loadbalancesController");
-        mapper.put("owners", "ownersController");
-        mapper.put("weights", "weightsController");
-        mapper.put("addresses", "addressesController");
-        mapper.put("services", "servicesController");
-    }
-
-
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/handler/CustomExceptionHandler.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/handler/CustomExceptionHandler.java
index 94c4a22..bbba539 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/handler/CustomExceptionHandler.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/handler/CustomExceptionHandler.java
@@ -16,13 +16,13 @@
  */
 package org.apache.dubbo.admin.handler;
 
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.admin.common.CommonResponse;
 import org.apache.dubbo.admin.common.exception.ParamValidationException;
 import org.apache.dubbo.admin.common.exception.PermissionDeniedException;
 import org.apache.dubbo.admin.common.exception.ResourceNotFoundException;
 import org.apache.dubbo.admin.common.exception.ServiceException;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Access.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Access.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Access.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Access.java
index 19c187f..0eb6715 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Access.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Access.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 public class Access extends Entity {
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Agreement.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Agreement.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Agreement.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Agreement.java
index 5e11877..87cb997 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Agreement.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Agreement.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Specifies the applied Quality of Service Level Agreement (SLA) object.
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Approval.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Approval.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Approval.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Approval.java
index ff37545..abeb8d4 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Approval.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Approval.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Service online approval.
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/ApprovalRequisition.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/ApprovalRequisition.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/ApprovalRequisition.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/ApprovalRequisition.java
index 8e3ff2d..70b3af8 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/ApprovalRequisition.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/ApprovalRequisition.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Service online / offline approval
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Change.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Change.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Change.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Change.java
index 846f3d8..957e2af 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Change.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Change.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Service change information object
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Cluster.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Cluster.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Cluster.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Cluster.java
index 820a2ee..b6b86cc 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Cluster.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Cluster.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 public class Cluster extends Entity {
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Config.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Config.java
similarity index 98%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Config.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Config.java
index 2181c87..7c4b330 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Config.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Config.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Config instance
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Consumer.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java
similarity index 90%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Consumer.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java
index 142c5a5..93d9835 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Consumer.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Consumer.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
 
 import java.util.Date;
 import java.util.List;
@@ -54,7 +54,7 @@
 
     private List<Override> overrides;
 
-    private List<Route> routes;
+    private List<Route> conditionRoutes;
 
     private List<Provider> providers;
 
@@ -176,12 +176,12 @@
         this.overrides = overrides;
     }
 
-    public List<Route> getRoutes() {
-        return routes;
+    public List<Route> getConditionRoutes() {
+        return conditionRoutes;
     }
 
-    public void setRoutes(List<Route> routes) {
-        this.routes = routes;
+    public void setConditionRoutes(List<Route> conditionRoutes) {
+        this.conditionRoutes = conditionRoutes;
     }
 
     public List<Provider> getProviders() {
@@ -196,7 +196,7 @@
         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/registry/common/domain/Document.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Document.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Document.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Document.java
index f529bbe..ea08450 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Document.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Document.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Document
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Entity.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Entity.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java
index ad2256b..3982d62 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Entity.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Entity.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 import java.io.Serializable;
 import java.util.Date;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Favorite.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Favorite.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Favorite.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Favorite.java
index cd3e648..17d9634 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Favorite.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Favorite.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 public class Favorite extends Entity {
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Feature.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Feature.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Feature.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Feature.java
index c9d1eb9..4318e47 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Feature.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Feature.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * System features
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Layer.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Layer.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Layer.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Layer.java
index 3e19554..8dce680 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Layer.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Layer.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 public class Layer extends Entity {
     private static final long serialVersionUID = 6114868933223039253L;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/LoadBalance.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/LoadBalance.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/LoadBalance.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/LoadBalance.java
index f0e1075..6062460 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/LoadBalance.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/LoadBalance.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * LoadBalance
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Mock.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Mock.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Mock.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Mock.java
index 48e2c58..1b714ad 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Mock.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Mock.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 /**
  * Mock
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Operation.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Operation.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java
index 96ecb20..4a9e2ca 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Operation.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Operation.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -28,7 +28,7 @@
 
     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/registry/common/domain/Override.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Override.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java
index 5487a70..ff79fad 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Override.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Override.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
 
 import java.util.Map;
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Owner.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Owner.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Owner.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Owner.java
index ab8301c..9f91bea 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Owner.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Owner.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 public class Owner extends Entity {
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Provider.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
similarity index 95%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Provider.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
index ccc95cd..6d4763a 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Provider.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Provider.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import org.apache.dubbo.admin.registry.common.registry.ConvertUtil;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
 
 import java.util.Date;
 import java.util.List;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Registry.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Registry.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Registry.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Registry.java
index 4531e32..3c56209 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Registry.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Registry.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 import java.util.Date;
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Route.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Route.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java
index d5531b3..5547bc4 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Route.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Route.java
@@ -14,19 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
+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";
 
@@ -231,5 +228,4 @@
                 + (group == null ? "" : "&" + Constants.GROUP_KEY + "=" + group)
                 + (version == null ? "" : "&" + Constants.VERSION_KEY + "=" + version));
     }
-
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BaseDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Tag.java
similarity index 67%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BaseDTO.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Tag.java
index 3bb2252..75ea77e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BaseDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Tag.java
@@ -14,21 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.dto;
 
-/**
- * BaseDTO
- *
- * For receive ID parameter with @RequestBody
- */
-public abstract class BaseDTO {
-    private String id;
+package org.apache.dubbo.admin.model.domain;
 
-    public String getId() {
-        return id;
+public class Tag {
+    String name;
+    String[] addresses;
+
+    public String getName() {
+        return name;
     }
 
-    public void setId(String id) {
-        this.id = id;
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String[] getAddresses() {
+        return addresses;
+    }
+
+    public void setAddresses(String[] addresses) {
+        this.addresses = addresses;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/User.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/User.java
similarity index 98%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/User.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/User.java
index 821f012..4038e12 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/User.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/User.java
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
-import org.apache.dubbo.admin.registry.common.route.ParseUtils;
+import org.apache.dubbo.admin.common.util.ParseUtils;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Weight.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Weight.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Weight.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Weight.java
index 0fa064f..fb2f175 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Weight.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/domain/Weight.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
+package org.apache.dubbo.admin.model.domain;
 
 public class Weight extends Entity {
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/AccessDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/AccessDTO.java
similarity index 82%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/AccessDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/AccessDTO.java
index c739ed1..8b8e7b4 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/AccessDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/AccessDTO.java
@@ -14,24 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.dto;
 
+import java.util.List;
 import java.util.Set;
 
 public class AccessDTO extends BaseDTO {
     // BlackWhiteList key
-    public static final String KEY_BLACK_WHITE_LIST = "blackwhitelist";
 
-    private String service;
     private Set<String> whitelist;
     private Set<String> blacklist;
+    private boolean enabled = true;
 
-    public String getService() {
-        return service;
+    public boolean isEnabled() {
+        return enabled;
     }
 
-    public void setService(String service) {
-        this.service = service;
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
     }
 
     public Set<String> getWhitelist() {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BalancingDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/BalancingDTO.java
similarity index 85%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BalancingDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/BalancingDTO.java
index d73d348..585d6f7 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/BalancingDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/BalancingDTO.java
@@ -15,22 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.dto;
 
 public class BalancingDTO extends BaseDTO{
 
-    private String service;
     private String methodName;
     private String strategy;
 
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
     public String getMethodName() {
         return methodName;
     }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/WeightDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/BaseDTO.java
similarity index 70%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/WeightDTO.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/BaseDTO.java
index b59fe2c..223b25f 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/WeightDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/BaseDTO.java
@@ -14,14 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.dubbo.admin.model.dto;
 
-package org.apache.dubbo.admin.dto;
-
-public class WeightDTO extends BaseDTO{
-
+/**
+ * BaseDTO
+ *
+ * For receive ID parameter with @RequestBody
+ */
+public abstract class BaseDTO {
+    private String application;
     private String service;
-    private int weight;
-    private String[] provider;
+
+    public String getApplication() {
+        return application;
+    }
+
+    public void setApplication(String application) {
+        this.application = application;
+    }
 
     public String getService() {
         return service;
@@ -30,20 +40,4 @@
     public void setService(String service) {
         this.service = service;
     }
-
-    public int getWeight() {
-        return weight;
-    }
-
-    public void setWeight(int weight) {
-        this.weight = weight;
-    }
-
-    public String[] getProvider() {
-        return provider;
-    }
-
-    public void setProvider(String[] provider) {
-        this.provider = provider;
-    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConfigService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConditionRouteDTO.java
similarity index 72%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConfigService.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConditionRouteDTO.java
index 0554459..08de709 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConfigService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ConditionRouteDTO.java
@@ -14,21 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service;
 
-import org.apache.dubbo.admin.registry.common.domain.Config;
+package org.apache.dubbo.admin.model.dto;
 
 import java.util.List;
-import java.util.Map;
 
-/**
- * TODO Comment of ConfigDAO
- *
- */
-public interface ConfigService {
+public class ConditionRouteDTO extends RouteDTO{
+    private List<String> conditions;
 
-    void update(List<Config> configs);
+    public List<String> getConditions() {
+        return conditions;
+    }
 
-    Map<String, String> findAllConfigsMap();
-
+    public void setConditions(List<String> conditions) {
+        this.conditions = conditions;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/Config.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/Config.java
new file mode 100644
index 0000000..45f6e96
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/Config.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.admin.model.dto;
+
+import java.util.List;
+import java.util.Map;
+
+public class Config {
+    private String side;
+    private List<String> addresses;
+    private List<String> providerAddresses;
+    private Map<String, Object> parameters;
+    private List<String> applications;
+    private List<String> services;
+
+    public String getSide() {
+        return side;
+    }
+
+    public void setSide(String side) {
+        this.side = side;
+    }
+
+    public List<String> getAddresses() {
+        return addresses;
+    }
+
+    public void setAddresses(List<String> addresses) {
+        this.addresses = addresses;
+    }
+
+    public List<String> getProviderAddresses() {
+        return providerAddresses;
+    }
+
+    public void setProviderAddresses(List<String> providerAddresses) {
+        this.providerAddresses = providerAddresses;
+    }
+
+    public Map<String, Object> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map<String, Object> parameters) {
+        this.parameters = parameters;
+    }
+
+    public List<String> getApplications() {
+        return applications;
+    }
+
+    public void setApplications(List<String> applications) {
+        this.applications = applications;
+    }
+
+    public List<String> getServices() {
+        return services;
+    }
+
+    public void setServices(List<String> services) {
+        this.services = services;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Feature.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/DynamicConfigDTO.java
similarity index 60%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Feature.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/DynamicConfigDTO.java
index c9d1eb9..9b62e8e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Feature.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/DynamicConfigDTO.java
@@ -14,49 +14,40 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.registry.common.domain;
 
-/**
- * System features
- */
-public class Feature extends Entity {
+package org.apache.dubbo.admin.model.dto;
 
-    private static final long serialVersionUID = 3246619851259746169L;
+import org.apache.dubbo.admin.model.store.OverrideConfig;
 
-    private String name;
+import java.util.List;
 
+public class DynamicConfigDTO extends BaseDTO {
+
+    private String configVersion;
     private boolean enabled;
+    private List<OverrideConfig> configs;
 
-    private String username;
-
-    public Feature() {
+    public List<OverrideConfig> getConfigs() {
+        return configs;
     }
 
-    public Feature(Long id) {
-        super(id);
+    public void setConfigs(List<OverrideConfig> configs) {
+        this.configs = configs;
     }
 
-    public String getName() {
-        return name;
+    public String getConfigVersion() {
+        return configVersion;
     }
 
-    public void setName(String name) {
-        this.name = name;
+    public void setConfigVersion(String configVersion) {
+        this.configVersion = configVersion;
     }
 
-    public boolean getEnabled() {
+    public boolean isEnabled() {
         return enabled;
     }
 
     public void setEnabled(boolean enabled) {
         this.enabled = enabled;
     }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java
similarity index 65%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java
index a6e65d2..0503660 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/RouteDTO.java
@@ -15,42 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.dto;
 
-public class RouteDTO extends BaseDTO{
-    private String app;
-    private String service;
-    private boolean dynamic;
+public abstract class RouteDTO extends BaseDTO{
     private int priority;
     private boolean enabled;
     private boolean force;
     private boolean runtime;
-    private String[] conditions;
-
-
-    public String getApp() {
-        return app;
-    }
-
-    public void setApp(String app) {
-        this.app = app;
-    }
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public boolean isDynamic() {
-        return dynamic;
-    }
-
-    public void setDynamic(boolean dynamic) {
-        this.dynamic = dynamic;
-    }
 
     public int getPriority() {
         return priority;
@@ -83,12 +54,4 @@
     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/dto/ServiceDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
similarity index 97%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/ServiceDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
index 42e2e8c..6e3fa50 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/ServiceDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.dto;
 
 import org.apache.commons.lang3.StringUtils;
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/ServiceDetailDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
similarity index 74%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/ServiceDetailDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
index 757b1c5..2a738f5 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/ServiceDetailDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDetailDTO.java
@@ -15,10 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.dto;
 
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
+import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
 
 import java.util.List;
 
@@ -27,6 +28,9 @@
     List<Provider> providers;
     List<Consumer> consumers;
 
+    FullServiceDefinition metadata;
+
+
     public List<Provider> getProviders() {
         return providers;
     }
@@ -42,4 +46,12 @@
     public void setConsumers(List<Consumer> consumers) {
         this.consumers = consumers;
     }
+
+    public FullServiceDefinition getMetadata() {
+        return metadata;
+    }
+
+    public void setMetadata(FullServiceDefinition metadata) {
+        this.metadata = metadata;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConfigService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/TagRouteDTO.java
similarity index 73%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConfigService.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/TagRouteDTO.java
index 0554459..5595572 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConfigService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/TagRouteDTO.java
@@ -14,21 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service;
 
-import org.apache.dubbo.admin.registry.common.domain.Config;
+package org.apache.dubbo.admin.model.dto;
+
+import org.apache.dubbo.admin.model.domain.Tag;
 
 import java.util.List;
-import java.util.Map;
 
-/**
- * TODO Comment of ConfigDAO
- *
- */
-public interface ConfigService {
+public class TagRouteDTO extends RouteDTO{
+    private List<Tag> tags;
 
-    void update(List<Config> configs);
+    public List<Tag> getTags() {
+        return tags;
+    }
 
-    Map<String, String> findAllConfigsMap();
-
+    public void setTags(List<Tag> tags) {
+        this.tags = tags;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/WeightDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/WeightDTO.java
similarity index 72%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/WeightDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/WeightDTO.java
index b59fe2c..62c73b0 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/WeightDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/WeightDTO.java
@@ -15,21 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.dto;
+
+import java.util.List;
 
 public class WeightDTO extends BaseDTO{
 
-    private String service;
     private int weight;
-    private String[] provider;
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
+    private List<String> addresses;
 
     public int getWeight() {
         return weight;
@@ -39,11 +32,11 @@
         this.weight = weight;
     }
 
-    public String[] getProvider() {
-        return provider;
+    public List<String> getAddresses() {
+        return addresses;
     }
 
-    public void setProvider(String[] provider) {
-        this.provider = provider;
+    public void setAddresses(List<String> addresses) {
+        this.addresses = addresses;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/BlackWhiteList.java
similarity index 68%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/BlackWhiteList.java
index a6e65d2..3072289 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/BlackWhiteList.java
@@ -15,50 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.store;
 
-public class RouteDTO extends BaseDTO{
-    private String app;
-    private String service;
-    private boolean dynamic;
-    private int priority;
+import java.util.List;
+
+public class BlackWhiteList {
     private boolean enabled;
     private boolean force;
     private boolean runtime;
-    private String[] conditions;
-
-
-    public String getApp() {
-        return app;
-    }
-
-    public void setApp(String app) {
-        this.app = app;
-    }
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public boolean isDynamic() {
-        return dynamic;
-    }
-
-    public void setDynamic(boolean dynamic) {
-        this.dynamic = dynamic;
-    }
-
-    public int getPriority() {
-        return priority;
-    }
-
-    public void setPriority(int priority) {
-        this.priority = priority;
-    }
+    private int priority;
+    private List<String> conditions;
 
     public boolean isEnabled() {
         return enabled;
@@ -84,11 +50,19 @@
         this.runtime = runtime;
     }
 
-    public String[] getConditions() {
+    public int getPriority() {
+        return priority;
+    }
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public List<String> getConditions() {
         return conditions;
     }
 
-    public void setConditions(String[] conditions) {
+    public void setConditions(List<String> conditions) {
         this.conditions = conditions;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/OverrideConfig.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/OverrideConfig.java
new file mode 100644
index 0000000..0a9878e
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/OverrideConfig.java
@@ -0,0 +1,97 @@
+/*
+ * 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.store;
+
+import java.util.List;
+import java.util.Map;
+
+public class OverrideConfig {
+
+    private String side;
+    private List<String> addresses;
+    private List<String> providerAddresses;
+    private Map<String, Object> parameters;
+    private List<String> applications;
+    private List<String> services;
+    private String type;
+    private boolean enabled;
+
+    public String getSide() {
+        return side;
+    }
+
+    public void setSide(String side) {
+        this.side = side;
+    }
+
+    public List<String> getAddresses() {
+        return addresses;
+    }
+
+    public void setAddresses(List<String> addresses) {
+        this.addresses = addresses;
+    }
+
+    public List<String> getProviderAddresses() {
+        return providerAddresses;
+    }
+
+    public void setProviderAddresses(List<String> providerAddresses) {
+        this.providerAddresses = providerAddresses;
+    }
+
+    public Map<String, Object> getParameters() {
+        return parameters;
+    }
+
+    public void setParameters(Map<String, Object> parameters) {
+        this.parameters = parameters;
+    }
+
+    public List<String> getApplications() {
+        return applications;
+    }
+
+    public void setApplications(List<String> applications) {
+        this.applications = applications;
+    }
+
+    public List<String> getServices() {
+        return services;
+    }
+
+    public void setServices(List<String> services) {
+        this.services = services;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/OverrideDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/OverrideDTO.java
new file mode 100644
index 0000000..c99854a
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/OverrideDTO.java
@@ -0,0 +1,68 @@
+/*
+ * 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.store;
+
+import java.util.List;
+
+public class OverrideDTO {
+    private String key;
+    private String scope;
+    private String configVersion;
+    private boolean enabled;
+    private List<OverrideConfig> configs;
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public String getScope() {
+        return scope;
+    }
+
+    public void setScope(String scope) {
+        this.scope = scope;
+    }
+
+    public String getConfigVersion() {
+        return configVersion;
+    }
+
+    public void setConfigVersion(String configVersion) {
+        this.configVersion = configVersion;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    public List<OverrideConfig> getConfigs() {
+        return configs;
+    }
+
+    public void setConfigs(List<OverrideConfig> configs) {
+        this.configs = configs;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java
similarity index 68%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java
index a6e65d2..46b012f 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java
@@ -15,41 +15,36 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.store;
 
-public class RouteDTO extends BaseDTO{
-    private String app;
-    private String service;
-    private boolean dynamic;
+import java.util.List;
+
+public class RoutingRule {
+
+    private String key;
+    private String scope;
     private int priority;
     private boolean enabled;
     private boolean force;
     private boolean runtime;
-    private String[] conditions;
+    private List<String> conditions;
+    private BlackWhiteList blackWhiteList;
 
 
-    public String getApp() {
-        return app;
+    public String getKey() {
+        return key;
     }
 
-    public void setApp(String app) {
-        this.app = app;
+    public void setKey(String key) {
+        this.key = key;
     }
 
-    public String getService() {
-        return service;
+    public String getScope() {
+        return scope;
     }
 
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public boolean isDynamic() {
-        return dynamic;
-    }
-
-    public void setDynamic(boolean dynamic) {
-        this.dynamic = dynamic;
+    public void setScope(String scope) {
+        this.scope = scope;
     }
 
     public int getPriority() {
@@ -84,11 +79,19 @@
         this.runtime = runtime;
     }
 
-    public String[] getConditions() {
+    public List<String> getConditions() {
         return conditions;
     }
 
-    public void setConditions(String[] conditions) {
+    public void setConditions(List<String> conditions) {
         this.conditions = conditions;
     }
+
+    public BlackWhiteList getBlackWhiteList() {
+        return blackWhiteList;
+    }
+
+    public void setBlackWhiteList(BlackWhiteList blackWhiteList) {
+        this.blackWhiteList = blackWhiteList;
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/TagRoute.java
similarity index 66%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
copy to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/TagRoute.java
index a6e65d2..968a518 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/dto/RouteDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/TagRoute.java
@@ -15,42 +15,19 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.dto;
+package org.apache.dubbo.admin.model.store;
 
-public class RouteDTO extends BaseDTO{
-    private String app;
-    private String service;
-    private boolean dynamic;
+import org.apache.dubbo.admin.model.domain.Tag;
+
+import java.util.List;
+
+public class TagRoute {
     private int priority;
     private boolean enabled;
     private boolean force;
     private boolean runtime;
-    private String[] conditions;
-
-
-    public String getApp() {
-        return app;
-    }
-
-    public void setApp(String app) {
-        this.app = app;
-    }
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public boolean isDynamic() {
-        return dynamic;
-    }
-
-    public void setDynamic(boolean dynamic) {
-        this.dynamic = dynamic;
-    }
+    private String key;
+    private List<Tag> tags;
 
     public int getPriority() {
         return priority;
@@ -84,11 +61,19 @@
         this.runtime = runtime;
     }
 
-    public String[] getConditions() {
-        return conditions;
+    public String getKey() {
+        return key;
     }
 
-    public void setConditions(String[] conditions) {
-        this.conditions = conditions;
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public List<Tag> getTags() {
+        return tags;
+    }
+
+    public void setTags(List<Tag> tags) {
+        this.tags = tags;
     }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/StatusManager.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/StatusManager.java
deleted file mode 100644
index 7f0d1ab..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/StatusManager.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.registry.common;
-
-import com.alibaba.dubbo.common.status.Status;
-import com.alibaba.dubbo.common.status.Status.Level;
-import com.alibaba.dubbo.common.status.StatusChecker;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * StatusManager
- *
- */
-public class StatusManager {
-
-    private static final StatusManager INSTANCE = new StatusManager();
-    private final Map<String, StatusChecker> statusHandlers = new ConcurrentHashMap<String, StatusChecker>();
-
-    private StatusManager() {
-    }
-
-    public static StatusManager getInstance() {
-        return INSTANCE;
-    }
-
-    public static Status getStatusSummary(Map<String, Status> statusList) {
-        return getSummaryStatus(statusList);
-    }
-
-    public static Status getSummaryStatus(Map<String, Status> statuses) {
-        Level level = Level.OK;
-        StringBuilder msg = new StringBuilder();
-        for (Map.Entry<String, Status> entry : statuses.entrySet()) {
-            String key = entry.getKey();
-            Status status = entry.getValue();
-            Level l = status.getLevel();
-            if (Level.ERROR.equals(l)) {
-                level = Level.ERROR;
-                if (msg.length() > 0) {
-                    msg.append(",");
-                }
-                msg.append(key);
-            } else if (Level.WARN.equals(l)) {
-                if (!Level.ERROR.equals(level)) {
-                    level = Level.WARN;
-                }
-                if (msg.length() > 0) {
-                    msg.append(",");
-                }
-                msg.append(key);
-            }
-        }
-        return new Status(level, msg.toString());
-    }
-
-    public void addStatusHandler(String name, StatusChecker statusHandler) {
-        this.statusHandlers.put(name, statusHandler);
-    }
-
-    public void addStatusHandlers(Map<String, StatusChecker> statusHandlers) {
-        this.statusHandlers.putAll(statusHandlers);
-    }
-
-    public void addStatusHandlers(Collection<StatusChecker> statusHandlers) {
-        for (StatusChecker statusChecker : statusHandlers) {
-            String name = statusChecker.getClass().getSimpleName();
-            if (name.endsWith(StatusChecker.class.getSimpleName())) {
-                name = name.substring(0, name.length() - StatusChecker.class.getSimpleName().length());
-            }
-            this.statusHandlers.put(name, statusChecker);
-        }
-    }
-
-    public void removeStatusHandler(String name) {
-        this.statusHandlers.remove(name);
-    }
-
-    public void clearStatusHandlers() {
-        this.statusHandlers.clear();
-    }
-
-    public Map<String, Status> getStatusList() {
-        return getStatusList(null);
-    }
-
-    /**
-     * Exclude items do not need to show in Summary Page
-     */
-    public Map<String, Status> getStatusList(String[] excludes) {
-        Map<String, Status> statuses = new HashMap<String, Status>();
-        Map<String, StatusChecker> temp = new HashMap<String, StatusChecker>();
-        temp.putAll(statusHandlers);
-        if (excludes != null && excludes.length > 0) {
-            for (String exclude : excludes) {
-                temp.remove(exclude);
-            }
-        }
-        for (Map.Entry<String, StatusChecker> entry : temp.entrySet()) {
-            statuses.put(entry.getKey(), entry.getValue().check());
-        }
-        return statuses;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/DependItem.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/DependItem.java
deleted file mode 100644
index 805cbef..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/DependItem.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.registry.common.domain;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * DependItem
- *
- */
-public class DependItem {
-
-    private final List<Integer> recursives = new ArrayList<Integer>();
-    private String application;
-    private int index;
-    private int level;
-    private DependItem parent;
-
-    public DependItem() {
-    }
-
-    public DependItem(String application, int level) {
-        this.application = application;
-        this.level = level;
-    }
-
-    public DependItem(DependItem parent, String application, int level, int index) {
-        this.parent = parent;
-        this.application = application;
-        this.level = level;
-        this.index = index;
-    }
-
-    public int getLevel() {
-        return level;
-    }
-
-    public void setLevel(int level) {
-        this.level = level;
-    }
-
-    public String getApplication() {
-        return application;
-    }
-
-    public void setApplication(String application) {
-        this.application = application;
-    }
-
-    public int getIndex() {
-        return index;
-    }
-
-    public void setIndex(int index) {
-        this.index = index;
-    }
-
-    public DependItem getParent() {
-        return parent;
-    }
-
-    public void setParent(DependItem parent) {
-        this.parent = parent;
-    }
-
-    public List<Integer> getRecursives() {
-        return recursives;
-    }
-
-    public void addRecursive(int padding, int value) {
-        while (recursives.size() < padding) {
-            recursives.add(0);
-        }
-        recursives.add(value);
-    }
-
-    public String toString() {
-        return "DependItem [application=" + application + ", index=" + index + ", level=" + level
-                + "]";
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Dependency.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Dependency.java
deleted file mode 100644
index b981d16..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Dependency.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.registry.common.domain;
-
-import java.io.Serializable;
-
-public class Dependency implements Serializable {
-
-    private static final long serialVersionUID = 8526869025719540547L;
-
-    private String providerApplication;
-
-    private String consumerApplication;
-
-    public String getProviderApplication() {
-        return providerApplication;
-    }
-
-    public void setProviderApplication(String providerApplication) {
-        this.providerApplication = providerApplication;
-    }
-
-    public String getConsumerApplication() {
-        return consumerApplication;
-    }
-
-    public void setConsumerApplication(String consumerApplication) {
-        this.consumerApplication = consumerApplication;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/PageList.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/PageList.java
deleted file mode 100644
index 83674ff..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/PageList.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.registry.common.domain;
-
-import java.io.Serializable;
-import java.util.List;
-
-/**
- * PageList
- *
- */
-public class PageList<T> implements Serializable {
-
-    private static final long serialVersionUID = 43869560130672722L;
-
-    private int start;
-
-    private int limit;
-
-    private int total;
-
-    private List<T> list;
-
-    public PageList() {
-    }
-
-    public PageList(int start, int limit, int total, List<T> list) {
-        this.start = start;
-        this.limit = limit;
-        this.total = total;
-        this.list = list;
-    }
-
-    public int getStart() {
-        return start;
-    }
-
-    public void setStart(int start) {
-        this.start = start;
-    }
-
-    public int getLimit() {
-        return limit;
-    }
-
-    public void setLimit(int limit) {
-        this.limit = limit;
-    }
-
-    public int getTotal() {
-        return total;
-    }
-
-    public void setTotal(int total) {
-        this.total = total;
-    }
-
-    public List<T> getList() {
-        return list;
-    }
-
-    public void setList(List<T> list) {
-        this.list = list;
-    }
-
-    public int getPageCount() {
-
-        int lim = limit;
-        if (limit < 1) {
-            lim = 1;
-        }
-
-        int page = total / lim;
-        if (page < 1) {
-            return 1;
-        }
-
-        int remain = total % lim;
-
-        if (remain > 0) {
-            page += 1;
-        }
-
-        return page;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/SearchHistory.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/SearchHistory.java
deleted file mode 100644
index 1812fdc..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/SearchHistory.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.registry.common.domain;
-
-public class SearchHistory extends Entity {
-
-    private static final long serialVersionUID = -1281982267153430266L;
-
-    private String name;
-
-    private String type;
-
-    private String url;
-
-    public SearchHistory() {
-    }
-
-    public SearchHistory(Long id) {
-        super(id);
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getType() {
-        return type;
-    }
-
-    public void setType(String type) {
-        this.type = type;
-    }
-
-    public String getUrl() {
-        return url;
-    }
-
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Test.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Test.java
deleted file mode 100644
index 75548e1..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/domain/Test.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.registry.common.domain;
-
-/**
- * Test
- *
- */
-public class Test extends Entity {
-
-    private static final long serialVersionUID = 872527738197173003L;
-
-    private String name;
-
-    private String service;
-
-    private String method;
-
-    private String parameters;
-
-    private boolean exception;
-
-    private String result;
-
-    private String username;
-
-    private boolean autoRun;
-
-    public Test() {
-    }
-
-    public Test(Long id) {
-        super(id);
-    }
-
-    public String getService() {
-        return service;
-    }
-
-    public void setService(String service) {
-        this.service = service;
-    }
-
-    public String getMethod() {
-        return method;
-    }
-
-    public void setMethod(String method) {
-        this.method = method;
-    }
-
-    public String getParameters() {
-        return parameters;
-    }
-
-    public void setParameters(String parameters) {
-        this.parameters = parameters;
-    }
-
-    public String getResult() {
-        return result;
-    }
-
-    public void setResult(String result) {
-        this.result = result;
-    }
-
-    public String getUsername() {
-        return username;
-    }
-
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    public boolean isException() {
-        return exception;
-    }
-
-    public void setException(boolean exception) {
-        this.exception = exception;
-    }
-
-    public boolean isAutoRun() {
-        return autoRun;
-    }
-
-    public void setAutoRun(boolean autoRun) {
-        this.autoRun = autoRun;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/registry/ConvertUtil.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/registry/ConvertUtil.java
deleted file mode 100644
index 098bab4..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/registry/ConvertUtil.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.registry.common.registry;
-
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.utils.StringUtils;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class ConvertUtil {
-    private ConvertUtil() {
-    }
-
-    public static Map<String, Map<String, String>> convertRegister(Map<String, Map<String, String>> register) {
-        Map<String, Map<String, String>> newRegister = new HashMap<String, Map<String, String>>();
-        for (Map.Entry<String, Map<String, String>> entry : register.entrySet()) {
-            String serviceName = entry.getKey();
-            Map<String, String> serviceUrls = entry.getValue();
-            if (!serviceName.contains(":") && !serviceName.contains("/")) {
-                for (Map.Entry<String, String> entry2 : serviceUrls.entrySet()) {
-                    String serviceUrl = entry2.getKey();
-                    String serviceQuery = entry2.getValue();
-                    Map<String, String> params = StringUtils.parseQueryString(serviceQuery);
-                    String group = params.get("group");
-                    String version = params.get("version");
-                    params.remove("group");
-                    params.remove("version");
-                    String name = serviceName;
-                    if (group != null && group.length() > 0) {
-                        name = group + "/" + name;
-                    }
-                    if (version != null && version.length() > 0 && !"0.0.0".equals(version)) {
-                        name = name + ":" + version;
-                    }
-                    Map<String, String> newUrls = newRegister.get(name);
-                    if (newUrls == null) {
-                        newUrls = new HashMap<String, String>();
-                        newRegister.put(name, newUrls);
-                    }
-                    newUrls.put(serviceUrl, StringUtils.toQueryString(params));
-                }
-            } else {
-                newRegister.put(serviceName, serviceUrls);
-            }
-        }
-        return newRegister;
-    }
-
-    public static Map<String, String> convertSubscribe(Map<String, String> subscribe) {
-        Map<String, String> newSubscribe = new HashMap<String, String>();
-        for (Map.Entry<String, String> entry : subscribe.entrySet()) {
-            String serviceName = entry.getKey();
-            String serviceQuery = entry.getValue();
-            if (!serviceName.contains(":") && !serviceName.contains("/")) {
-                Map<String, String> params = StringUtils.parseQueryString(serviceQuery);
-                String group = params.get("group");
-                String version = params.get("version");
-                params.remove("group");
-                params.remove("version");
-                String name = serviceName;
-                if (group != null && group.length() > 0) {
-                    name = group + "/" + name;
-                }
-                if (version != null && version.length() > 0 && !"0.0.0".equals(version)) {
-                    name = name + ":" + version;
-                }
-                newSubscribe.put(name, StringUtils.toQueryString(params));
-            } else {
-                newSubscribe.put(serviceName, serviceQuery);
-            }
-        }
-        return newSubscribe;
-    }
-
-    public static Map<String, String> serviceName2Map(String serviceName) {
-        String group = null;
-        String version = null;
-        int i = serviceName.indexOf("/");
-        if (i > 0) {
-            group = serviceName.substring(0, i);
-            serviceName = serviceName.substring(i + 1);
-        }
-        i = serviceName.lastIndexOf(":");
-        if (i > 0) {
-            version = serviceName.substring(i + 1);
-            serviceName = serviceName.substring(0, i);
-        }
-
-        Map<String, String> ret = new HashMap<String, String>();
-        if (!StringUtils.isEmpty(serviceName)) {
-            ret.put(Constants.INTERFACE_KEY, serviceName);
-        }
-        if (!StringUtils.isEmpty(version)) {
-            ret.put(Constants.VERSION_KEY, version);
-        }
-        if (!StringUtils.isEmpty(group)) {
-            ret.put(Constants.GROUP_KEY, group);
-        }
-
-        return ret;
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/OverrideUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/OverrideUtils.java
deleted file mode 100644
index d229ed5..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/OverrideUtils.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.registry.common.route;
-
-import com.alibaba.dubbo.common.Constants;
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-public class OverrideUtils {
-
-    public static final Comparator<Override> OVERRIDE_COMPARATOR = new Comparator<Override>() {
-        public int compare(Override o1, Override o2) {
-            if (o1 == null && o2 == null) {
-                return 0;
-            }
-            if (o1 == null) {
-                return -1;
-            }
-            if (o2 == null) {
-                return 1;
-            }
-            int cmp = cmp(o1.getAddress(), o2.getAddress());
-            if (cmp != 0) {
-                return cmp;
-            }
-            cmp = cmp(o1.getApplication(), o2.getApplication());
-            if (cmp != 0) {
-                return cmp;
-            }
-            return cmp(o1.getService(), o2.getService());
-        }
-
-        private int cmp(String s1, String s2) {
-            if (s1 == null && s2 == null) {
-                return 0;
-            }
-            if (s1 == null) {
-                return -1;
-            }
-            if (s2 == null) {
-                return 1;
-            }
-            if (s1.equals(s2)) {
-                return 0;
-            }
-            if (isAny(s1)) {
-                return 1;
-            }
-            if (isAny(s2)) {
-                return -1;
-            }
-            return s1.compareTo(s2);
-        }
-
-        private boolean isAny(String s) {
-            return s == null || s.length() == 0 || Constants.ANY_VALUE.equals(s) || Constants.ANYHOST_VALUE.equals(s);
-        }
-    };
-
-    public static void setConsumerOverrides(Consumer consumer, List<Override> overrides) {
-        if (consumer == null || overrides == null) {
-            return;
-        }
-        List<Override> result = new ArrayList<Override>(overrides.size());
-        for (Override override : overrides) {
-            if (!override.isEnabled()) {
-                continue;
-            }
-            if (override.isMatch(consumer)) {
-                result.add(override);
-            }
-            if (override.isUniqueMatch(consumer)) {
-                consumer.setOverride(override);
-            }
-        }
-        Collections.sort(result, OverrideUtils.OVERRIDE_COMPARATOR);
-        consumer.setOverrides(result);
-    }
-
-    public static void setProviderOverrides(Provider provider, List<Override> overrides) {
-        if (provider == null || overrides == null) {
-            return;
-        }
-        List<Override> result = new ArrayList<Override>(overrides.size());
-        for (Override override : overrides) {
-            if (!override.isEnabled()) {
-                continue;
-            }
-            if (override.isMatch(provider)) {
-                result.add(override);
-            }
-            if (override.isUniqueMatch(provider)) {
-                provider.setOverride(override);
-            }
-        }
-        provider.setOverrides(overrides);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteRuleUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteRuleUtils.java
deleted file mode 100644
index 5f12722..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteRuleUtils.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.registry.common.route;
-
-import com.alibaba.dubbo.common.utils.StringUtils;
-
-import java.util.*;
-import java.util.Map.Entry;
-
-public class RouteRuleUtils {
-    private RouteRuleUtils() {
-    }
-
-    /**
-     * When one of the value that is bound to a specific key of a condition is expanded, it is merged into another value of a specified key.
-     * @param <T> generic type
-     * @param condition
-     * @param srcKeyName the key to expand
-     * @param destKeyName the key to merge into
-     * @param expandName2Set the mapping of values to values that are carried out
-     */
-    public static <T extends Collection<String>> Map<String, RouteRule.MatchPair> expandCondition(
-        Map<String, RouteRule.MatchPair> condition, String srcKeyName, String destKeyName,
-        Map<String, T> expandName2Set) {
-        if (null == condition || StringUtils.isEmpty(srcKeyName) || StringUtils.isEmpty(destKeyName)) {
-            return condition;
-        }
-
-        RouteRule.MatchPair matchPair = condition.get(srcKeyName);
-        if (matchPair == null) {
-            return condition;
-        }
-
-        Map<String, RouteRule.MatchPair> ret = new HashMap<String, RouteRule.MatchPair>();
-
-        Iterator<Entry<String, RouteRule.MatchPair>> iterator = condition.entrySet().iterator();
-        for (; iterator.hasNext(); ) {
-            Entry<String, RouteRule.MatchPair> entry = iterator.next();
-            String condName = entry.getKey();
-
-            // Neither source nor destination
-            if (!condName.equals(srcKeyName) && !condName.equals(destKeyName)) {
-                RouteRule.MatchPair p = entry.getValue();
-                if (p != null) ret.put(condName, p);
-            }
-            // equals with source
-            else if (condName.equals(srcKeyName)) {
-                RouteRule.MatchPair from = condition.get(srcKeyName);
-                RouteRule.MatchPair to = condition.get(destKeyName);
-
-                // no items to Expand
-                if (from == null || from.getMatches().isEmpty() && from.getUnmatches().isEmpty()) {
-                    if (to != null) ret.put(destKeyName, to);
-                    continue;
-                }
-
-                Set<String> matches = new HashSet<String>();
-                Set<String> unmatches = new HashSet<String>();
-                // add items from source Expand key
-                for (String s : from.getMatches()) {
-                    if (expandName2Set == null || !expandName2Set.containsKey(s)) continue;
-
-                    matches.addAll(expandName2Set.get(s));
-                }
-                for (String s : from.getUnmatches()) {
-                    if (expandName2Set == null || !expandName2Set.containsKey(s)) continue;
-
-                    unmatches.addAll(expandName2Set.get(s));
-                }
-                // add the original items
-                if (to != null) {
-                    matches.addAll(to.getMatches());
-                    unmatches.addAll(to.getUnmatches());
-                }
-
-                ret.put(destKeyName, new RouteRule.MatchPair(matches, unmatches));
-            }
-            // else, it must be Key == destKeyName, do nothing
-        }
-
-        return ret;
-    }
-
-    /**
-     * Check whether the KV (key=value pair of Provider or Consumer) matches the conditions.
-     *
-     * @param condition can contains variable definition. For example, <code>{key1={matches={value1,value2,$var1},unmatches={Vx,Vy,$var2}}}</code>
-     * @param valueParams Set of values of interpolated variables in a condition
-     * @param kv key=value pair of Provider or Consumer
-     * @see RouteRule
-     */
-    public static boolean isMatchCondition(Map<String, RouteRule.MatchPair> condition,
-                                           Map<String, String> valueParams, Map<String, String> kv) {
-        if (condition != null && condition.size() > 0) {
-            for (Map.Entry<String, RouteRule.MatchPair> entry : condition.entrySet()) {
-                String condName = entry.getKey();
-                RouteRule.MatchPair p = entry.getValue();
-                String value = kv.get(condName);
-                Set<String> matches = p.getMatches();
-                if (matches != null && matches.size() > 0
-                        && !ParseUtils.isMatchGlobPatternsNeedInterpolate(matches, valueParams, value)) { // if V is null, return false
-                    // don't match matches
-                    return false;
-                }
-                Set<String> unmatches = p.getUnmatches();
-                if (unmatches != null && unmatches.size() > 0
-                        && ParseUtils.isMatchGlobPatternsNeedInterpolate(unmatches, valueParams, value)) {
-                    // match unmatches
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-
-    /**
-     * Return services that can match When Condition in Route Rule, use Glob Pattern.
-     */
-    public static Set<String> filterServiceByRule(List<String> services, RouteRule rule) {
-        if (null == services || services.isEmpty() || rule == null) {
-            return new HashSet<String>();
-        }
-
-        RouteRule.MatchPair p = rule.getWhenCondition().get("service");
-        if (p == null) {
-            return new HashSet<String>();
-        }
-
-        Set<String> filter = ParseUtils.filterByGlobPattern(p.getMatches(), services);
-        Set<String> set = ParseUtils.filterByGlobPattern(p.getUnmatches(), services);
-        filter.addAll(set);
-        return filter;
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteUtils.java
deleted file mode 100644
index 8bab986..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/route/RouteUtils.java
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * 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.registry.common.route;
-
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
-import org.apache.dubbo.admin.registry.common.domain.Route;
-import org.apache.dubbo.admin.web.pulltool.Tool;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.*;
-
-/**
- * RouteParser route rule parse tool。
- *
- */
-public class RouteUtils {
-
-    public static boolean matchRoute(String consumerAddress, String consumerQueryUrl, Route route, Map<String, List<String>> clusters) {
-        RouteRule rule = RouteRule.parseQuitely(route);
-        Map<String, RouteRule.MatchPair> when = RouteRuleUtils.expandCondition(
-                rule.getWhenCondition(), "consumer.cluster", "consumer.host", clusters);
-        Map<String, String> consumerSample = ParseUtils.parseQuery("consumer.", consumerQueryUrl);
-
-        final int index = consumerAddress.lastIndexOf(":");
-        String consumerHost = null;
-        if (index != -1) {
-            consumerHost = consumerAddress.substring(0, index);
-        } else {
-            consumerHost = consumerAddress;
-        }
-        consumerSample.put("consumer.host", consumerHost);
-
-        return RouteRuleUtils.isMatchCondition(when, consumerSample, consumerSample);
-    }
-
-    public static Map<String, String> previewRoute(String serviceName, String consumerAddress, String queryUrl, Map<String, String> serviceUrls,
-                                                   Route route, Map<String, List<String>> clusters, List<Route> routed) {
-        if (null == route) {
-            throw new IllegalArgumentException("Route is null.");
-        }
-        List<Route> routes = new ArrayList<Route>();
-        routes.add(route);
-        return route(serviceName, consumerAddress, queryUrl, serviceUrls, routes, clusters, routed);
-    }
-
-    /**
-     * @return Map<methodName, Route>
-     */
-    public static List<Route> findUsedRoute(String serviceName, String consumerAddress, String consumerQueryUrl,
-                                            List<Route> routes, Map<String, List<String>> clusters) {
-        List<Route> routed = new ArrayList<Route>();
-        Map<String, String> urls = new HashMap<String, String>();
-        urls.put("dubbo://" + consumerAddress + "/" + serviceName, consumerQueryUrl);
-        RouteUtils.route(serviceName, consumerAddress, consumerQueryUrl, urls, routes, clusters, routed);
-        return routed;
-    }
-
-    public static List<Provider> route(String serviceName, String consumerAddress, String consumerQueryUrl, List<Provider> providers,
-                                       List<Override> overrides, List<Route> routes, Map<String, List<String>> clusters, List<Route> routed) {
-        if (providers == null) {
-            return null;
-        }
-        Map<String, String> urls = new HashMap<String, String>();
-        urls.put("consumer://" + consumerAddress + "/" + serviceName, consumerQueryUrl); // not empty dummy data
-        for (Provider provider : providers) {
-            if (Tool.isProviderEnabled(provider, overrides)) {
-                urls.put(provider.getUrl(), provider.getParameters());
-            }
-        }
-        urls = RouteUtils.route(serviceName, consumerAddress, consumerQueryUrl, urls, routes, clusters, routed);
-        List<Provider> result = new ArrayList<Provider>();
-        for (Provider provider : providers) {
-            if (urls.containsKey(provider.getUrl())) {
-                result.add(provider);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * @param serviceName e.g. {@code com.alibaba.morgan.MemberService}
-     * @param consumerAddress e.g. {@code 192.168.1.3:54333}
-     * @param consumerQueryUrl metadata of subscribe url, e.g. <code>aplication=nasdaq&dubbo=2.0.3&methods=updateItems,validateNew&revision=1.7.0</code>
-     * @param serviceUrls providers
-     * @param routes all route rules
-     * @param clusters all clusters
-     * @return route result, Map<url-body, url-params>
-     */
-    // FIXME The combination of clusters and routes can be done in advance when clusters or routes changes
-    // FIXME Separating the operation of Cache from the Util method
-    public static Map<String, String> route(String serviceName, String consumerAddress, String consumerQueryUrl, Map<String, String> serviceUrls,
-                                            List<Route> routes, Map<String, List<String>> clusters, List<Route> routed) {
-        if (serviceUrls == null || serviceUrls.size() == 0) {
-            return serviceUrls;
-        }
-        if (routes == null || routes.isEmpty()) {
-            return serviceUrls;
-        }
-
-        Map<Long, RouteRule> rules = route2RouteRule(routes, clusters);
-
-        final Map<String, String> consumerSample = ParseUtils.parseQuery("consumer.", consumerQueryUrl);
-        final int index = consumerAddress.lastIndexOf(":");
-        final String consumerHost;
-        if (consumerAddress != null && index != -1) {
-            consumerHost = consumerAddress.substring(0, index);
-        } else {
-            consumerHost = consumerAddress;
-        }
-        consumerSample.put("consumer.host", consumerHost);
-
-        Map<String, Map<String, String>> url2ProviderSample = new HashMap<String, Map<String, String>>();
-        for (Map.Entry<String, String> entry : serviceUrls.entrySet()) {
-            URI uri;
-            try {
-                uri = new URI(entry.getKey());
-            } catch (URISyntaxException e) {
-                throw new IllegalStateException("fail to parse url(" + entry.getKey() + "):" + e.getMessage(), e);
-            }
-            Map<String, String> sample = new HashMap<String, String>();
-            sample.putAll(ParseUtils.parseQuery("provider.", entry.getValue()));
-            sample.put("provider.protocol", uri.getScheme());
-            sample.put("provider.host", uri.getHost());
-            sample.put("provider.port", String.valueOf(uri.getPort()));
-
-            url2ProviderSample.put(entry.getKey(), sample);
-        }
-
-
-        Map<String, Set<String>> url2Methods = new HashMap<String, Set<String>>();
-
-        // Consumer can specify the required methods through the consumer.methods Key
-        String methodsString = consumerSample.get("consumer.methods");
-        String[] methods = methodsString == null || methodsString.length() == 0 ? new String[]{Route.ALL_METHOD} : methodsString.split(ParseUtils.METHOD_SPLIT);
-        for (String method : methods) {
-            consumerSample.put("method", method);
-            // NOTE: 
-            // <*method>only configure <no method key>
-            // if method1 matches <no method key> and <method = method1>, we should reduce the priority of <no method key>.
-            if (routes != null && routes.size() > 0) {
-                for (Route route : routes) {
-                    if (isSerivceNameMatched(route.getService(), serviceName)) {
-                        RouteRule rule = rules.get(route.getId());
-                        // matches When Condition
-                        if (rule != null && RouteRuleUtils.isMatchCondition(
-                                rule.getWhenCondition(), consumerSample, consumerSample)) {
-                            if (routed != null && !routed.contains(route)) {
-                                routed.add(route);
-                            }
-                            Map<String, RouteRule.MatchPair> then = rule.getThenCondition();
-                            if (then != null) {
-                                Map<String, Map<String, String>> tmp = getUrlsMatchedCondition(then, consumerSample, url2ProviderSample);
-                                // If the result of the rule is empty, the rule is invalid and all Provider is used.
-                                if (route.isForce() || !tmp.isEmpty()) {
-                                    url2ProviderSample = tmp;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            for (String url : url2ProviderSample.keySet()) {
-                Set<String> mts = url2Methods.get(url);
-                if (mts == null) {
-                    mts = new HashSet<String>();
-                    url2Methods.put(url, mts);
-                }
-                mts.add(method);
-            }
-        } // end of for methods
-
-        return appendMethodsToUrls(serviceUrls, url2Methods);
-    }
-
-    static Map<Long, RouteRule> route2RouteRule(List<Route> routes,
-                                                Map<String, List<String>> clusters) {
-        Map<Long, RouteRule> rules = new HashMap<Long, RouteRule>();
-        // route -> RouteRule
-        if (routes != null && routes.size() > 0) {
-            for (Route route : routes) {
-                rules.put(route.getId(), RouteRule.parseQuitely(route));
-            }
-        }
-        // expand the cluster parameters into conditions of routerule
-        if (clusters != null && clusters.size() > 0) {
-            Map<Long, RouteRule> rrs = new HashMap<Long, RouteRule>();
-            for (Map.Entry<Long, RouteRule> entry : rules.entrySet()) {
-                RouteRule rr = entry.getValue();
-
-                Map<String, RouteRule.MatchPair> when = RouteRuleUtils.expandCondition(
-                        rr.getWhenCondition(), "consumer.cluster", "consumer.host", clusters);
-                Map<String, RouteRule.MatchPair> then = RouteRuleUtils.expandCondition(
-                        rr.getThenCondition(), "provider.cluster", "provider.host", clusters);
-
-                rrs.put(entry.getKey(), RouteRule.createFromCondition(when, then));
-            }
-            rules = rrs;
-        }
-        return rules;
-    }
-
-    static Map<String, String> appendMethodsToUrls(Map<String, String> serviceUrls,
-                                                   Map<String, Set<String>> url2Methods) {
-        // Add method parameters to URL
-        Map<String, String> results = new HashMap<String, String>();
-        for (Map.Entry<String, Set<String>> entry : url2Methods.entrySet()) {
-            String url = entry.getKey();
-            String query = serviceUrls.get(url);
-
-            Set<String> methodNames = entry.getValue();
-            if (methodNames != null && methodNames.size() > 0) {
-                String ms = StringUtils.join(methodNames.toArray(new String[0]), ParseUtils.METHOD_SPLIT);
-                query = ParseUtils.replaceParameter(query, "methods", ms);
-            }
-            results.put(url, query);
-        }
-        return results;
-    }
-
-    static Route getFirstRouteMatchedWhenConditionOfRule(String serviceName, Map<String, String> consumerSample, List<Route> routes, Map<Long, RouteRule> routeRuleMap) {
-        if (serviceName == null || serviceName.length() == 0) {
-            return null;
-        }
-        if (routes != null && routes.size() > 0) {
-            for (Route route : routes) {
-                if (isSerivceNameMatched(route.getService(), serviceName)) {
-                    RouteRule rule = routeRuleMap.get(route.getId());
-                    // if matches When Condition
-                    if (rule != null && RouteRuleUtils.isMatchCondition(
-                            rule.getWhenCondition(), consumerSample, consumerSample)) {
-                        return route; // will return if the first condition matches
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Check if a service name matches pattern
-     *
-     * @param servicePattern
-     * @param serviceName
-     */
-    static boolean isSerivceNameMatched(String servicePattern, String serviceName) {
-        final int pip = servicePattern.indexOf('/');
-        final int pi = serviceName.indexOf('/');
-        if (pip != -1) { // pattern has group
-            if (pi == -1) return false; // servicename doesn't have group
-
-            String gp = servicePattern.substring(0, pip);
-            servicePattern = servicePattern.substring(pip + 1);
-
-            String g = serviceName.substring(0, pi);
-            if (!gp.equals(g)) return false;
-        }
-        if (pi != -1)
-            serviceName = serviceName.substring(pi + 1);
-
-        final int vip = servicePattern.lastIndexOf(':');
-        final int vi = serviceName.lastIndexOf(':');
-        if (vip != -1) { // pattern has group
-            if (vi == -1) return false;
-
-            String vp = servicePattern.substring(vip + 1);
-            servicePattern = servicePattern.substring(0, vip);
-
-            String v = serviceName.substring(vi + 1);
-            if (!vp.equals(v)) return false;
-        }
-        if (vi != -1)
-            serviceName = serviceName.substring(0, vi);
-
-        return ParseUtils.isMatchGlobPattern(servicePattern, serviceName);
-    }
-
-    static Map<String, Map<String, String>> getUrlsMatchedCondition(Map<String, RouteRule.MatchPair> condition,
-                                                                    Map<String, String> parameters, Map<String, Map<String, String>> url2Sample) {
-        Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
-        for (Map.Entry<String, Map<String, String>> entry : url2Sample.entrySet()) {
-            Map<String, String> sample = entry.getValue();
-
-            Map<String, String> params = new HashMap<String, String>();
-            params.putAll(sample);
-            params.putAll(parameters);
-
-            if (RouteRuleUtils.isMatchCondition(condition, params, sample)) {
-                result.put(entry.getKey(), entry.getValue());
-            }
-        }
-        return result;
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/DatabaseStatusChecker.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/DatabaseStatusChecker.java
deleted file mode 100644
index 6336c22..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/DatabaseStatusChecker.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.registry.common.status;
-
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import com.alibaba.dubbo.common.status.Status;
-import com.alibaba.dubbo.common.status.StatusChecker;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-
-/**
- * DatabaseStatus
- *
- */
-public class DatabaseStatusChecker implements StatusChecker {
-
-    private static final Logger logger = LoggerFactory.getLogger(DatabaseStatusChecker.class);
-
-    private int version;
-
-    private String message;
-
-    @Autowired
-    private DataSource dataSource;
-
-    public void setDataSource(DataSource dataSource) {
-        this.dataSource = dataSource;
-        check(); // init
-    }
-
-    public Status check() {
-        boolean ok;
-        try {
-            Connection connection = dataSource.getConnection();
-            try {
-                DatabaseMetaData metaData = connection.getMetaData();
-                ResultSet resultSet = metaData.getTypeInfo();
-                try {
-                    ok = resultSet.next();
-                } finally {
-                    resultSet.close();
-                }
-                if (message == null) {
-                    message = metaData.getURL()
-                            + " (" + metaData.getDatabaseProductName()
-                            + " " + metaData.getDatabaseProductVersion()
-                            + ", " + getIsolation(metaData.getDefaultTransactionIsolation()) + ")";
-                }
-                if (version == 0) {
-                    version = metaData.getDatabaseMajorVersion();
-                }
-            } finally {
-                connection.close();
-            }
-        } catch (Throwable e) {
-            logger.error(e.getMessage(), e);
-            ok = false;
-        }
-        return new Status(!ok ? Status.Level.ERROR : (version < 5 ? Status.Level.WARN : Status.Level.OK), message);
-    }
-
-    private String getIsolation(int i) {
-        if (i == Connection.TRANSACTION_READ_COMMITTED) {
-            return "READ_COMMITTED";
-        }
-        if (i == Connection.TRANSACTION_READ_UNCOMMITTED) {
-            return "READ_UNCOMMITTED";
-        }
-        if (i == Connection.TRANSACTION_REPEATABLE_READ) {
-            return "REPEATABLE_READ";
-        }
-        if (i == Connection.TRANSACTION_SERIALIZABLE) {
-            return "SERIALIZABLE)";
-        }
-        return "NONE";
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/LoadStatusChecker.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/LoadStatusChecker.java
deleted file mode 100644
index f555fdb..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/LoadStatusChecker.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.registry.common.status;
-
-import com.alibaba.dubbo.common.status.Status;
-import com.alibaba.dubbo.common.status.StatusChecker;
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.OperatingSystemMXBean;
-import java.lang.reflect.Method;
-
-/**
- * Load StatusController
- *
- */
-public class LoadStatusChecker implements StatusChecker {
-
-    public Status check() {
-        OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean();
-        double load;
-        try {
-            Method method = OperatingSystemMXBean.class.getMethod("getSystemLoadAverage", new Class<?>[0]);
-            load = (Double) method.invoke(operatingSystemMXBean, new Object[0]);
-        } catch (Throwable e) {
-            load = -1;
-        }
-        int cpu = operatingSystemMXBean.getAvailableProcessors();
-        return new Status(load < 0 ? Status.Level.UNKNOWN : (load < cpu ? Status.Level.OK : Status.Level.WARN), "Load: " + load + " / CPU: " + cpu);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/MemoryStatusChecker.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/MemoryStatusChecker.java
deleted file mode 100644
index fa1ac7d..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/status/MemoryStatusChecker.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.registry.common.status;
-
-import com.alibaba.dubbo.common.status.Status;
-import com.alibaba.dubbo.common.status.StatusChecker;
-
-/**
- * MemoryStatus
- *
- */
-public class MemoryStatusChecker implements StatusChecker {
-
-    public Status check() {
-        Runtime runtime = Runtime.getRuntime();
-        long freeMemory = runtime.freeMemory();
-        long totalMemory = runtime.totalMemory();
-        long maxMemory = runtime.maxMemory();
-        boolean ok = (maxMemory - (totalMemory - freeMemory) > 2048); // Alarm when spare memory < 2M
-        String msg = "Max:" + (maxMemory / 1024 / 1024) + "M, Total:"
-                + (totalMemory / 1024 / 1024) + "M, Free:" + (freeMemory / 1024 / 1024)
-                + "M, Use:" + ((totalMemory / 1024 / 1024) - (freeMemory / 1024 / 1024)) + "M";
-        return new Status(ok ? Status.Level.OK : Status.Level.WARN, msg);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Coder.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Coder.java
deleted file mode 100644
index 874adca..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Coder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import com.alibaba.dubbo.common.io.Bytes;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class Coder {
-
-    private Coder() {
-    }
-
-    public static String encodeHex(byte[] bytes) {
-        StringBuffer buffer = new StringBuffer(bytes.length * 2);
-        for (int i = 0; i < bytes.length; i++) {
-            if (((int) bytes[i] & 0xff) < 0x10)
-                buffer.append("0");
-            buffer.append(Long.toString((int) bytes[i] & 0xff, 16));
-        }
-        return buffer.toString();
-    }
-
-    public static String encodeMd5(String source) {
-        return encodeMd5(source.getBytes());
-    }
-
-    public static String encodeMd5(byte[] source) {
-        try {
-            return encodeHex(MessageDigest.getInstance("MD5").digest(source));
-        } catch (NoSuchAlgorithmException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        }
-    }
-
-    public static String encodeBase64(String source) {
-        return Bytes.bytes2base64(source.getBytes());
-    }
-
-    public static String decodeBase64(String source) {
-        return new String(Bytes.base642bytes(source));
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Entities.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Entities.java
deleted file mode 100644
index 8d321c7..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Entities.java
+++ /dev/null
@@ -1,953 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeMap;
-
-/**
- * <p>
- * Provides HTML and XML entity utilities.
- * </p>
- *
- * @version $Id: Entities.java 181192 2012-06-21 05:05:47Z tony.chenl $
- * @see <a href="http://hotwired.lycos.com/webmonkey/reference/special_characters/">ISO Entities</a>
- * @see <a href="http://www.w3.org/TR/REC-html32#latin1">HTML 3.2 Character Entities for ISO Latin-1</a>
- * @see <a href="http://www.w3.org/TR/REC-html40/sgml/entities.html">HTML 4.0 Character entity references</a>
- * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3">HTML 4.01 Character References</a>
- * @see <a href="http://www.w3.org/TR/html401/charset.html#code-position">HTML 4.01 Code positions</a>
- * @since 2.0
- */
-class Entities {
-
-    /**
-     * <p>
-     * The set of entities supported by standard XML.
-     * </p>
-     */
-    public static final Entities XML;
-    /**
-     * <p>
-     * The set of entities supported by HTML 3.2.
-     * </p>
-     */
-    public static final Entities HTML32;
-    /**
-     * <p>
-     * The set of entities supported by HTML 4.0.
-     * </p>
-     */
-    public static final Entities HTML40;
-    // package scoped for testing
-    static final String[][] ISO8859_1_ARRAY = {{"nbsp", "160"}, // non-breaking space
-            {"iexcl", "161"}, // inverted exclamation mark
-            {"cent", "162"}, // cent sign
-            {"pound", "163"}, // pound sign
-            {"curren", "164"}, // currency sign
-            {"yen", "165"}, // yen sign = yuan sign
-            {"brvbar", "166"}, // broken bar = broken vertical bar
-            {"sect", "167"}, // section sign
-            {"uml", "168"}, // diaeresis = spacing diaeresis
-            {"copy", "169"}, // � - copyright sign
-            {"ordf", "170"}, // feminine ordinal indicator
-            {"laquo", "171"}, // left-pointing double angle quotation mark = left pointing guillemet
-            {"not", "172"}, // not sign
-            {"shy", "173"}, // soft hyphen = discretionary hyphen
-            {"reg", "174"}, // � - registered trademark sign
-            {"macr", "175"}, // macron = spacing macron = overline = APL overbar
-            {"deg", "176"}, // degree sign
-            {"plusmn", "177"}, // plus-minus sign = plus-or-minus sign
-            {"sup2", "178"}, // superscript two = superscript digit two = squared
-            {"sup3", "179"}, // superscript three = superscript digit three = cubed
-            {"acute", "180"}, // acute accent = spacing acute
-            {"micro", "181"}, // micro sign
-            {"para", "182"}, // pilcrow sign = paragraph sign
-            {"middot", "183"}, // middle dot = Georgian comma = Greek middle dot
-            {"cedil", "184"}, // cedilla = spacing cedilla
-            {"sup1", "185"}, // superscript one = superscript digit one
-            {"ordm", "186"}, // masculine ordinal indicator
-            {"raquo", "187"}, // right-pointing double angle quotation mark = right pointing guillemet
-            {"frac14", "188"}, // vulgar fraction one quarter = fraction one quarter
-            {"frac12", "189"}, // vulgar fraction one half = fraction one half
-            {"frac34", "190"}, // vulgar fraction three quarters = fraction three quarters
-            {"iquest", "191"}, // inverted question mark = turned question mark
-            {"Agrave", "192"}, // � - uppercase A, grave accent
-            {"Aacute", "193"}, // � - uppercase A, acute accent
-            {"Acirc", "194"}, // � - uppercase A, circumflex accent
-            {"Atilde", "195"}, // � - uppercase A, tilde
-            {"Auml", "196"}, // � - uppercase A, umlaut
-            {"Aring", "197"}, // � - uppercase A, ring
-            {"AElig", "198"}, // � - uppercase AE
-            {"Ccedil", "199"}, // � - uppercase C, cedilla
-            {"Egrave", "200"}, // � - uppercase E, grave accent
-            {"Eacute", "201"}, // � - uppercase E, acute accent
-            {"Ecirc", "202"}, // � - uppercase E, circumflex accent
-            {"Euml", "203"}, // � - uppercase E, umlaut
-            {"Igrave", "204"}, // � - uppercase I, grave accent
-            {"Iacute", "205"}, // � - uppercase I, acute accent
-            {"Icirc", "206"}, // � - uppercase I, circumflex accent
-            {"Iuml", "207"}, // � - uppercase I, umlaut
-            {"ETH", "208"}, // � - uppercase Eth, Icelandic
-            {"Ntilde", "209"}, // � - uppercase N, tilde
-            {"Ograve", "210"}, // � - uppercase O, grave accent
-            {"Oacute", "211"}, // � - uppercase O, acute accent
-            {"Ocirc", "212"}, // � - uppercase O, circumflex accent
-            {"Otilde", "213"}, // � - uppercase O, tilde
-            {"Ouml", "214"}, // � - uppercase O, umlaut
-            {"times", "215"}, // multiplication sign
-            {"Oslash", "216"}, // � - uppercase O, slash
-            {"Ugrave", "217"}, // � - uppercase U, grave accent
-            {"Uacute", "218"}, // � - uppercase U, acute accent
-            {"Ucirc", "219"}, // � - uppercase U, circumflex accent
-            {"Uuml", "220"}, // � - uppercase U, umlaut
-            {"Yacute", "221"}, // � - uppercase Y, acute accent
-            {"THORN", "222"}, // � - uppercase THORN, Icelandic
-            {"szlig", "223"}, // � - lowercase sharps, German
-            {"agrave", "224"}, // � - lowercase a, grave accent
-            {"aacute", "225"}, // � - lowercase a, acute accent
-            {"acirc", "226"}, // � - lowercase a, circumflex accent
-            {"atilde", "227"}, // � - lowercase a, tilde
-            {"auml", "228"}, // � - lowercase a, umlaut
-            {"aring", "229"}, // � - lowercase a, ring
-            {"aelig", "230"}, // � - lowercase ae
-            {"ccedil", "231"}, // � - lowercase c, cedilla
-            {"egrave", "232"}, // � - lowercase e, grave accent
-            {"eacute", "233"}, // � - lowercase e, acute accent
-            {"ecirc", "234"}, // � - lowercase e, circumflex accent
-            {"euml", "235"}, // � - lowercase e, umlaut
-            {"igrave", "236"}, // � - lowercase i, grave accent
-            {"iacute", "237"}, // � - lowercase i, acute accent
-            {"icirc", "238"}, // � - lowercase i, circumflex accent
-            {"iuml", "239"}, // � - lowercase i, umlaut
-            {"eth", "240"}, // � - lowercase eth, Icelandic
-            {"ntilde", "241"}, // � - lowercase n, tilde
-            {"ograve", "242"}, // � - lowercase o, grave accent
-            {"oacute", "243"}, // � - lowercase o, acute accent
-            {"ocirc", "244"}, // � - lowercase o, circumflex accent
-            {"otilde", "245"}, // � - lowercase o, tilde
-            {"ouml", "246"}, // � - lowercase o, umlaut
-            {"divide", "247"}, // division sign
-            {"oslash", "248"}, // � - lowercase o, slash
-            {"ugrave", "249"}, // � - lowercase u, grave accent
-            {"uacute", "250"}, // � - lowercase u, acute accent
-            {"ucirc", "251"}, // � - lowercase u, circumflex accent
-            {"uuml", "252"}, // � - lowercase u, umlaut
-            {"yacute", "253"}, // � - lowercase y, acute accent
-            {"thorn", "254"}, // � - lowercase thorn, Icelandic
-            {"yuml", "255"}, // � - lowercase y, umlaut
-    };
-    // http://www.w3.org/TR/REC-html40/sgml/entities.html
-    // package scoped for testing
-    static final String[][] HTML40_ARRAY = {
-            // <!-- Latin Extended-B -->
-            {"fnof", "402"}, // latin small f with hook = function= florin, U+0192 ISOtech -->
-            // <!-- Greek -->
-            {"Alpha", "913"}, // greek capital letter alpha, U+0391 -->
-            {"Beta", "914"}, // greek capital letter beta, U+0392 -->
-            {"Gamma", "915"}, // greek capital letter gamma,U+0393 ISOgrk3 -->
-            {"Delta", "916"}, // greek capital letter delta,U+0394 ISOgrk3 -->
-            {"Epsilon", "917"}, // greek capital letter epsilon, U+0395 -->
-            {"Zeta", "918"}, // greek capital letter zeta, U+0396 -->
-            {"Eta", "919"}, // greek capital letter eta, U+0397 -->
-            {"Theta", "920"}, // greek capital letter theta,U+0398 ISOgrk3 -->
-            {"Iota", "921"}, // greek capital letter iota, U+0399 -->
-            {"Kappa", "922"}, // greek capital letter kappa, U+039A -->
-            {"Lambda", "923"}, // greek capital letter lambda,U+039B ISOgrk3 -->
-            {"Mu", "924"}, // greek capital letter mu, U+039C -->
-            {"Nu", "925"}, // greek capital letter nu, U+039D -->
-            {"Xi", "926"}, // greek capital letter xi, U+039E ISOgrk3 -->
-            {"Omicron", "927"}, // greek capital letter omicron, U+039F -->
-            {"Pi", "928"}, // greek capital letter pi, U+03A0 ISOgrk3 -->
-            {"Rho", "929"}, // greek capital letter rho, U+03A1 -->
-            // <!-- there is no Sigmaf, and no U+03A2 character either -->
-            {"Sigma", "931"}, // greek capital letter sigma,U+03A3 ISOgrk3 -->
-            {"Tau", "932"}, // greek capital letter tau, U+03A4 -->
-            {"Upsilon", "933"}, // greek capital letter upsilon,U+03A5 ISOgrk3 -->
-            {"Phi", "934"}, // greek capital letter phi,U+03A6 ISOgrk3 -->
-            {"Chi", "935"}, // greek capital letter chi, U+03A7 -->
-            {"Psi", "936"}, // greek capital letter psi,U+03A8 ISOgrk3 -->
-            {"Omega", "937"}, // greek capital letter omega,U+03A9 ISOgrk3 -->
-            {"alpha", "945"}, // greek small letter alpha,U+03B1 ISOgrk3 -->
-            {"beta", "946"}, // greek small letter beta, U+03B2 ISOgrk3 -->
-            {"gamma", "947"}, // greek small letter gamma,U+03B3 ISOgrk3 -->
-            {"delta", "948"}, // greek small letter delta,U+03B4 ISOgrk3 -->
-            {"epsilon", "949"}, // greek small letter epsilon,U+03B5 ISOgrk3 -->
-            {"zeta", "950"}, // greek small letter zeta, U+03B6 ISOgrk3 -->
-            {"eta", "951"}, // greek small letter eta, U+03B7 ISOgrk3 -->
-            {"theta", "952"}, // greek small letter theta,U+03B8 ISOgrk3 -->
-            {"iota", "953"}, // greek small letter iota, U+03B9 ISOgrk3 -->
-            {"kappa", "954"}, // greek small letter kappa,U+03BA ISOgrk3 -->
-            {"lambda", "955"}, // greek small letter lambda,U+03BB ISOgrk3 -->
-            {"mu", "956"}, // greek small letter mu, U+03BC ISOgrk3 -->
-            {"nu", "957"}, // greek small letter nu, U+03BD ISOgrk3 -->
-            {"xi", "958"}, // greek small letter xi, U+03BE ISOgrk3 -->
-            {"omicron", "959"}, // greek small letter omicron, U+03BF NEW -->
-            {"pi", "960"}, // greek small letter pi, U+03C0 ISOgrk3 -->
-            {"rho", "961"}, // greek small letter rho, U+03C1 ISOgrk3 -->
-            {"sigmaf", "962"}, // greek small letter final sigma,U+03C2 ISOgrk3 -->
-            {"sigma", "963"}, // greek small letter sigma,U+03C3 ISOgrk3 -->
-            {"tau", "964"}, // greek small letter tau, U+03C4 ISOgrk3 -->
-            {"upsilon", "965"}, // greek small letter upsilon,U+03C5 ISOgrk3 -->
-            {"phi", "966"}, // greek small letter phi, U+03C6 ISOgrk3 -->
-            {"chi", "967"}, // greek small letter chi, U+03C7 ISOgrk3 -->
-            {"psi", "968"}, // greek small letter psi, U+03C8 ISOgrk3 -->
-            {"omega", "969"}, // greek small letter omega,U+03C9 ISOgrk3 -->
-            {"thetasym", "977"}, // greek small letter theta symbol,U+03D1 NEW -->
-            {"upsih", "978"}, // greek upsilon with hook symbol,U+03D2 NEW -->
-            {"piv", "982"}, // greek pi symbol, U+03D6 ISOgrk3 -->
-            // <!-- General Punctuation -->
-            {"bull", "8226"}, // bullet = black small circle,U+2022 ISOpub -->
-            // <!-- bullet is NOT the same as bullet operator, U+2219 -->
-            {"hellip", "8230"}, // horizontal ellipsis = three dot leader,U+2026 ISOpub -->
-            {"prime", "8242"}, // prime = minutes = feet, U+2032 ISOtech -->
-            {"Prime", "8243"}, // double prime = seconds = inches,U+2033 ISOtech -->
-            {"oline", "8254"}, // overline = spacing overscore,U+203E NEW -->
-            {"frasl", "8260"}, // fraction slash, U+2044 NEW -->
-            // <!-- Letterlike Symbols -->
-            {"weierp", "8472"}, // script capital P = power set= Weierstrass p, U+2118 ISOamso -->
-            {"image", "8465"}, // blackletter capital I = imaginary part,U+2111 ISOamso -->
-            {"real", "8476"}, // blackletter capital R = real part symbol,U+211C ISOamso -->
-            {"trade", "8482"}, // trade mark sign, U+2122 ISOnum -->
-            {"alefsym", "8501"}, // alef symbol = first transfinite cardinal,U+2135 NEW -->
-            // <!-- alef symbol is NOT the same as hebrew letter alef,U+05D0 although the
-            // same glyph could be used to depict both characters -->
-            // <!-- Arrows -->
-            {"larr", "8592"}, // leftwards arrow, U+2190 ISOnum -->
-            {"uarr", "8593"}, // upwards arrow, U+2191 ISOnum-->
-            {"rarr", "8594"}, // rightwards arrow, U+2192 ISOnum -->
-            {"darr", "8595"}, // downwards arrow, U+2193 ISOnum -->
-            {"harr", "8596"}, // left right arrow, U+2194 ISOamsa -->
-            {"crarr", "8629"}, // downwards arrow with corner leftwards= carriage return, U+21B5 NEW -->
-            {"lArr", "8656"}, // leftwards double arrow, U+21D0 ISOtech -->
-            // <!-- ISO 10646 does not say that lArr is the same as the 'is implied by'
-            // arrow but also does not have any other character for that function.
-            // So ? lArr canbe used for 'is implied by' as ISOtech suggests -->
-            {"uArr", "8657"}, // upwards double arrow, U+21D1 ISOamsa -->
-            {"rArr", "8658"}, // rightwards double arrow,U+21D2 ISOtech -->
-            // <!-- ISO 10646 does not say this is the 'implies' character but does not
-            // have another character with this function so ?rArr can be used for
-            // 'implies' as ISOtech suggests -->
-            {"dArr", "8659"}, // downwards double arrow, U+21D3 ISOamsa -->
-            {"hArr", "8660"}, // left right double arrow,U+21D4 ISOamsa -->
-            // <!-- Mathematical Operators -->
-            {"forall", "8704"}, // for all, U+2200 ISOtech -->
-            {"part", "8706"}, // partial differential, U+2202 ISOtech -->
-            {"exist", "8707"}, // there exists, U+2203 ISOtech -->
-            {"empty", "8709"}, // empty set = null set = diameter,U+2205 ISOamso -->
-            {"nabla", "8711"}, // nabla = backward difference,U+2207 ISOtech -->
-            {"isin", "8712"}, // element of, U+2208 ISOtech -->
-            {"notin", "8713"}, // not an element of, U+2209 ISOtech -->
-            {"ni", "8715"}, // contains as member, U+220B ISOtech -->
-            // <!-- should there be a more memorable name than 'ni'? -->
-            {"prod", "8719"}, // n-ary product = product sign,U+220F ISOamsb -->
-            // <!-- prod is NOT the same character as U+03A0 'greek capital letter pi'
-            // though the same glyph might be used for both -->
-            {"sum", "8721"}, // n-ary summation, U+2211 ISOamsb -->
-            // <!-- sum is NOT the same character as U+03A3 'greek capital letter sigma'
-            // though the same glyph might be used for both -->
-            {"minus", "8722"}, // minus sign, U+2212 ISOtech -->
-            {"lowast", "8727"}, // asterisk operator, U+2217 ISOtech -->
-            {"radic", "8730"}, // square root = radical sign,U+221A ISOtech -->
-            {"prop", "8733"}, // proportional to, U+221D ISOtech -->
-            {"infin", "8734"}, // infinity, U+221E ISOtech -->
-            {"ang", "8736"}, // angle, U+2220 ISOamso -->
-            {"and", "8743"}, // logical and = wedge, U+2227 ISOtech -->
-            {"or", "8744"}, // logical or = vee, U+2228 ISOtech -->
-            {"cap", "8745"}, // intersection = cap, U+2229 ISOtech -->
-            {"cup", "8746"}, // union = cup, U+222A ISOtech -->
-            {"int", "8747"}, // integral, U+222B ISOtech -->
-            {"there4", "8756"}, // therefore, U+2234 ISOtech -->
-            {"sim", "8764"}, // tilde operator = varies with = similar to,U+223C ISOtech -->
-            // <!-- tilde operator is NOT the same character as the tilde, U+007E,although
-            // the same glyph might be used to represent both -->
-            {"cong", "8773"}, // approximately equal to, U+2245 ISOtech -->
-            {"asymp", "8776"}, // almost equal to = asymptotic to,U+2248 ISOamsr -->
-            {"ne", "8800"}, // not equal to, U+2260 ISOtech -->
-            {"equiv", "8801"}, // identical to, U+2261 ISOtech -->
-            {"le", "8804"}, // less-than or equal to, U+2264 ISOtech -->
-            {"ge", "8805"}, // greater-than or equal to,U+2265 ISOtech -->
-            {"sub", "8834"}, // subset of, U+2282 ISOtech -->
-            {"sup", "8835"}, // superset of, U+2283 ISOtech -->
-            // <!-- note that nsup, 'not a superset of, U+2283' is not covered by the
-            // Symbol font encoding and is not included. Should it be, for symmetry?
-            // It is in ISOamsn --> <!ENTITY nsub", "8836"},
-            // not a subset of, U+2284 ISOamsn -->
-            {"sube", "8838"}, // subset of or equal to, U+2286 ISOtech -->
-            {"supe", "8839"}, // superset of or equal to,U+2287 ISOtech -->
-            {"oplus", "8853"}, // circled plus = direct sum,U+2295 ISOamsb -->
-            {"otimes", "8855"}, // circled times = vector product,U+2297 ISOamsb -->
-            {"perp", "8869"}, // up tack = orthogonal to = perpendicular,U+22A5 ISOtech -->
-            {"sdot", "8901"}, // dot operator, U+22C5 ISOamsb -->
-            // <!-- dot operator is NOT the same character as U+00B7 middle dot -->
-            // <!-- Miscellaneous Technical -->
-            {"lceil", "8968"}, // left ceiling = apl upstile,U+2308 ISOamsc -->
-            {"rceil", "8969"}, // right ceiling, U+2309 ISOamsc -->
-            {"lfloor", "8970"}, // left floor = apl downstile,U+230A ISOamsc -->
-            {"rfloor", "8971"}, // right floor, U+230B ISOamsc -->
-            {"lang", "9001"}, // left-pointing angle bracket = bra,U+2329 ISOtech -->
-            // <!-- lang is NOT the same character as U+003C 'less than' or U+2039 'single left-pointing angle quotation
-            // mark' -->
-            {"rang", "9002"}, // right-pointing angle bracket = ket,U+232A ISOtech -->
-            // <!-- rang is NOT the same character as U+003E 'greater than' or U+203A
-            // 'single right-pointing angle quotation mark' -->
-            // <!-- Geometric Shapes -->
-            {"loz", "9674"}, // lozenge, U+25CA ISOpub -->
-            // <!-- Miscellaneous Symbols -->
-            {"spades", "9824"}, // black spade suit, U+2660 ISOpub -->
-            // <!-- black here seems to mean filled as opposed to hollow -->
-            {"clubs", "9827"}, // black club suit = shamrock,U+2663 ISOpub -->
-            {"hearts", "9829"}, // black heart suit = valentine,U+2665 ISOpub -->
-            {"diams", "9830"}, // black diamond suit, U+2666 ISOpub -->
-
-            // <!-- Latin Extended-A -->
-            {"OElig", "338"}, // -- latin capital ligature OE,U+0152 ISOlat2 -->
-            {"oelig", "339"}, // -- latin small ligature oe, U+0153 ISOlat2 -->
-            // <!-- ligature is a misnomer, this is a separate character in some languages -->
-            {"Scaron", "352"}, // -- latin capital letter S with caron,U+0160 ISOlat2 -->
-            {"scaron", "353"}, // -- latin small letter s with caron,U+0161 ISOlat2 -->
-            {"Yuml", "376"}, // -- latin capital letter Y with diaeresis,U+0178 ISOlat2 -->
-            // <!-- Spacing Modifier Letters -->
-            {"circ", "710"}, // -- modifier letter circumflex accent,U+02C6 ISOpub -->
-            {"tilde", "732"}, // small tilde, U+02DC ISOdia -->
-            // <!-- General Punctuation -->
-            {"ensp", "8194"}, // en space, U+2002 ISOpub -->
-            {"emsp", "8195"}, // em space, U+2003 ISOpub -->
-            {"thinsp", "8201"}, // thin space, U+2009 ISOpub -->
-            {"zwnj", "8204"}, // zero width non-joiner,U+200C NEW RFC 2070 -->
-            {"zwj", "8205"}, // zero width joiner, U+200D NEW RFC 2070 -->
-            {"lrm", "8206"}, // left-to-right mark, U+200E NEW RFC 2070 -->
-            {"rlm", "8207"}, // right-to-left mark, U+200F NEW RFC 2070 -->
-            {"ndash", "8211"}, // en dash, U+2013 ISOpub -->
-            {"mdash", "8212"}, // em dash, U+2014 ISOpub -->
-            {"lsquo", "8216"}, // left single quotation mark,U+2018 ISOnum -->
-            {"rsquo", "8217"}, // right single quotation mark,U+2019 ISOnum -->
-            {"sbquo", "8218"}, // single low-9 quotation mark, U+201A NEW -->
-            {"ldquo", "8220"}, // left double quotation mark,U+201C ISOnum -->
-            {"rdquo", "8221"}, // right double quotation mark,U+201D ISOnum -->
-            {"bdquo", "8222"}, // double low-9 quotation mark, U+201E NEW -->
-            {"dagger", "8224"}, // dagger, U+2020 ISOpub -->
-            {"Dagger", "8225"}, // double dagger, U+2021 ISOpub -->
-            {"permil", "8240"}, // per mille sign, U+2030 ISOtech -->
-            {"lsaquo", "8249"}, // single left-pointing angle quotation mark,U+2039 ISO proposed -->
-            // <!-- lsaquo is proposed but not yet ISO standardized -->
-            {"rsaquo", "8250"}, // single right-pointing angle quotation mark,U+203A ISO proposed -->
-            // <!-- rsaquo is proposed but not yet ISO standardized -->
-            {"euro", "8364"}, // -- euro sign, U+20AC NEW -->
-    };
-    private static final String[][] BASIC_ARRAY = {{"quot", "34"}, // " - double-quote
-            {"amp", "38"}, // & - ampersand
-            {"lt", "60"}, // < - less-than
-            {"gt", "62"}, // > - greater-than
-    };
-    private static final String[][] APOS_ARRAY = {{"apos", "39"}, // XML apostrophe
-    };
-
-    static {
-        XML = new Entities();
-        XML.addEntities(BASIC_ARRAY);
-        XML.addEntities(APOS_ARRAY);
-    }
-
-    static {
-        HTML32 = new Entities();
-        HTML32.addEntities(BASIC_ARRAY);
-        HTML32.addEntities(ISO8859_1_ARRAY);
-    }
-
-    static {
-        HTML40 = new Entities();
-        fillWithHtml40Entities(HTML40);
-    }
-
-    // package scoped for testing
-    EntityMap map = new Entities.LookupEntityMap();
-
-    /**
-     * <p>
-     * Fills the specified entities instance with HTML 40 entities.
-     * </p>
-     *
-     * @param entities the instance to be filled.
-     */
-    static void fillWithHtml40Entities(Entities entities) {
-        entities.addEntities(BASIC_ARRAY);
-        entities.addEntities(ISO8859_1_ARRAY);
-        entities.addEntities(HTML40_ARRAY);
-    }
-
-    /**
-     * <p>
-     * Adds entities to this entity.
-     * </p>
-     *
-     * @param entityArray array of entities to be added
-     */
-    public void addEntities(String[][] entityArray) {
-        for (int i = 0; i < entityArray.length; ++i) {
-            addEntity(entityArray[i][0], Integer.parseInt(entityArray[i][1]));
-        }
-    }
-
-    /**
-     * <p>
-     * Add an entity to this entity.
-     * </p>
-     *
-     * @param name  name of the entity
-     * @param value vale of the entity
-     */
-    public void addEntity(String name, int value) {
-        map.add(name, value);
-    }
-
-    /**
-     * <p>
-     * Returns the name of the entity identified by the specified value.
-     * </p>
-     *
-     * @param value the value to locate
-     * @return entity name associated with the specified value
-     */
-    public String entityName(int value) {
-        return map.name(value);
-    }
-
-    /**
-     * <p>
-     * Returns the value of the entity identified by the specified name.
-     * </p>
-     *
-     * @param name the name to locate
-     * @return entity value associated with the specified name
-     */
-    public int entityValue(String name) {
-        return map.value(name);
-    }
-
-    /**
-     * <p>
-     * Escapes the characters in a <code>String</code>.
-     * </p>
-     * <p>
-     * <p>
-     * For example, if you have called addEntity(&quot;foo&quot;, 0xA1), escape(&quot;\u00A1&quot;) will return
-     * &quot;&amp;foo;&quot;
-     * </p>
-     *
-     * @param str The <code>String</code> to escape.
-     * @return A new escaped <code>String</code>.
-     */
-    public String escape(String str) {
-        StringWriter stringWriter = createStringWriter(str);
-        try {
-            this.escape(stringWriter, str);
-        } catch (IOException e) {
-            // This should never happen because ALL the StringWriter methods called by #escape(Writer, String) do not
-            // throw IOExceptions.
-            throw new IllegalStateException(e);
-        }
-        return stringWriter.toString();
-    }
-
-    /**
-     * <p>
-     * Escapes the characters in the <code>String</code> passed and writes the result to the <code>Writer</code>
-     * passed.
-     * </p>
-     *
-     * @param writer The <code>Writer</code> to write the results of the escaping to. Assumed to be a non-null value.
-     * @param str    The <code>String</code> to escape. Assumed to be a non-null value.
-     * @throws IOException when <code>Writer</code> passed throws the exception from calls to the {@link Writer#write(int)}
-     *                     methods.
-     * @see #escape(String)
-     * @see Writer
-     */
-    public void escape(Writer writer, String str) throws IOException {
-        int len = str.length();
-        for (int i = 0; i < len; i++) {
-            char c = str.charAt(i);
-            String entityName = this.entityName(c);
-            if (entityName == null) {
-                if (c > 0x7F) {
-                    writer.write("&#");
-                    writer.write(Integer.toString(c, 10));
-                    writer.write(';');
-                } else {
-                    writer.write(c);
-                }
-            } else {
-                writer.write('&');
-                writer.write(entityName);
-                writer.write(';');
-            }
-        }
-    }
-
-    /**
-     * <p>
-     * Unescapes the entities in a <code>String</code>.
-     * </p>
-     * <p>
-     * <p>
-     * For example, if you have called addEntity(&quot;foo&quot;, 0xA1), unescape(&quot;&amp;foo;&quot;) will return
-     * &quot;\u00A1&quot;
-     * </p>
-     *
-     * @param str The <code>String</code> to escape.
-     * @return A new escaped <code>String</code>.
-     */
-    public String unescape(String str) {
-        int firstAmp = str.indexOf('&');
-        if (firstAmp < 0) {
-            return str;
-        } else {
-            StringWriter stringWriter = createStringWriter(str);
-            try {
-                this.doUnescape(stringWriter, str, firstAmp);
-            } catch (IOException e) {
-                // This should never happen because ALL the StringWriter methods called by #escape(Writer, String)
-                // do not throw IOExceptions.
-                throw new IllegalStateException(e);
-            }
-            return stringWriter.toString();
-        }
-    }
-
-    /**
-     * Make the StringWriter 10% larger than the source String to avoid growing the writer
-     *
-     * @param str The source string
-     * @return A newly created StringWriter
-     */
-    private StringWriter createStringWriter(String str) {
-        return new StringWriter((int) (str.length() + (str.length() * 0.1)));
-    }
-
-    /**
-     * <p>
-     * Unescapes the escaped entities in the <code>String</code> passed and writes the result to the
-     * <code>Writer</code> passed.
-     * </p>
-     *
-     * @param writer The <code>Writer</code> to write the results to; assumed to be non-null.
-     * @param str    The source <code>String</code> to unescape; assumed to be non-null.
-     * @throws IOException when <code>Writer</code> passed throws the exception from calls to the {@link Writer#write(int)}
-     *                     methods.
-     * @see #escape(String)
-     * @see Writer
-     */
-    public void unescape(Writer writer, String str) throws IOException {
-        int firstAmp = str.indexOf('&');
-        if (firstAmp < 0) {
-            writer.write(str);
-            return;
-        } else {
-            doUnescape(writer, str, firstAmp);
-        }
-    }
-
-    /**
-     * Underlying unescape method that allows the optimisation of not starting from the 0 index again.
-     *
-     * @param writer   The <code>Writer</code> to write the results to; assumed to be non-null.
-     * @param str      The source <code>String</code> to unescape; assumed to be non-null.
-     * @param firstAmp The <code>int</code> index of the first ampersand in the source String.
-     * @throws IOException when <code>Writer</code> passed throws the exception from calls to the {@link Writer#write(int)}
-     *                     methods.
-     */
-    private void doUnescape(Writer writer, String str, int firstAmp) throws IOException {
-        writer.write(str, 0, firstAmp);
-        int len = str.length();
-        for (int i = firstAmp; i < len; i++) {
-            char c = str.charAt(i);
-            if (c == '&') {
-                int nextIdx = i + 1;
-                int semiColonIdx = str.indexOf(';', nextIdx);
-                if (semiColonIdx == -1) {
-                    writer.write(c);
-                    continue;
-                }
-                int amphersandIdx = str.indexOf('&', i + 1);
-                if (amphersandIdx != -1 && amphersandIdx < semiColonIdx) {
-                    // Then the text looks like &...&...;
-                    writer.write(c);
-                    continue;
-                }
-                String entityContent = str.substring(nextIdx, semiColonIdx);
-                int entityValue = -1;
-                int entityContentLen = entityContent.length();
-                if (entityContentLen > 0) {
-                    if (entityContent.charAt(0) == '#') { // escaped value content is an integer (decimal or
-                        // hexidecimal)
-                        if (entityContentLen > 1) {
-                            char isHexChar = entityContent.charAt(1);
-                            try {
-                                switch (isHexChar) {
-                                    case 'X':
-                                    case 'x': {
-                                        entityValue = Integer.parseInt(entityContent.substring(2), 16);
-                                        break;
-                                    }
-                                    default: {
-                                        entityValue = Integer.parseInt(entityContent.substring(1), 10);
-                                    }
-                                }
-                                if (entityValue > 0xFFFF) {
-                                    entityValue = -1;
-                                }
-                            } catch (NumberFormatException e) {
-                                entityValue = -1;
-                            }
-                        }
-                    } else { // escaped value content is an entity name
-                        entityValue = this.entityValue(entityContent);
-                    }
-                }
-
-                if (entityValue == -1) {
-                    writer.write('&');
-                    writer.write(entityContent);
-                    writer.write(';');
-                } else {
-                    writer.write(entityValue);
-                }
-                i = semiColonIdx; // move index up to the semi-colon
-            } else {
-                writer.write(c);
-            }
-        }
-    }
-
-    static interface EntityMap {
-        /**
-         * <p>
-         * Add an entry to this entity map.
-         * </p>
-         *
-         * @param name  the entity name
-         * @param value the entity value
-         */
-        void add(String name, int value);
-
-        /**
-         * <p>
-         * Returns the name of the entity identified by the specified value.
-         * </p>
-         *
-         * @param value the value to locate
-         * @return entity name associated with the specified value
-         */
-        String name(int value);
-
-        /**
-         * <p>
-         * Returns the value of the entity identified by the specified name.
-         * </p>
-         *
-         * @param name the name to locate
-         * @return entity value associated with the specified name
-         */
-        int value(String name);
-    }
-
-    static class PrimitiveEntityMap implements EntityMap {
-        private Map mapNameToValue = new HashMap();
-
-        private IntHashMap mapValueToName = new IntHashMap();
-
-        /**
-         * {@inheritDoc}
-         */
-        public void add(String name, int value) {
-            mapNameToValue.put(name, Integer.valueOf(value));
-            mapValueToName.put(value, name);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String name(int value) {
-            return (String) mapValueToName.get(value);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public int value(String name) {
-            Object value = mapNameToValue.get(name);
-            if (value == null) {
-                return -1;
-            }
-            return ((Integer) value).intValue();
-        }
-    }
-
-    static abstract class MapIntMap implements Entities.EntityMap {
-        protected Map mapNameToValue;
-
-        protected Map mapValueToName;
-
-        /**
-         * {@inheritDoc}
-         */
-        public void add(String name, int value) {
-            mapNameToValue.put(name, Integer.valueOf(value));
-            mapValueToName.put(Integer.valueOf(value), name);
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String name(int value) {
-            return (String) mapValueToName.get(Integer.valueOf(value));
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public int value(String name) {
-            Object value = mapNameToValue.get(name);
-            if (value == null) {
-                return -1;
-            }
-            return ((Integer) value).intValue();
-        }
-    }
-
-    static class HashEntityMap extends MapIntMap {
-        /**
-         * Constructs a new instance of <code>HashEntityMap</code>.
-         */
-        public HashEntityMap() {
-            mapNameToValue = new HashMap();
-            mapValueToName = new HashMap();
-        }
-    }
-
-    static class TreeEntityMap extends MapIntMap {
-        /**
-         * Constructs a new instance of <code>TreeEntityMap</code>.
-         */
-        public TreeEntityMap() {
-            mapNameToValue = new TreeMap();
-            mapValueToName = new TreeMap();
-        }
-    }
-
-    static class LookupEntityMap extends PrimitiveEntityMap {
-        private String[] lookupTable;
-
-        private int LOOKUP_TABLE_SIZE = 256;
-
-        /**
-         * {@inheritDoc}
-         */
-        public String name(int value) {
-            if (value < LOOKUP_TABLE_SIZE) {
-                return lookupTable()[value];
-            }
-            return super.name(value);
-        }
-
-        /**
-         * <p>
-         * Returns the lookup table for this entity map. The lookup table is created if it has not been previously.
-         * </p>
-         *
-         * @return the lookup table
-         */
-        private String[] lookupTable() {
-            if (lookupTable == null) {
-                createLookupTable();
-            }
-            return lookupTable;
-        }
-
-        /**
-         * <p>
-         * Creates an entity lookup table of LOOKUP_TABLE_SIZE elements, initialized with entity names.
-         * </p>
-         */
-        private void createLookupTable() {
-            lookupTable = new String[LOOKUP_TABLE_SIZE];
-            for (int i = 0; i < LOOKUP_TABLE_SIZE; ++i) {
-                lookupTable[i] = super.name(i);
-            }
-        }
-    }
-
-    static class ArrayEntityMap implements EntityMap {
-        protected int growBy = 100;
-
-        protected int size = 0;
-
-        protected String[] names;
-
-        protected int[] values;
-
-        /**
-         * Constructs a new instance of <code>ArrayEntityMap</code>.
-         */
-        public ArrayEntityMap() {
-            names = new String[growBy];
-            values = new int[growBy];
-        }
-
-        /**
-         * Constructs a new instance of <code>ArrayEntityMap</code> specifying the size by which the array should
-         * grow.
-         *
-         * @param growBy array will be initialized to and will grow by this amount
-         */
-        public ArrayEntityMap(int growBy) {
-            this.growBy = growBy;
-            names = new String[growBy];
-            values = new int[growBy];
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void add(String name, int value) {
-            ensureCapacity(size + 1);
-            names[size] = name;
-            values[size] = value;
-            size++;
-        }
-
-        /**
-         * Verifies the capacity of the entity array, adjusting the size if necessary.
-         *
-         * @param capacity size the array should be
-         */
-        protected void ensureCapacity(int capacity) {
-            if (capacity > names.length) {
-                int newSize = Math.max(capacity, size + growBy);
-                String[] newNames = new String[newSize];
-                System.arraycopy(names, 0, newNames, 0, size);
-                names = newNames;
-                int[] newValues = new int[newSize];
-                System.arraycopy(values, 0, newValues, 0, size);
-                values = newValues;
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String name(int value) {
-            for (int i = 0; i < size; ++i) {
-                if (values[i] == value) {
-                    return names[i];
-                }
-            }
-            return null;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public int value(String name) {
-            for (int i = 0; i < size; ++i) {
-                if (names[i].equals(name)) {
-                    return values[i];
-                }
-            }
-            return -1;
-        }
-    }
-
-    static class BinaryEntityMap extends ArrayEntityMap {
-
-        /**
-         * Constructs a new instance of <code>BinaryEntityMap</code>.
-         */
-        public BinaryEntityMap() {
-            super();
-        }
-
-        /**
-         * Constructs a new instance of <code>ArrayEntityMap</code> specifying the size by which the underlying array
-         * should grow.
-         *
-         * @param growBy array will be initialized to and will grow by this amount
-         */
-        public BinaryEntityMap(int growBy) {
-            super(growBy);
-        }
-
-        /**
-         * Performs a binary search of the entity array for the specified key. This method is based on code in
-         * {@link java.util.Arrays}.
-         *
-         * @param key the key to be found
-         * @return the index of the entity array matching the specified key
-         */
-        private int binarySearch(int key) {
-            int low = 0;
-            int high = size - 1;
-
-            while (low <= high) {
-                int mid = (low + high) >>> 1;
-                int midVal = values[mid];
-
-                if (midVal < key) {
-                    low = mid + 1;
-                } else if (midVal > key) {
-                    high = mid - 1;
-                } else {
-                    return mid; // key found
-                }
-            }
-            return -(low + 1); // key not found.
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public void add(String name, int value) {
-            ensureCapacity(size + 1);
-            int insertAt = binarySearch(value);
-            if (insertAt > 0) {
-                return; // note: this means you can't insert the same value twice
-            }
-            insertAt = -(insertAt + 1); // binarySearch returns it negative and off-by-one
-            System.arraycopy(values, insertAt, values, insertAt + 1, size - insertAt);
-            values[insertAt] = value;
-            System.arraycopy(names, insertAt, names, insertAt + 1, size - insertAt);
-            names[insertAt] = name;
-            size++;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public String name(int value) {
-            int index = binarySearch(value);
-            if (index < 0) {
-                return null;
-            }
-            return names[index];
-        }
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/IntHashMap.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/IntHashMap.java
deleted file mode 100644
index 6dc36f0..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/IntHashMap.java
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * 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.registry.common.util;
-
-/**
- * <p>A hash map that uses primitive ints for the key rather than objects.</p>
- * <p>
- * <p>Note that this class is for internal optimization purposes only, and may
- * not be supported in future releases of Apache Commons Lang.  Utilities of
- * this sort may be included in future releases of Apache Commons Collections.</p>
- *
- * @version $Revision: 181192 $
- * @see java.util.HashMap
- * @since 2.0
- */
-class IntHashMap {
-
-    /**
-     * The hash table data.
-     */
-    private transient Entry table[];
-
-    /**
-     * The total number of entries in the hash table.
-     */
-    private transient int count;
-
-    /**
-     * The table is rehashed when its size exceeds this threshold.  (The
-     * value of this field is (int)(capacity * loadFactor).)
-     *
-     * @serial
-     */
-    private int threshold;
-
-    /**
-     * The load factor for the hashtable.
-     *
-     * @serial
-     */
-    private float loadFactor;
-
-    /**
-     * <p>Constructs a new, empty hashtable with a default capacity and load
-     * factor, which is <code>20</code> and <code>0.75</code> respectively.</p>
-     */
-    public IntHashMap() {
-        this(20, 0.75f);
-    }
-
-    /**
-     * <p>Constructs a new, empty hashtable with the specified initial capacity
-     * and default load factor, which is <code>0.75</code>.</p>
-     *
-     * @param initialCapacity the initial capacity of the hashtable.
-     * @throws IllegalArgumentException if the initial capacity is less
-     *                                  than zero.
-     */
-    public IntHashMap(int initialCapacity) {
-        this(initialCapacity, 0.75f);
-    }
-
-    /**
-     * <p>Constructs a new, empty hashtable with the specified initial
-     * capacity and the specified load factor.</p>
-     *
-     * @param initialCapacity the initial capacity of the hashtable.
-     * @param loadFactor      the load factor of the hashtable.
-     * @throws IllegalArgumentException if the initial capacity is less
-     *                                  than zero, or if the load factor is nonpositive.
-     */
-    public IntHashMap(int initialCapacity, float loadFactor) {
-        super();
-        if (initialCapacity < 0) {
-            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
-        }
-        if (loadFactor <= 0) {
-            throw new IllegalArgumentException("Illegal Load: " + loadFactor);
-        }
-        if (initialCapacity == 0) {
-            initialCapacity = 1;
-        }
-
-        this.loadFactor = loadFactor;
-        table = new Entry[initialCapacity];
-        threshold = (int) (initialCapacity * loadFactor);
-    }
-
-    /**
-     * <p>Returns the number of keys in this hashtable.</p>
-     *
-     * @return the number of keys in this hashtable.
-     */
-    public int size() {
-        return count;
-    }
-
-    /**
-     * <p>Tests if this hashtable maps no keys to values.</p>
-     *
-     * @return <code>true</code> if this hashtable maps no keys to values;
-     * <code>false</code> otherwise.
-     */
-    public boolean isEmpty() {
-        return count == 0;
-    }
-
-    /**
-     * <p>Tests if some key maps into the specified value in this hashtable.
-     * This operation is more expensive than the <code>containsKey</code>
-     * method.</p>
-     * <p>
-     * <p>Note that this method is identical in functionality to containsValue,
-     * (which is part of the Map interface in the collections framework).</p>
-     *
-     * @param value a value to search for.
-     * @return <code>true</code> if and only if some key maps to the
-     * <code>value</code> argument in this hashtable as
-     * determined by the <tt>equals</tt> method;
-     * <code>false</code> otherwise.
-     * @throws NullPointerException if the value is <code>null</code>.
-     * @see #containsKey(int)
-     * @see #containsValue(Object)
-     * @see java.util.Map
-     */
-    public boolean contains(Object value) {
-        if (value == null) {
-            throw new NullPointerException();
-        }
-
-        Entry tab[] = table;
-        for (int i = tab.length; i-- > 0; ) {
-            for (Entry e = tab[i]; e != null; e = e.next) {
-                if (e.value.equals(value)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * <p>Returns <code>true</code> if this HashMap maps one or more keys
-     * to this value.</p>
-     * <p>
-     * <p>Note that this method is identical in functionality to contains
-     * (which predates the Map interface).</p>
-     *
-     * @param value value whose presence in this HashMap is to be tested.
-     * @return boolean <code>true</code> if the value is contained
-     * @see java.util.Map
-     * @since JDK1.2
-     */
-    public boolean containsValue(Object value) {
-        return contains(value);
-    }
-
-    /**
-     * <p>Tests if the specified object is a key in this hashtable.</p>
-     *
-     * @param key possible key.
-     * @return <code>true</code> if and only if the specified object is a
-     * key in this hashtable, as determined by the <tt>equals</tt>
-     * method; <code>false</code> otherwise.
-     * @see #contains(Object)
-     */
-    public boolean containsKey(int key) {
-        Entry tab[] = table;
-        int hash = key;
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        for (Entry e = tab[index]; e != null; e = e.next) {
-            if (e.hash == hash) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * <p>Returns the value to which the specified key is mapped in this map.</p>
-     *
-     * @param key a key in the hashtable.
-     * @return the value to which the key is mapped in this hashtable;
-     * <code>null</code> if the key is not mapped to any value in
-     * this hashtable.
-     * @see #put(int, Object)
-     */
-    public Object get(int key) {
-        Entry tab[] = table;
-        int hash = key;
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        for (Entry e = tab[index]; e != null; e = e.next) {
-            if (e.hash == hash) {
-                return e.value;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * <p>Increases the capacity of and internally reorganizes this
-     * hashtable, in order to accommodate and access its entries more
-     * efficiently.</p>
-     * <p>
-     * <p>This method is called automatically when the number of keys
-     * in the hashtable exceeds this hashtable's capacity and load
-     * factor.</p>
-     */
-    protected void rehash() {
-        int oldCapacity = table.length;
-        Entry oldMap[] = table;
-
-        int newCapacity = oldCapacity * 2 + 1;
-        Entry newMap[] = new Entry[newCapacity];
-
-        threshold = (int) (newCapacity * loadFactor);
-        table = newMap;
-
-        for (int i = oldCapacity; i-- > 0; ) {
-            for (Entry old = oldMap[i]; old != null; ) {
-                Entry e = old;
-                old = old.next;
-
-                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
-                e.next = newMap[index];
-                newMap[index] = e;
-            }
-        }
-    }
-
-    /**
-     * <p>Maps the specified <code>key</code> to the specified
-     * <code>value</code> in this hashtable. The key cannot be
-     * <code>null</code>. </p>
-     * <p>
-     * <p>The value can be retrieved by calling the <code>get</code> method
-     * with a key that is equal to the original key.</p>
-     *
-     * @param key   the hashtable key.
-     * @param value the value.
-     * @return the previous value of the specified key in this hashtable,
-     * or <code>null</code> if it did not have one.
-     * @throws NullPointerException if the key is <code>null</code>.
-     * @see #get(int)
-     */
-    public Object put(int key, Object value) {
-        // Makes sure the key is not already in the hashtable.
-        Entry tab[] = table;
-        int hash = key;
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        for (Entry e = tab[index]; e != null; e = e.next) {
-            if (e.hash == hash) {
-                Object old = e.value;
-                e.value = value;
-                return old;
-            }
-        }
-
-        if (count >= threshold) {
-            // Rehash the table if the threshold is exceeded
-            rehash();
-
-            tab = table;
-            index = (hash & 0x7FFFFFFF) % tab.length;
-        }
-
-        // Creates the new entry.
-        Entry e = new Entry(hash, key, value, tab[index]);
-        tab[index] = e;
-        count++;
-        return null;
-    }
-
-    /**
-     * <p>Removes the key (and its corresponding value) from this
-     * hashtable.</p>
-     * <p>
-     * <p>This method does nothing if the key is not present in the
-     * hashtable.</p>
-     *
-     * @param key the key that needs to be removed.
-     * @return the value to which the key had been mapped in this hashtable,
-     * or <code>null</code> if the key did not have a mapping.
-     */
-    public Object remove(int key) {
-        Entry tab[] = table;
-        int hash = key;
-        int index = (hash & 0x7FFFFFFF) % tab.length;
-        for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
-            if (e.hash == hash) {
-                if (prev != null) {
-                    prev.next = e.next;
-                } else {
-                    tab[index] = e.next;
-                }
-                count--;
-                Object oldValue = e.value;
-                e.value = null;
-                return oldValue;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * <p>Clears this hashtable so that it contains no keys.</p>
-     */
-    public synchronized void clear() {
-        Entry tab[] = table;
-        for (int index = tab.length; --index >= 0; ) {
-            tab[index] = null;
-        }
-        count = 0;
-    }
-
-    /**
-     * <p>Innerclass that acts as a datastructure to create a new entry in the
-     * table.</p>
-     */
-    private static class Entry {
-        int hash;
-        int key;
-        Object value;
-        Entry next;
-
-        /**
-         * <p>Create a new entry with the given values.</p>
-         *
-         * @param hash  The code used to hash the object with
-         * @param key   The key used to enter this in the table
-         * @param value The value for this key
-         * @param next  A reference to the next entry in the table
-         */
-        protected Entry(int hash, int key, Object value, Entry next) {
-            this.hash = hash;
-            this.key = key;
-            this.value = value;
-            this.next = next;
-        }
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/LocaleUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/LocaleUtils.java
deleted file mode 100644
index 2917fe1..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/LocaleUtils.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import java.util.Locale;
-
-public class LocaleUtils {
-
-    private LocaleUtils() {
-    }
-
-    public static Locale getLocale(String language) {
-        if ("en".equalsIgnoreCase(language)) {
-            return Locale.ENGLISH;
-        } else if ("zh".equalsIgnoreCase(language)) {
-            return Locale.SIMPLIFIED_CHINESE;
-        } else if ("zh_TW".equalsIgnoreCase(language)) {
-            return Locale.TRADITIONAL_CHINESE;
-        }
-        return Locale.getDefault();
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/MessageSource.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/MessageSource.java
deleted file mode 100644
index 8b22ca3..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/MessageSource.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-
-import java.text.MessageFormat;
-import java.util.ResourceBundle;
-
-/**
- * MessageSource
- *
- */
-public class MessageSource {
-
-    private static final Logger logger = LoggerFactory.getLogger(MessageSource.class);
-
-    private final ResourceBundle resourceBundle;
-
-    private final String errorPrefix;
-
-    public MessageSource(ResourceBundle resourceBundle) {
-        this(resourceBundle, null);
-    }
-
-    public MessageSource(ResourceBundle resourceBundle, String errorPrefix) {
-        this.resourceBundle = resourceBundle;
-        this.errorPrefix = errorPrefix == null ? "" : errorPrefix + " ";
-    }
-
-    public String getString(String key) {
-        try {
-            return resourceBundle.getString(key);
-        } catch (Throwable t) {
-            logger.warn(errorPrefix + t.getMessage(), t);
-            return key;
-        }
-    }
-
-    public String getString(String key, Object... args) {
-        try {
-            return new MessageFormat(resourceBundle.getString(key)).format(args);
-        } catch (Throwable t) {
-            logger.warn(errorPrefix + t.getMessage(), t);
-            return key;
-        }
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/OverrideUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/OverrideUtils.java
deleted file mode 100644
index 2f64195..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/OverrideUtils.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.registry.common.domain.LoadBalance;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.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/registry/common/util/StringEscapeUtils.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/StringEscapeUtils.java
deleted file mode 100644
index f11f429..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/StringEscapeUtils.java
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-
-/**
- * <p>Escapes and unescapes <code>String</code>s for
- * Java, Java Script, HTML, XML, and SQL.</p>
- *
- * @version $Id: StringEscapeUtils.java 181192 2012-06-21 05:05:47Z tony.chenl $
- * @since 2.0
- */
-public class StringEscapeUtils {
-
-    private static final char CSV_DELIMITER = ',';
-    private static final char CSV_QUOTE = '"';
-    private static final String CSV_QUOTE_STR = String.valueOf(CSV_QUOTE);
-    private static final char[] CSV_SEARCH_CHARS = new char[]{CSV_DELIMITER, CSV_QUOTE, '\r', '\n'};
-
-    /**
-     * <p><code>StringEscapeUtils</code> instances should NOT be constructed in
-     * standard programming.</p>
-     * <p>
-     * <p>Instead, the class should be used as:
-     * <pre>StringEscapeUtils.escapeJava("foo");</pre></p>
-     *
-     * <p>This constructor is public to permit tools that require a JavaBean
-     * instance to operate.</p>
-     */
-    public StringEscapeUtils() {
-        super();
-    }
-
-    // Java and JavaScript
-    //--------------------------------------------------------------------------
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using Java String rules.</p>
-     * <p>
-     * <p>Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>
-     * <p>
-     * <p>So a tab becomes the characters <code>'\\'</code> and
-     * <code>'t'</code>.</p>
-     * <p>
-     * <p>The only difference between Java strings and JavaScript strings
-     * is that in JavaScript, a single quote must be escaped.</p>
-     * <p>
-     * <p>Example:
-     * <pre>
-     * input string: He didn't say, "Stop!"
-     * output string: He didn't say, \"Stop!\"
-     * </pre>
-     * </p>
-     *
-     * @param str String to escape values in, may be null
-     * @return String with escaped values, <code>null</code> if null string input
-     */
-    public static String escapeJava(String str) {
-        return escapeJavaStyleString(str, false);
-    }
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using Java String rules to
-     * a <code>Writer</code>.</p>
-     * <p>
-     * <p>A <code>null</code> string input has no effect.</p>
-     *
-     * @param out Writer to write escaped string into
-     * @param str String to escape values in, may be null
-     * @throws IllegalArgumentException if the Writer is <code>null</code>
-     * @throws IOException              if error occurs on underlying Writer
-     * @see #escapeJava(java.lang.String)
-     */
-    public static void escapeJava(Writer out, String str) throws IOException {
-        escapeJavaStyleString(out, str, false);
-    }
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using JavaScript String rules.</p>
-     * <p>Escapes any values it finds into their JavaScript String form.
-     * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) </p>
-     * <p>
-     * <p>So a tab becomes the characters <code>'\\'</code> and
-     * <code>'t'</code>.</p>
-     * <p>
-     * <p>The only difference between Java strings and JavaScript strings
-     * is that in JavaScript, a single quote must be escaped.</p>
-     * <p>
-     * <p>Example:
-     * <pre>
-     * input string: He didn't say, "Stop!"
-     * output string: He didn\'t say, \"Stop!\"
-     * </pre>
-     * </p>
-     *
-     * @param str String to escape values in, may be null
-     * @return String with escaped values, <code>null</code> if null string input
-     */
-    public static String escapeJavaScript(String str) {
-        return escapeJavaStyleString(str, true);
-    }
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using JavaScript String rules
-     * to a <code>Writer</code>.</p>
-     * <p>
-     * <p>A <code>null</code> string input has no effect.</p>
-     *
-     * @param out Writer to write escaped string into
-     * @param str String to escape values in, may be null
-     * @throws IllegalArgumentException if the Writer is <code>null</code>
-     * @throws IOException              if error occurs on underlying Writer
-     * @see #escapeJavaScript(java.lang.String)
-     **/
-    public static void escapeJavaScript(Writer out, String str) throws IOException {
-        escapeJavaStyleString(out, str, true);
-    }
-
-    /**
-     * <p>Worker method for the {@link #escapeJavaScript(String)} method.</p>
-     *
-     * @param str                String to escape values in, may be null
-     * @param escapeSingleQuotes escapes single quotes if <code>true</code>
-     * @return the escaped string
-     */
-    private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            StringWriter writer = new StringWriter(str.length() * 2);
-            escapeJavaStyleString(writer, str, escapeSingleQuotes);
-            return writer.toString();
-        } catch (IOException ioe) {
-            // this should never ever happen while writing to a StringWriter
-            ioe.printStackTrace();
-            return null;
-        }
-    }
-
-    /**
-     * <p>Worker method for the {@link #escapeJavaScript(String)} method.</p>
-     *
-     * @param out               write to receieve the escaped string
-     * @param str               String to escape values in, may be null
-     * @param escapeSingleQuote escapes single quotes if <code>true</code>
-     * @throws IOException if an IOException occurs
-     */
-    private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote) throws IOException {
-        if (out == null) {
-            throw new IllegalArgumentException("The Writer must not be null");
-        }
-        if (str == null) {
-            return;
-        }
-        int sz;
-        sz = str.length();
-        for (int i = 0; i < sz; i++) {
-            char ch = str.charAt(i);
-
-            // handle unicode
-            if (ch > 0xfff) {
-                out.write("\\u" + hex(ch));
-            } else if (ch > 0xff) {
-                out.write("\\u0" + hex(ch));
-            } else if (ch > 0x7f) {
-                out.write("\\u00" + hex(ch));
-            } else if (ch < 32) {
-                switch (ch) {
-                    case '\b':
-                        out.write('\\');
-                        out.write('b');
-                        break;
-                    case '\n':
-                        out.write('\\');
-                        out.write('n');
-                        break;
-                    case '\t':
-                        out.write('\\');
-                        out.write('t');
-                        break;
-                    case '\f':
-                        out.write('\\');
-                        out.write('f');
-                        break;
-                    case '\r':
-                        out.write('\\');
-                        out.write('r');
-                        break;
-                    default:
-                        if (ch > 0xf) {
-                            out.write("\\u00" + hex(ch));
-                        } else {
-                            out.write("\\u000" + hex(ch));
-                        }
-                        break;
-                }
-            } else {
-                switch (ch) {
-                    case '\'':
-                        if (escapeSingleQuote) {
-                            out.write('\\');
-                        }
-                        out.write('\'');
-                        break;
-                    case '"':
-                        out.write('\\');
-                        out.write('"');
-                        break;
-                    case '\\':
-                        out.write('\\');
-                        out.write('\\');
-                        break;
-                    case '/':
-                        out.write('\\');
-                        out.write('/');
-                        break;
-                    default:
-                        out.write(ch);
-                        break;
-                }
-            }
-        }
-    }
-
-    /**
-     * <p>Returns an upper case hexadecimal <code>String</code> for the given
-     * character.</p>
-     *
-     * @param ch The character to convert.
-     * @return An upper case hexadecimal <code>String</code>
-     */
-    private static String hex(char ch) {
-        return Integer.toHexString(ch).toUpperCase();
-    }
-
-    /**
-     * <p>Unescapes any Java literals found in the <code>String</code>.
-     * For example, it will turn a sequence of <code>'\'</code> and
-     * <code>'n'</code> into a newline character, unless the <code>'\'</code>
-     * is preceded by another <code>'\'</code>.</p>
-     *
-     * @param str the <code>String</code> to unescape, may be null
-     * @return a new unescaped <code>String</code>, <code>null</code> if null string input
-     */
-    public static String unescapeJava(String str) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            StringWriter writer = new StringWriter(str.length());
-            unescapeJava(writer, str);
-            return writer.toString();
-        } catch (IOException ioe) {
-            // this should never ever happen while writing to a StringWriter
-            ioe.printStackTrace();
-            return null;
-        }
-    }
-
-    /**
-     * <p>Unescapes any Java literals found in the <code>String</code> to a
-     * <code>Writer</code>.</p>
-     * <p>
-     * <p>For example, it will turn a sequence of <code>'\'</code> and
-     * <code>'n'</code> into a newline character, unless the <code>'\'</code>
-     * is preceded by another <code>'\'</code>.</p>
-     * <p>
-     * <p>A <code>null</code> string input has no effect.</p>
-     *
-     * @param out the <code>Writer</code> used to output unescaped characters
-     * @param str the <code>String</code> to unescape, may be null
-     * @throws IllegalArgumentException if the Writer is <code>null</code>
-     * @throws IOException              if error occurs on underlying Writer
-     */
-    public static void unescapeJava(Writer out, String str) throws IOException {
-        if (out == null) {
-            throw new IllegalArgumentException("The Writer must not be null");
-        }
-        if (str == null) {
-            return;
-        }
-        int sz = str.length();
-        StringBuffer unicode = new StringBuffer(4);
-        boolean hadSlash = false;
-        boolean inUnicode = false;
-        for (int i = 0; i < sz; i++) {
-            char ch = str.charAt(i);
-            if (inUnicode) {
-                // if in unicode, then we're reading unicode
-                // values in somehow
-                unicode.append(ch);
-                if (unicode.length() == 4) {
-                    // unicode now contains the four hex digits
-                    // which represents our unicode character
-                    try {
-                        int value = Integer.parseInt(unicode.toString(), 16);
-                        out.write((char) value);
-                        unicode.setLength(0);
-                        inUnicode = false;
-                        hadSlash = false;
-                    } catch (NumberFormatException nfe) {
-                        throw new RuntimeException("Unable to parse unicode value: " + unicode, nfe);
-                    }
-                }
-                continue;
-            }
-            if (hadSlash) {
-                // handle an escaped value
-                hadSlash = false;
-                switch (ch) {
-                    case '\\':
-                        out.write('\\');
-                        break;
-                    case '\'':
-                        out.write('\'');
-                        break;
-                    case '\"':
-                        out.write('"');
-                        break;
-                    case 'r':
-                        out.write('\r');
-                        break;
-                    case 'f':
-                        out.write('\f');
-                        break;
-                    case 't':
-                        out.write('\t');
-                        break;
-                    case 'n':
-                        out.write('\n');
-                        break;
-                    case 'b':
-                        out.write('\b');
-                        break;
-                    case 'u': {
-                        // uh-oh, we're in unicode country....
-                        inUnicode = true;
-                        break;
-                    }
-                    default:
-                        out.write(ch);
-                        break;
-                }
-                continue;
-            } else if (ch == '\\') {
-                hadSlash = true;
-                continue;
-            }
-            out.write(ch);
-        }
-        if (hadSlash) {
-            // then we're in the weird case of a \ at the end of the
-            // string, let's output it anyway.
-            out.write('\\');
-        }
-    }
-
-    /**
-     * <p>Unescapes any JavaScript literals found in the <code>String</code>.</p>
-     * <p>
-     * <p>For example, it will turn a sequence of <code>'\'</code> and <code>'n'</code>
-     * into a newline character, unless the <code>'\'</code> is preceded by another
-     * <code>'\'</code>.</p>
-     *
-     * @param str the <code>String</code> to unescape, may be null
-     * @return A new unescaped <code>String</code>, <code>null</code> if null string input
-     * @see #unescapeJava(String)
-     */
-    public static String unescapeJavaScript(String str) {
-        return unescapeJava(str);
-    }
-
-    /**
-     * <p>Unescapes any JavaScript literals found in the <code>String</code> to a
-     * <code>Writer</code>.</p>
-     * <p>
-     * <p>For example, it will turn a sequence of <code>'\'</code> and <code>'n'</code>
-     * into a newline character, unless the <code>'\'</code> is preceded by another
-     * <code>'\'</code>.</p>
-     * <p>
-     * <p>A <code>null</code> string input has no effect.</p>
-     *
-     * @param out the <code>Writer</code> used to output unescaped characters
-     * @param str the <code>String</code> to unescape, may be null
-     * @throws IllegalArgumentException if the Writer is <code>null</code>
-     * @throws IOException              if error occurs on underlying Writer
-     * @see #unescapeJava(Writer, String)
-     */
-    public static void unescapeJavaScript(Writer out, String str) throws IOException {
-        unescapeJava(out, str);
-    }
-
-    // HTML and XML
-    //--------------------------------------------------------------------------
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using HTML entities.</p>
-     * <p>
-     * <p>
-     * For example:
-     * </p>
-     * <p><code>"bread" & "butter"</code></p>
-     * becomes:
-     * <p>
-     * <code>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</code>.
-     * </p>
-     * <p>
-     * <p>Supports all known HTML 4.0 entities, including funky accents.
-     * Note that the commonly used apostrophe escape character (&amp;apos;)
-     * is not a legal entity and so is not supported). </p>
-     *
-     * @param str the <code>String</code> to escape, may be null
-     * @return a new escaped <code>String</code>, <code>null</code> if null string input
-     * @see #unescapeHtml(String)
-     * @see <a href="http://hotwired.lycos.com/webmonkey/reference/special_characters/">ISO Entities</a>
-     * @see <a href="http://www.w3.org/TR/REC-html32#latin1">HTML 3.2 Character Entities for ISO Latin-1</a>
-     * @see <a href="http://www.w3.org/TR/REC-html40/sgml/entities.html">HTML 4.0 Character entity references</a>
-     * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3">HTML 4.01 Character References</a>
-     * @see <a href="http://www.w3.org/TR/html401/charset.html#code-position">HTML 4.01 Code positions</a>
-     */
-    public static String escapeHtml(String str) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            StringWriter writer = new StringWriter((int) (str.length() * 1.5));
-            escapeHtml(writer, str);
-            return writer.toString();
-        } catch (IOException e) {
-            //assert false;
-            //should be impossible
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using HTML entities and writes
-     * them to a <code>Writer</code>.</p>
-     * <p>
-     * <p>
-     * For example:
-     * </p>
-     * <code>"bread" & "butter"</code>
-     * <p>becomes:</p>
-     * <code>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</code>.
-     * <p>
-     * <p>Supports all known HTML 4.0 entities, including funky accents.
-     * Note that the commonly used apostrophe escape character (&amp;apos;)
-     * is not a legal entity and so is not supported). </p>
-     *
-     * @param writer the writer receiving the escaped string, not null
-     * @param string the <code>String</code> to escape, may be null
-     * @throws IllegalArgumentException if the writer is null
-     * @throws IOException              when <code>Writer</code> passed throws the exception from
-     *                                  calls to the {@link Writer#write(int)} methods.
-     * @see #escapeHtml(String)
-     * @see #unescapeHtml(String)
-     * @see <a href="http://hotwired.lycos.com/webmonkey/reference/special_characters/">ISO Entities</a>
-     * @see <a href="http://www.w3.org/TR/REC-html32#latin1">HTML 3.2 Character Entities for ISO Latin-1</a>
-     * @see <a href="http://www.w3.org/TR/REC-html40/sgml/entities.html">HTML 4.0 Character entity references</a>
-     * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3">HTML 4.01 Character References</a>
-     * @see <a href="http://www.w3.org/TR/html401/charset.html#code-position">HTML 4.01 Code positions</a>
-     */
-    public static void escapeHtml(Writer writer, String string) throws IOException {
-        if (writer == null) {
-            throw new IllegalArgumentException("The Writer must not be null.");
-        }
-        if (string == null) {
-            return;
-        }
-        Entities.HTML40.escape(writer, string);
-    }
-
-    //-----------------------------------------------------------------------
-
-    /**
-     * <p>Unescapes a string containing entity escapes to a string
-     * containing the actual Unicode characters corresponding to the
-     * escapes. Supports HTML 4.0 entities.</p>
-     * <p>
-     * <p>For example, the string "&amp;lt;Fran&amp;ccedil;ais&amp;gt;"
-     * will become "&lt;Fran&ccedil;ais&gt;"</p>
-     * <p>
-     * <p>If an entity is unrecognized, it is left alone, and inserted
-     * verbatim into the result string. e.g. "&amp;gt;&amp;zzzz;x" will
-     * become "&gt;&amp;zzzz;x".</p>
-     *
-     * @param str the <code>String</code> to unescape, may be null
-     * @return a new unescaped <code>String</code>, <code>null</code> if null string input
-     * @see #escapeHtml(Writer, String)
-     */
-    public static String unescapeHtml(String str) {
-        if (str == null) {
-            return null;
-        }
-        try {
-            StringWriter writer = new StringWriter((int) (str.length() * 1.5));
-            unescapeHtml(writer, str);
-            return writer.toString();
-        } catch (IOException e) {
-            //assert false;
-            //should be impossible
-            e.printStackTrace();
-            return null;
-        }
-    }
-
-    /**
-     * <p>Unescapes a string containing entity escapes to a string
-     * containing the actual Unicode characters corresponding to the
-     * escapes. Supports HTML 4.0 entities.</p>
-     * <p>
-     * <p>For example, the string "&amp;lt;Fran&amp;ccedil;ais&amp;gt;"
-     * will become "&lt;Fran&ccedil;ais&gt;"</p>
-     * <p>
-     * <p>If an entity is unrecognized, it is left alone, and inserted
-     * verbatim into the result string. e.g. "&amp;gt;&amp;zzzz;x" will
-     * become "&gt;&amp;zzzz;x".</p>
-     *
-     * @param writer the writer receiving the unescaped string, not null
-     * @param string the <code>String</code> to unescape, may be null
-     * @throws IllegalArgumentException if the writer is null
-     * @throws IOException              if an IOException occurs
-     * @see #escapeHtml(String)
-     */
-    public static void unescapeHtml(Writer writer, String string) throws IOException {
-        if (writer == null) {
-            throw new IllegalArgumentException("The Writer must not be null.");
-        }
-        if (string == null) {
-            return;
-        }
-        Entities.HTML40.unescape(writer, string);
-    }
-
-    //-----------------------------------------------------------------------
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using XML entities.</p>
-     * <p>
-     * <p>For example: <tt>"bread" & "butter"</tt> =>
-     * <tt>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</tt>.
-     * </p>
-     * <p>
-     * <p>Supports only the five basic XML entities (gt, lt, quot, amp, apos).
-     * Does not support DTDs or external entities.</p>
-     * <p>
-     * <p>Note that unicode characters greater than 0x7f are currently escaped to
-     * their numerical \\u equivalent. This may change in future releases. </p>
-     *
-     * @param writer the writer receiving the unescaped string, not null
-     * @param str    the <code>String</code> to escape, may be null
-     * @throws IllegalArgumentException if the writer is null
-     * @throws IOException              if there is a problem writing
-     * @see #unescapeXml(java.lang.String)
-     */
-    public static void escapeXml(Writer writer, String str) throws IOException {
-        if (writer == null) {
-            throw new IllegalArgumentException("The Writer must not be null.");
-        }
-        if (str == null) {
-            return;
-        }
-        Entities.XML.escape(writer, str);
-    }
-
-    /**
-     * <p>Escapes the characters in a <code>String</code> using XML entities.</p>
-     * <p>
-     * <p>For example: <tt>"bread" & "butter"</tt> =>
-     * <tt>&amp;quot;bread&amp;quot; &amp;amp; &amp;quot;butter&amp;quot;</tt>.
-     * </p>
-     * <p>
-     * <p>Supports only the five basic XML entities (gt, lt, quot, amp, apos).
-     * Does not support DTDs or external entities.</p>
-     * <p>
-     * <p>Note that unicode characters greater than 0x7f are currently escaped to
-     * their numerical \\u equivalent. This may change in future releases. </p>
-     *
-     * @param str the <code>String</code> to escape, may be null
-     * @return a new escaped <code>String</code>, <code>null</code> if null string input
-     * @see #unescapeXml(java.lang.String)
-     */
-    public static String escapeXml(String str) {
-        if (str == null) {
-            return null;
-        }
-        return Entities.XML.escape(str);
-    }
-
-    //-----------------------------------------------------------------------
-
-    /**
-     * <p>Unescapes a string containing XML entity escapes to a string
-     * containing the actual Unicode characters corresponding to the
-     * escapes.</p>
-     * <p>
-     * <p>Supports only the five basic XML entities (gt, lt, quot, amp, apos).
-     * Does not support DTDs or external entities.</p>
-     * <p>
-     * <p>Note that numerical \\u unicode codes are unescaped to their respective
-     * unicode characters. This may change in future releases. </p>
-     *
-     * @param writer the writer receiving the unescaped string, not null
-     * @param str    the <code>String</code> to unescape, may be null
-     * @throws IllegalArgumentException if the writer is null
-     * @throws IOException              if there is a problem writing
-     * @see #escapeXml(String)
-     */
-    public static void unescapeXml(Writer writer, String str) throws IOException {
-        if (writer == null) {
-            throw new IllegalArgumentException("The Writer must not be null.");
-        }
-        if (str == null) {
-            return;
-        }
-        Entities.XML.unescape(writer, str);
-    }
-
-    /**
-     * <p>Unescapes a string containing XML entity escapes to a string
-     * containing the actual Unicode characters corresponding to the
-     * escapes.</p>
-     * <p>
-     * <p>Supports only the five basic XML entities (gt, lt, quot, amp, apos).
-     * Does not support DTDs or external entities.</p>
-     * <p>
-     * <p>Note that numerical \\u unicode codes are unescaped to their respective
-     * unicode characters. This may change in future releases. </p>
-     *
-     * @param str the <code>String</code> to unescape, may be null
-     * @return a new unescaped <code>String</code>, <code>null</code> if null string input
-     * @see #escapeXml(String)
-     */
-    public static String unescapeXml(String str) {
-        if (str == null) {
-            return null;
-        }
-        return Entities.XML.unescape(str);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Tool.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Tool.java
deleted file mode 100644
index cfb8a50..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/common/util/Tool.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.registry.common.util;
-
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.utils.NetUtils;
-import com.alibaba.dubbo.common.utils.StringUtils;
-
-import java.lang.reflect.Array;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.*;
-import java.util.regex.Pattern;
-
-/**
- * Tool
- *
- */
-public class Tool {
-
-    private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");
-    private static final Comparator<String> SIMPLE_NAME_COMPARATOR = new Comparator<String>() {
-        public int compare(String s1, String s2) {
-            if (s1 == null && s2 == null) {
-                return 0;
-            }
-            if (s1 == null) {
-                return -1;
-            }
-            if (s2 == null) {
-                return 1;
-            }
-            s1 = getSimpleName(s1);
-            s2 = getSimpleName(s2);
-            return s1.compareToIgnoreCase(s2);
-        }
-    };
-
-    public static boolean startWith(String value, String prefix) {
-        return value.startsWith(prefix);
-    }
-
-    public static boolean isContains(String[] values, String value) {
-        return StringUtils.isContains(values, value);
-    }
-
-    public static boolean isValidAddress(String address) {
-        return IP_PATTERN.matcher(address).matches();
-    }
-
-    public static String getHostName(String address) {
-        if (address != null && address.length() > 0) {
-            String hostname = NetUtils.getHostName(address);
-            if (!address.equals(hostname)) {
-                return hostname + "/";
-            }
-        }
-        return "";
-    }
-
-    public static String getIP(String address) {
-        if (address != null && address.length() > 0) {
-            int i = address.indexOf("://");
-            if (i >= 0) {
-                address = address.substring(i + 3);
-            }
-            i = address.indexOf('/');
-            if (i >= 0) {
-                address = address.substring(0, i);
-            }
-            i = address.indexOf('@');
-            if (i >= 0) {
-                address = address.substring(i + 1);
-            }
-            i = address.indexOf(':');
-            if (i >= 0) {
-                address = address.substring(0, i);
-            }
-            if (address.matches("[a-zA-Z]+")) {
-                try {
-                    address = InetAddress.getByName(address).getHostAddress();
-                } catch (UnknownHostException e) {
-                }
-            }
-        }
-        return address;
-    }
-
-    public static String encodeUrl(String url) {
-        return URL.encode(url);
-    }
-
-    public static String decodeUrl(String url) {
-        return URL.decode(url);
-    }
-
-    public static String encodeHtml(String html) {
-        return StringEscapeUtils.escapeHtml(html);
-    }
-
-    public static String decodeHtml(String html) {
-        return StringEscapeUtils.unescapeHtml(html);
-    }
-
-    public static int countMapValues(Map<?, ?> map) {
-        int total = 0;
-        if (map != null && map.size() > 0) {
-            for (Object value : map.values()) {
-                if (value != null) {
-                    if (value instanceof Number) {
-                        total += ((Number) value).intValue();
-                    } else if (value.getClass().isArray()) {
-                        total += Array.getLength(value);
-                    } else if (value instanceof Collection) {
-                        total += ((Collection<?>) value).size();
-                    } else if (value instanceof Map) {
-                        total += ((Map<?, ?>) value).size();
-                    } else {
-                        total += 1;
-                    }
-                }
-            }
-        }
-        return total;
-    }
-
-    public static List<String> sortSimpleName(List<String> list) {
-        if (list != null && list.size() > 0) {
-            Collections.sort(list, SIMPLE_NAME_COMPARATOR);
-        }
-        return list;
-    }
-
-    public static String getSimpleName(String name) {
-        if (name != null && name.length() > 0) {
-            final int ip = name.indexOf('/');
-            String v = ip != -1 ? name.substring(0, ip + 1) : "";
-
-            int i = name.lastIndexOf(':');
-            int j = (i >= 0 ? name.lastIndexOf('.', i) : name.lastIndexOf('.'));
-            if (j >= 0) {
-                name = name.substring(j + 1);
-            }
-            name = v + name;
-        }
-        return name;
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConsumerService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java
similarity index 88%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConsumerService.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java
index daafd7d..0cd5238 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ConsumerService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ConsumerService.java
@@ -14,9 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service;
+package org.apache.dubbo.admin.service;
 
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
+import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 
 import java.util.List;
 
@@ -30,6 +31,8 @@
 
     Consumer findConsumer(String id);
 
+    String getConsumerMetadata(MetadataIdentifier consumerIdentifier);
+
     List<Consumer> findAll();
 
     /**
@@ -57,4 +60,4 @@
 
     List<String> findServices();
 
-}
\ No newline at end of file
+}
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
new file mode 100644
index 0000000..b17b96f
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OverrideService.java
@@ -0,0 +1,53 @@
+/*
+ * 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;
+
+import org.apache.dubbo.admin.model.dto.BalancingDTO;
+import org.apache.dubbo.admin.model.dto.DynamicConfigDTO;
+import org.apache.dubbo.admin.model.dto.WeightDTO;
+
+public interface OverrideService {
+
+    void saveOverride(DynamicConfigDTO override);
+
+    void updateOverride(DynamicConfigDTO override);
+
+    void deleteOverride(String id);
+
+    void enableOverride(String id);
+
+    void disableOverride(String id);
+
+    DynamicConfigDTO findOverride(String id);
+
+    void saveWeight(WeightDTO weightDTO);
+
+    void updateWeight(WeightDTO weightDTO);
+
+    void deleteWeight(String id);
+
+    WeightDTO findWeight(String id);
+
+    void saveBalance(BalancingDTO balancingDTO);
+
+    void updateBalance(BalancingDTO balancingDTO);
+
+    void deleteBalance(String id);
+
+    BalancingDTO findBalance(String id);
+
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OwnerService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OwnerService.java
similarity index 91%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OwnerService.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OwnerService.java
index e079edb..660b5f4 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/OwnerService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/OwnerService.java
@@ -14,9 +14,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service;
+package org.apache.dubbo.admin.service;
 
-import org.apache.dubbo.admin.registry.common.domain.Owner;
+import org.apache.dubbo.admin.model.domain.Owner;
 
 import java.util.List;
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ProviderService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
similarity index 78%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ProviderService.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
index 5f2398d..eafb6d0 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/ProviderService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
@@ -14,9 +14,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service;
+package org.apache.dubbo.admin.service;
 
-import org.apache.dubbo.admin.registry.common.domain.Provider;
+import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 
 import java.util.List;
 
@@ -28,13 +29,13 @@
 
     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);
 
@@ -42,8 +43,14 @@
 
     Provider findProvider(String id);
 
+    String getProviderMetaData(MetadataIdentifier providerIdentifier);
+
     List<String> findServices();
 
+    String findServiceVersion(String serviceName, String application);
+
+    String findVersionInApplication(String application);
+
     List<String> findAddresses();
 
     List<String> findAddressesByApplication(String application);
@@ -72,4 +79,4 @@
 
     Provider findByServiceAndAddress(String service, String address);
 
-}
\ No newline at end of file
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/RegistryServerSync.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
similarity index 91%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/RegistryServerSync.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
index b4ff073..7a9b1fa 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/sync/RegistryServerSync.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
@@ -14,18 +14,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.sync;
+package org.apache.dubbo.admin.service;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import com.alibaba.dubbo.common.utils.NetUtils;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import com.alibaba.dubbo.registry.NotifyListener;
-import com.alibaba.dubbo.registry.RegistryService;
-import org.apache.dubbo.admin.util.MD5Util;
-import org.apache.dubbo.admin.web.pulltool.Tool;
+import org.apache.dubbo.admin.common.util.MD5Util;
+import org.apache.dubbo.admin.common.util.Tool;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.registry.NotifyListener;
+import org.apache.dubbo.registry.Registry;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -64,7 +64,7 @@
     private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>>
         registryCache = new ConcurrentHashMap<>();
     @Autowired
-    private RegistryService registryService;
+    private Registry registry;
 
     public ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> getRegistryCache() {
         return registryCache;
@@ -72,11 +72,11 @@
 
     public void afterPropertiesSet() throws Exception {
         logger.info("Init Dubbo Admin Sync Cache...");
-        registryService.subscribe(SUBSCRIBE, this);
+        registry.subscribe(SUBSCRIBE, this);
     }
 
     public void destroy() throws Exception {
-        registryService.unsubscribe(SUBSCRIBE, this);
+        registry.unsubscribe(SUBSCRIBE, this);
     }
 
     // Notification of of any service with any type (override、subcribe、route、provider) is full.
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
new file mode 100644
index 0000000..4f5acb8
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RouteService.java
@@ -0,0 +1,67 @@
+/*
+ * 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;
+
+import org.apache.dubbo.admin.model.dto.AccessDTO;
+import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
+import org.apache.dubbo.admin.model.dto.TagRouteDTO;
+
+/**
+ * RouteService
+ *
+ */
+public interface RouteService {
+
+    void createConditionRoute(ConditionRouteDTO conditionRoute);
+
+    void updateConditionRoute(ConditionRouteDTO newConditionRoute);
+
+    void deleteConditionRoute(String id);
+
+    void deleteAccess(String id);
+
+    void createAccess(AccessDTO accessDTO);
+
+    AccessDTO findAccess(String id);
+
+    void updateAccess(AccessDTO accessDTO);
+
+    void enableConditionRoute(String id);
+
+
+    void disableConditionRoute(String id);
+
+
+    ConditionRouteDTO findConditionRoute(String id);
+
+    void createTagRoute(TagRouteDTO tagRoute);
+
+    void updateTagRoute(TagRouteDTO tagRoute);
+
+    void deleteTagRoute(String id);
+
+
+    void enableTagRoute(String id);
+
+
+    void disableTagRoute(String id);
+
+
+    TagRouteDTO findTagRoute(String id);
+
+
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/AbstractService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
similarity index 68%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/AbstractService.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
index 10d5eec..914943d 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/AbstractService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
@@ -14,13 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service.impl;
+package org.apache.dubbo.admin.service.impl;
 
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import com.alibaba.dubbo.registry.RegistryService;
-import org.apache.dubbo.admin.governance.sync.RegistryServerSync;
+import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
+import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.admin.service.RegistryServerSync;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.registry.Registry;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import java.util.Map;
@@ -33,8 +35,16 @@
 public class AbstractService {
 
     protected static final Logger logger = LoggerFactory.getLogger(AbstractService.class);
+
     @Autowired
-    protected RegistryService registryService;
+    protected Registry registry;
+
+    @Autowired
+    protected GovernanceConfiguration dynamicConfiguration;
+
+    @Autowired
+    protected MetaDataCollector metaDataCollector;
+
     @Autowired
     private RegistryServerSync sync;
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ConsumerServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
similarity index 93%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ConsumerServiceImpl.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
index 98056c2..c719389 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/governance/service/impl/ConsumerServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java
@@ -14,14 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.admin.governance.service.impl;
+package org.apache.dubbo.admin.service.impl;
 
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import org.apache.dubbo.admin.governance.service.ConsumerService;
-import org.apache.dubbo.admin.governance.sync.util.Pair;
-import org.apache.dubbo.admin.governance.sync.util.SyncUtils;
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
+import org.apache.dubbo.admin.common.util.Pair;
+import org.apache.dubbo.admin.common.util.SyncUtils;
+import org.apache.dubbo.admin.model.domain.Consumer;
+import org.apache.dubbo.admin.service.ConsumerService;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.springframework.stereotype.Component;
 
 import java.util.ArrayList;
@@ -49,6 +50,11 @@
         return SyncUtils.url2ConsumerList(findAllConsumerUrl());
     }
 
+    @Override
+    public String getConsumerMetadata(MetadataIdentifier consumerIdentifier) {
+        return metaDataCollector.getConsumerMetaData(consumerIdentifier);
+    }
+
     private Map<String, URL> findAllConsumerUrl() {
         Map<String, String> filter = new HashMap<String, String>();
         filter.put(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY);
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
new file mode 100644
index 0000000..f69e7bb
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OverrideServiceImpl.java
@@ -0,0 +1,566 @@
+/*
+ * 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.commons.lang3.StringUtils;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.common.util.OverrideUtils;
+import org.apache.dubbo.admin.common.util.YamlParser;
+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 org.apache.dubbo.admin.model.dto.BalancingDTO;
+import org.apache.dubbo.admin.model.dto.DynamicConfigDTO;
+import org.apache.dubbo.admin.model.dto.WeightDTO;
+import org.apache.dubbo.admin.model.store.OverrideConfig;
+import org.apache.dubbo.admin.model.store.OverrideDTO;
+import org.apache.dubbo.admin.service.OverrideService;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * IbatisOverrideDAO.java
+ *
+ */
+@Component
+public class OverrideServiceImpl extends AbstractService implements OverrideService {
+    private String prefix = Constants.CONFIG_KEY;
+
+    @java.lang.Override
+    public void saveOverride(DynamicConfigDTO override) {
+        String id = ConvertUtil.getIdFromDTO(override);
+        String path = getPath(id);
+        String exitConfig = dynamicConfiguration.getConfig(path);
+        List<OverrideConfig> configs = new ArrayList<>();
+        OverrideDTO existOverride = OverrideUtils.createFromDynamicConfig(override);
+        if (exitConfig != null) {
+            existOverride = YamlParser.loadObject(exitConfig, OverrideDTO.class);
+            if (existOverride.getConfigs() != null) {
+                for (OverrideConfig overrideConfig : existOverride.getConfigs()) {
+                    if (Constants.CONFIGS.contains(overrideConfig.getType())) {
+                        configs.add(overrideConfig);
+                    }
+                }
+            }
+        }
+        configs.addAll(override.getConfigs());
+        existOverride.setEnabled(override.isEnabled());
+        existOverride.setConfigs(configs);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(existOverride));
+
+        //for2.6
+        if (StringUtils.isNotEmpty(override.getService())) {
+            List<Override> result = convertDTOtoOldOverride(override);
+            for (Override o : result) {
+                registry.register(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            }
+        }
+    }
+
+    @java.lang.Override
+    public void updateOverride(DynamicConfigDTO update) {
+        String id = ConvertUtil.getIdFromDTO(update);
+        String path = getPath(id);
+        String exitConfig = dynamicConfiguration.getConfig(path);
+        if (exitConfig == null) {
+            //throw exception
+        }
+        OverrideDTO overrideDTO = YamlParser.loadObject(exitConfig, OverrideDTO.class);
+        DynamicConfigDTO old = OverrideUtils.createFromOverride(overrideDTO);
+        List<OverrideConfig> configs = new ArrayList<>();
+        if (overrideDTO.getConfigs() != null) {
+            List<OverrideConfig> overrideConfigs = overrideDTO.getConfigs();
+            for (OverrideConfig config : overrideConfigs) {
+                if (Constants.CONFIGS.contains(config.getType())) {
+                    configs.add(config);
+                }
+            }
+        }
+        configs.addAll(update.getConfigs());
+        overrideDTO.setConfigs(configs);
+        overrideDTO.setEnabled(update.isEnabled());
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+
+        //for 2.6
+        if (StringUtils.isNotEmpty(update.getService())) {
+            List<Override> oldOverrides = convertDTOtoOldOverride(old);
+            List<Override> updatedOverrides = convertDTOtoOldOverride(update);
+            for (Override o : oldOverrides) {
+                registry.unregister(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            }
+            for (Override o : updatedOverrides) {
+                registry.register(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            }
+        }
+    }
+
+    @java.lang.Override
+    public void deleteOverride(String id) {
+        if (StringUtils.isEmpty(id)) {
+            // throw exception
+        }
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config == null) {
+            //throw exception
+        }
+        OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+        DynamicConfigDTO old = OverrideUtils.createFromOverride(overrideDTO);
+        List<OverrideConfig> newConfigs = new ArrayList<>();
+        if (overrideDTO.getConfigs() != null && overrideDTO.getConfigs().size() > 0) {
+            for (OverrideConfig overrideConfig : overrideDTO.getConfigs()) {
+                if (Constants.CONFIGS.contains(overrideConfig.getType())) {
+                    newConfigs.add(overrideConfig);
+                }
+            }
+            if (newConfigs.size() == 0) {
+                dynamicConfiguration.deleteConfig(path);
+            } else {
+                overrideDTO.setConfigs(newConfigs);
+                dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+            }
+        } else {
+            dynamicConfiguration.deleteConfig(path);
+        }
+
+        //for 2.6
+        if (overrideDTO.getScope().equals(Constants.SERVICE)) {
+            List<Override> overrides = convertDTOtoOldOverride(old);
+            for (Override o : overrides) {
+                registry.unregister(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            }
+        }
+    }
+
+    @java.lang.Override
+    public void enableOverride(String id) {
+        if (StringUtils.isEmpty(id)) {
+            //throw exception
+        }
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config == null) {
+            //throw exception
+        }
+        OverrideDTO override = YamlParser.loadObject(config, OverrideDTO.class);
+        DynamicConfigDTO old = OverrideUtils.createFromOverride(override);
+        override.setEnabled(true);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(override));
+
+        //2.6
+        if (override.getScope().equals(Constants.SERVICE)) {
+            List<Override> overrides = convertDTOtoOldOverride(old);
+            for (Override o : overrides) {
+                o.setEnabled(false);
+                registry.unregister(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+                o.setEnabled(true);
+                registry.register(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            }
+        }
+    }
+
+    @java.lang.Override
+    public void disableOverride(String id) {
+        if (StringUtils.isEmpty(id)) {
+            //throw exception
+        }
+        String path = getPath(id);
+        if (dynamicConfiguration.getConfig(path) == null) {
+            //throw exception
+        }
+        String config = dynamicConfiguration.getConfig(path);
+        OverrideDTO override = YamlParser.loadObject(config, OverrideDTO.class);
+        DynamicConfigDTO old = OverrideUtils.createFromOverride(override);
+        override.setEnabled(false);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(override));
+
+        //for 2.6
+        if (override.getScope().equals(Constants.SERVICE)) {
+            List<Override> overrides = convertDTOtoOldOverride(old);
+            for (Override o : overrides) {
+                o.setEnabled(true);
+                registry.unregister(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+                o.setEnabled(false);
+                registry.register(o.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            }
+        }
+    }
+
+    @java.lang.Override
+    public DynamicConfigDTO findOverride(String id) {
+        if (StringUtils.isEmpty(id)) {
+            //throw exception
+        }
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            return OverrideUtils.createFromOverride(overrideDTO);
+        }
+        return null;
+    }
+
+    @java.lang.Override
+    public void saveWeight(WeightDTO weightDTO) {
+        String id = ConvertUtil.getIdFromDTO(weightDTO);
+        String scope = ConvertUtil.getScopeFromDTO(weightDTO);
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        OverrideConfig overrideConfig = OverrideUtils.weightDTOtoConfig(weightDTO);
+        OverrideDTO overrideDTO = insertConfig(config, overrideConfig, id, scope, Constants.WEIGHT);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+
+        //for 2.6
+        if (scope.equals(Constants.SERVICE)) {
+            registerWeight(weightDTO);
+        }
+
+    }
+
+    @java.lang.Override
+    public void updateWeight(WeightDTO weightDTO) {
+        String id = ConvertUtil.getIdFromDTO(weightDTO);
+        String scope = ConvertUtil.getScopeFromDTO(weightDTO);
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        WeightDTO oldWeight = null;
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null && configs.size() > 0) {
+                for (OverrideConfig overrideConfig : configs) {
+                    if (Constants.WEIGHT.equals(overrideConfig.getType())) {
+                        if (overrideDTO.getScope().equals(Constants.SERVICE)) {
+                            oldWeight = OverrideUtils.configtoWeightDTO(overrideConfig, scope, id);
+                        }
+                        int index = configs.indexOf(overrideConfig);
+                        OverrideConfig newConfig = OverrideUtils.weightDTOtoConfig(weightDTO);
+                        configs.set(index, newConfig);
+                        break;
+                    }
+                }
+                dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+            } else {
+                //throw exception
+            }
+        } else {
+            //throw exception
+        }
+
+
+        //for 2.6
+        if (oldWeight != null) {
+            unregisterWeight(oldWeight);
+            registerWeight(weightDTO);
+        }
+
+    }
+
+    @java.lang.Override
+    public void deleteWeight(String id) {
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        OverrideConfig oldConfig = null;
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null) {
+                for (OverrideConfig overrideConfig : configs) {
+                    if (Constants.WEIGHT.equals(overrideConfig.getType())) {
+                        if (overrideDTO.getScope().equals(Constants.SERVICE)) {
+                            oldConfig = overrideConfig;
+                        }
+                        configs.remove(overrideConfig);
+                        break;
+                    }
+                }
+                if (configs.size() == 0) {
+                    dynamicConfiguration.deleteConfig(path);
+                } else {
+                    dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+                }
+
+            }
+
+            //for 2.6
+            if (oldConfig != null) {
+                String key = overrideDTO.getKey();
+                WeightDTO weightDTO = OverrideUtils.configtoWeightDTO(oldConfig, overrideDTO.getScope(), key);
+                unregisterWeight(weightDTO);
+            }
+        }
+    }
+
+    @java.lang.Override
+    public WeightDTO findWeight(String id) {
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null) {
+                for (OverrideConfig overrideConfig : configs) {
+                    if (Constants.WEIGHT.equals(overrideConfig.getType())) {
+                        WeightDTO weightDTO = OverrideUtils.configtoWeightDTO(overrideConfig, overrideDTO.getScope(), id);
+                        return weightDTO;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    @java.lang.Override
+    public void saveBalance(BalancingDTO balancingDTO) {
+        String id = ConvertUtil.getIdFromDTO(balancingDTO);
+        String scope = ConvertUtil.getScopeFromDTO(balancingDTO);
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        OverrideConfig overrideConfig = OverrideUtils.balanceDTOtoConfig(balancingDTO);
+        OverrideDTO overrideDTO = insertConfig(config, overrideConfig, id, scope, Constants.BALANCING);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+
+        //for 2.6
+
+        if (scope.equals(Constants.SERVICE)) {
+            registerBalancing(balancingDTO);
+        }
+    }
+
+    @java.lang.Override
+    public void updateBalance(BalancingDTO balancingDTO) {
+        String id = ConvertUtil.getIdFromDTO(balancingDTO);
+        String scope = ConvertUtil.getScopeFromDTO(balancingDTO);
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        BalancingDTO oldBalancing = null;
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null && configs.size() > 0) {
+                for (OverrideConfig overrideConfig : configs) {
+                    if (Constants.BALANCING.equals(overrideConfig.getType())) {
+                        if (overrideDTO.getScope().equals(Constants.SERVICE)) {
+                            oldBalancing = OverrideUtils.configtoBalancingDTO(overrideConfig, Constants.SERVICE, overrideDTO.getKey());
+                        }
+                        int index = configs.indexOf(overrideConfig);
+                        OverrideConfig newConfig = OverrideUtils.balanceDTOtoConfig(balancingDTO);
+                        configs.set(index, newConfig);
+                        break;
+                    }
+                }
+                dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+            } else {
+                //throw exception
+            }
+        } else {
+            //throw exception
+        }
+
+        //for 2.6
+        if (oldBalancing != null) {
+            unregisterBalancing(oldBalancing);
+            registerBalancing(balancingDTO);
+        }
+    }
+
+    @java.lang.Override
+    public void deleteBalance(String id) {
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        OverrideConfig oldConfig = null;
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null) {
+                for (OverrideConfig overrideConfig : configs) {
+                    if (Constants.BALANCING.equals(overrideConfig.getType())) {
+                        if (overrideDTO.getScope().equals(Constants.SERVICE)) {
+                            oldConfig = overrideConfig;
+                        }
+                        configs.remove(overrideConfig);
+                        break;
+                    }
+                }
+                if (configs.size() == 0) {
+                    dynamicConfiguration.deleteConfig(path);
+                } else {
+                    dynamicConfiguration.setConfig(path, YamlParser.dumpObject(overrideDTO));
+                }
+            }
+            //for 2.6
+            if (oldConfig != null) {
+                String key = overrideDTO.getKey();
+                BalancingDTO balancingDTO = OverrideUtils.configtoBalancingDTO(oldConfig, Constants.SERVICE, key);
+                unregisterBalancing(balancingDTO);
+            }
+        }
+    }
+
+    @java.lang.Override
+    public BalancingDTO findBalance(String id) {
+        String path = getPath(id);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            OverrideDTO overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null) {
+                for (OverrideConfig overrideConfig : configs) {
+                    if (Constants.BALANCING.equals(overrideConfig.getType())) {
+                        BalancingDTO balancingDTO = OverrideUtils.configtoBalancingDTO(overrideConfig, overrideDTO.getScope(), id);
+                        return balancingDTO;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private OverrideDTO insertConfig(String config, OverrideConfig overrideConfig, String key, String scope, String configType) {
+        OverrideDTO overrideDTO = null;
+        if(config == null) {
+            overrideDTO = new OverrideDTO();
+            overrideDTO.setKey(key);
+            overrideDTO.setScope(scope);
+            List<OverrideConfig> configs = new ArrayList<>();
+            configs.add(overrideConfig);
+            overrideDTO.setConfigs(configs);
+        } else {
+            overrideDTO = YamlParser.loadObject(config, OverrideDTO.class);
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            if (configs != null) {
+                for (OverrideConfig o : configs) {
+                    if (configType.equals(o.getType())) {
+                        configs.remove(o);
+                        break;
+                    }
+                }
+                configs.add(overrideConfig);
+            } else {
+                configs = new ArrayList<>();
+                configs.add(overrideConfig);
+            }
+            overrideDTO.setConfigs(configs);
+        }
+        return overrideDTO;
+    }
+
+    private void overrideDTOToParams(Override override, OverrideConfig config) {
+        Map<String, Object> parameters = config.getParameters();
+        StringBuilder params = new StringBuilder();
+
+        if (parameters != null) {
+            for (Map.Entry<String, Object> entry : parameters.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 List<Override> convertDTOtoOldOverride(DynamicConfigDTO overrideDTO) {
+        List<Override> result = new ArrayList<>();
+        List<OverrideConfig> configs = overrideDTO.getConfigs();
+        for (OverrideConfig config : configs) {
+            if (Constants.CONFIGS.contains(config.getType())) {
+                continue;
+            }
+            List<String> apps = config.getApplications();
+            List<String> addresses = config.getAddresses();
+            for (String address : addresses) {
+                if (apps != null && apps.size() > 0) {
+                    for (String app : apps) {
+                        Override override = new Override();
+                        override.setService(overrideDTO.getService());
+                        override.setAddress(address);
+                        override.setEnabled(overrideDTO.isEnabled());
+                        overrideDTOToParams(override, config);
+                        override.setApplication(app);
+                        result.add(override);
+                    }
+                } else {
+                    Override override = new Override();
+                    override.setService(overrideDTO.getService());
+                    override.setAddress(address);
+                    override.setEnabled(overrideDTO.isEnabled());
+                    overrideDTOToParams(override, config);
+                    result.add(override);
+                }
+            }
+        }
+        return result;
+    }
+    private String getPath(String key) {
+        return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + Constants.CONFIGURATOR;
+    }
+
+    private void unregisterWeight(WeightDTO weightDTO) {
+        List<String> addresses = weightDTO.getAddresses();
+        if (addresses != null) {
+            for (String address : addresses) {
+                Weight weight = new Weight();
+                weight.setService(weightDTO.getService());
+                weight.setAddress(address);
+                weight.setWeight(weightDTO.getWeight());
+                Override override = OverrideUtils.weightToOverride(weight);
+                registry.unregister(override.toUrl());
+            }
+        }
+    }
+
+    private void registerWeight(WeightDTO weightDTO) {
+        List<String> addresses = weightDTO.getAddresses();
+        if (addresses != null) {
+            for (String address : addresses) {
+                Weight weight = new Weight();
+                weight.setService(weightDTO.getService());
+                weight.setAddress(address);
+                weight.setWeight(weightDTO.getWeight());
+                Override override = OverrideUtils.weightToOverride(weight);
+                registry.register(override.toUrl());
+            }
+
+        }
+    }
+
+    private void unregisterBalancing(BalancingDTO balancingDTO) {
+        LoadBalance loadBalance = new LoadBalance();
+        loadBalance.setService(balancingDTO.getService());
+        loadBalance.setMethod(balancingDTO.getMethodName());
+        loadBalance.setStrategy(balancingDTO.getStrategy());
+        registry.unregister(OverrideUtils.loadBalanceToOverride(loadBalance).toUrl());
+    }
+
+    private void registerBalancing(BalancingDTO balancingDTO) {
+        LoadBalance loadBalance = new LoadBalance();
+        loadBalance.setService(balancingDTO.getService());
+        loadBalance.setMethod(balancingDTO.getMethodName());
+        loadBalance.setStrategy(balancingDTO.getStrategy());
+        registry.register(OverrideUtils.loadBalanceToOverride(loadBalance).toUrl());
+    }
+
+}
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
new file mode 100644
index 0000000..38be229
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/OwnerServiceImpl.java
@@ -0,0 +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());
+//                    }
+//                }
+//            }
+//        }
+//    }
+//
+//}
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
new file mode 100644
index 0000000..09670c8
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
@@ -0,0 +1,509 @@
+/*
+ * 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 com.google.common.collect.Iterables;
+import com.google.gson.Gson;
+import org.apache.dubbo.admin.common.exception.ParamValidationException;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.common.util.Pair;
+import org.apache.dubbo.admin.common.util.ParseUtils;
+import org.apache.dubbo.admin.common.util.SyncUtils;
+import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.admin.service.OverrideService;
+import org.apache.dubbo.admin.service.ProviderService;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.yaml.snakeyaml.events.Event;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentMap;
+
+import static org.apache.dubbo.common.Constants.SPECIFICATION_VERSION_KEY;
+
+/**
+ * IbatisProviderService
+ *
+ */
+@Component
+public class ProviderServiceImpl extends AbstractService implements ProviderService {
+
+    @Autowired
+    OverrideService overrideService;
+
+    public void create(Provider provider) {
+        URL url = provider.toUrl();
+        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);
+//        }
+//    }
+
+    @java.lang.Override
+    public String getProviderMetaData(MetadataIdentifier 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);
+//        }
+//    }
+
+    private int getWeight(String value, float factor) {
+        int weight = 100;
+        if (value != null && value.length() > 0) {
+            weight = Integer.parseInt(value);
+        }
+        weight = (int) (weight * factor);
+        if (weight < 1) weight = 1;
+        if (weight == 2) weight = 3;
+        if (weight == 24) weight = 25;
+        return weight;
+    }
+
+    public void deleteStaticProvider(String id) {
+        URL oldProvider = findProviderUrl(id);
+        if (oldProvider == null) {
+            throw new IllegalStateException("Provider was changed!");
+        }
+        registry.unregister(oldProvider);
+    }
+
+    public void updateProvider(Provider provider) {
+        String hash = provider.getHash();
+        if (hash == null) {
+            throw new IllegalStateException("no provider id");
+        }
+
+        URL oldProvider = findProviderUrl(hash);
+        if (oldProvider == null) {
+            throw new IllegalStateException("Provider was changed!");
+        }
+        URL newProvider = provider.toUrl();
+
+        registry.unregister(oldProvider);
+        registry.register(newProvider);
+    }
+
+    public Provider findProvider(String id) {
+        return SyncUtils.url2Provider(findProviderUrlPair(id));
+    }
+
+    public Pair<String, URL> findProviderUrlPair(String id) {
+        return SyncUtils.filterFromCategory(getRegistryCache(), Constants.PROVIDERS_CATEGORY, id);
+    }
+
+    public List<String> findServices() {
+        List<String> ret = new ArrayList<String>();
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls != null) ret.addAll(providerUrls.keySet());
+        return ret;
+    }
+
+    public List<String> findAddresses() {
+        List<String> ret = new ArrayList<String>();
+
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (null == providerUrls) return ret;
+
+        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
+            Map<String, URL> value = e1.getValue();
+            for (Map.Entry<String, URL> e2 : value.entrySet()) {
+                URL u = e2.getValue();
+                String app = u.getAddress();
+                if (app != null) ret.add(app);
+            }
+        }
+
+        return ret;
+    }
+
+    public List<String> findAddressesByApplication(String application) {
+        List<String> ret = new ArrayList<String>();
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
+            Map<String, URL> value = e1.getValue();
+            for (Map.Entry<String, URL> e2 : value.entrySet()) {
+                URL u = e2.getValue();
+                if (application.equals(u.getParameter(Constants.APPLICATION_KEY))) {
+                    String addr = u.getAddress();
+                    if (addr != null) ret.add(addr);
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    public List<String> findAddressesByService(String service) {
+        List<String> ret = new ArrayList<String>();
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (null == providerUrls) return ret;
+
+        for (Map.Entry<String, URL> e2 : providerUrls.get(service).entrySet()) {
+            URL u = e2.getValue();
+            String app = u.getAddress();
+            if (app != null) ret.add(app);
+        }
+
+        return ret;
+    }
+
+    public List<String> findApplicationsByServiceName(String service) {
+        List<String> ret = new ArrayList<String>();
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (null == providerUrls) return ret;
+
+        Map<String, URL> value = providerUrls.get(service);
+        if (value == null) {
+            return ret;
+        }
+        for (Map.Entry<String, URL> e2 : value.entrySet()) {
+            URL u = e2.getValue();
+            String app = u.getParameter(Constants.APPLICATION_KEY);
+            if (app != null) ret.add(app);
+        }
+
+        return ret;
+    }
+
+    public List<Provider> findByService(String serviceName) {
+        return SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
+    }
+
+    public List<Provider> findByAppandService(String app, String serviceName) {
+        return SyncUtils.url2ProviderList(findProviderUrlByAppandService(app, serviceName));
+    }
+
+    private Map<String, URL> findProviderUrlByService(String service) {
+        Map<String, String> filter = new HashMap<String, String>();
+        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+        filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
+
+        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+    }
+
+    public List<Provider> findAll() {
+        return SyncUtils.url2ProviderList(findAllProviderUrl());
+    }
+
+    private Map<String, URL> findAllProviderUrl() {
+        Map<String, String> filter = new HashMap<String, String>();
+        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+    }
+
+    public List<Provider> findByAddress(String providerAddress) {
+        return SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
+    }
+
+    public Map<String, URL> findProviderUrlByAddress(String address) {
+        Map<String, String> filter = new HashMap<String, String>();
+        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+        filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
+
+        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+    }
+
+    public List<String> findServicesByAddress(String address) {
+        List<String> ret = new ArrayList<String>();
+
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls == null || address == null || address.length() == 0) return ret;
+
+        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
+            Map<String, URL> value = e1.getValue();
+            for (Map.Entry<String, URL> e2 : value.entrySet()) {
+                URL u = e2.getValue();
+                if (address.equals(u.getAddress())) {
+                    ret.add(e1.getKey());
+                    break;
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    public List<String> findApplications() {
+        List<String> ret = new ArrayList<String>();
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls == null) return ret;
+
+        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
+            Map<String, URL> value = e1.getValue();
+            for (Map.Entry<String, URL> e2 : value.entrySet()) {
+                URL u = e2.getValue();
+                String app = u.getParameter(Constants.APPLICATION_KEY);
+                if (app != null) ret.add(app);
+            }
+        }
+
+        return ret;
+    }
+
+    public List<Provider> findByApplication(String application) {
+        return SyncUtils.url2ProviderList(findProviderUrlByApplication(application));
+    }
+
+    @Override
+    public String findVersionInApplication(String application) {
+        List<String> services = findServicesByApplication(application);
+        if (services == null || services.size() == 0) {
+            throw new ParamValidationException("there is no service for application: " + application);
+        }
+        return findServiceVersion(services.get(0), application);
+    }
+
+    @Override
+    public String findServiceVersion(String serviceName, String application) {
+        String version = "2.6";
+        Map<String, URL> result = findProviderUrlByAppandService(application, serviceName);
+        if (result != null && result.size() > 0) {
+            URL url = result.values().stream().findFirst().get();
+            if (url.getParameter(Constants.SPECIFICATION_VERSION_KEY) != null) {
+                version = url.getParameter(Constants.SPECIFICATION_VERSION_KEY);
+            }
+        }
+        return version;
+    }
+
+    private Map<String, URL> findProviderUrlByAppandService(String app, String service) {
+        Map<String, String> filter = new HashMap<>();
+        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+        filter.put(Constants.APPLICATION_KEY, app);
+        filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
+        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+    }
+
+
+
+    private Map<String, URL> findProviderUrlByApplication(String application) {
+        Map<String, String> filter = new HashMap<>();
+        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+        filter.put(Constants.APPLICATION_KEY, application);
+        return SyncUtils.filterFromCategory(getRegistryCache(), filter);
+    }
+
+    public List<String> findServicesByApplication(String application) {
+        List<String> ret = new ArrayList<String>();
+
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls == null || application == null || application.length() == 0) return ret;
+
+        for (Map.Entry<String, Map<String, URL>> e1 : providerUrls.entrySet()) {
+            Map<String, URL> value = e1.getValue();
+            for (Map.Entry<String, URL> e2 : value.entrySet()) {
+                URL u = e2.getValue();
+                if (application.equals(u.getParameter(Constants.APPLICATION_KEY))) {
+                    ret.add(e1.getKey());
+                    break;
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    public List<String> findMethodsByService(String service) {
+        List<String> ret = new ArrayList<String>();
+
+        ConcurrentMap<String, Map<String, URL>> providerUrls = getRegistryCache().get(Constants.PROVIDERS_CATEGORY);
+        if (providerUrls == null || service == null || service.length() == 0) return ret;
+
+        Map<String, URL> providers = providerUrls.get(service);
+        if (null == providers || providers.isEmpty()) return ret;
+
+        Entry<String, URL> p = providers.entrySet().iterator().next();
+        String value = p.getValue().getParameter("methods");
+        if (value == null || value.length() == 0) {
+            return ret;
+        }
+        String[] methods = value.split(ParseUtils.METHOD_SPLIT);
+        if (methods == null || methods.length == 0) {
+            return ret;
+        }
+
+        for (String m : methods) {
+            ret.add(m);
+        }
+        return ret;
+    }
+
+    private URL findProviderUrl(String id) {
+        return findProvider(id).toUrl();
+    }
+
+    public Provider findByServiceAndAddress(String service, String address) {
+        return SyncUtils.url2Provider(findProviderUrl(service, address));
+    }
+
+    private Pair<String, URL> findProviderUrl(String service, String address) {
+        Map<String, String> filter = new HashMap<String, String>();
+        filter.put(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
+        filter.put(SyncUtils.ADDRESS_FILTER_KEY, address);
+
+        Map<String, URL> ret = SyncUtils.filterFromCategory(getRegistryCache(), filter);
+        if (ret.isEmpty()) {
+            return null;
+        } else {
+            String key = ret.entrySet().iterator().next().getKey();
+            return new Pair<String, URL>(key, ret.get(key));
+        }
+    }
+
+}
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
new file mode 100644
index 0000000..f888113
--- /dev/null
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
@@ -0,0 +1,372 @@
+/*
+ * 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.admin.common.exception.ResourceNotFoundException;
+import org.apache.dubbo.admin.common.util.Constants;
+import org.apache.dubbo.admin.common.util.ConvertUtil;
+import org.apache.dubbo.admin.common.util.RouteRule;
+import org.apache.dubbo.admin.common.util.YamlParser;
+import org.apache.dubbo.admin.model.domain.Route;
+import org.apache.dubbo.admin.model.dto.AccessDTO;
+import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
+import org.apache.dubbo.admin.model.dto.TagRouteDTO;
+import org.apache.dubbo.admin.model.store.BlackWhiteList;
+import org.apache.dubbo.admin.model.store.RoutingRule;
+import org.apache.dubbo.admin.model.store.TagRoute;
+import org.apache.dubbo.admin.service.RouteService;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * IbatisRouteService
+ *
+ */
+@Component
+public class RouteServiceImpl extends AbstractService implements RouteService {
+
+    private String prefix = Constants.CONFIG_KEY;
+
+    @Override
+    public void createConditionRoute(ConditionRouteDTO conditionRoute) {
+        String id = ConvertUtil.getIdFromDTO(conditionRoute);
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String existConfig = dynamicConfiguration.getConfig(path);
+        RoutingRule existRule = null;
+        if (existConfig != null) {
+            existRule = YamlParser.loadObject(existConfig, RoutingRule.class);
+        }
+        existRule = RouteRule.insertConditionRule(existRule, conditionRoute);
+        //register2.7
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(existRule));
+
+        //register2.6
+        if (StringUtils.isNotEmpty(conditionRoute.getService())) {
+            Route old = convertRouteToOldRoute(conditionRoute);
+            registry.register(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+        }
+
+    }
+
+    @Override
+    public void updateConditionRoute(ConditionRouteDTO newConditionRoute) {
+        String id = ConvertUtil.getIdFromDTO(newConditionRoute);
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String existConfig = dynamicConfiguration.getConfig(path);
+        if (existConfig == null) {
+            throw new ResourceNotFoundException("no existing condition route for path: " + path);
+        }
+        RoutingRule routingRule = YamlParser.loadObject(existConfig, RoutingRule.class);
+        ConditionRouteDTO oldConditionRoute = RouteRule.createConditionRouteFromRule(routingRule);
+        routingRule = RouteRule.insertConditionRule(routingRule, newConditionRoute);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(routingRule));
+
+        //for 2.6
+        if (StringUtils.isNotEmpty(newConditionRoute.getService())) {
+            Route old = convertRouteToOldRoute(oldConditionRoute);
+            Route updated = convertRouteToOldRoute(newConditionRoute);
+            registry.unregister(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+            registry.register(updated.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+        }
+    }
+
+    @Override
+    public void deleteConditionRoute(String id) {
+        if (StringUtils.isEmpty(id)) {
+            // throw exception
+        }
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config == null) {
+            //throw exception
+        }
+        RoutingRule route = YamlParser.loadObject(config, RoutingRule.class);
+        if (route.getBlackWhiteList() != null) {
+           route.setConditions(null);
+            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(route));
+        } else {
+            dynamicConfiguration.deleteConfig(path);
+        }
+
+        //for 2.6
+        if (route.getScope().equals(Constants.SERVICE)) {
+            RoutingRule originRule = YamlParser.loadObject(config, RoutingRule.class);
+            ConditionRouteDTO conditionRouteDTO = RouteRule.createConditionRouteFromRule(originRule);
+            Route old = convertRouteToOldRoute(conditionRouteDTO);
+            registry.unregister(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
+        }
+    }
+
+    @Override
+    public void deleteAccess(String id) {
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
+            BlackWhiteList old = ruleDTO.getBlackWhiteList();
+            if (ruleDTO.getConditions() == null) {
+                dynamicConfiguration.deleteConfig(path);
+            } else {
+                ruleDTO.setBlackWhiteList(null);
+                dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
+            }
+            //2.6
+            if (ruleDTO.getScope().equals(Constants.SERVICE) && old != null) {
+                Route route = RouteRule.convertBlackWhiteListtoRoute(old, Constants.SERVICE, id);
+                registry.unregister(route.toUrl());
+            }
+        }
+    }
+
+    @Override
+    public void createAccess(AccessDTO accessDTO) {
+        String id = ConvertUtil.getIdFromDTO(accessDTO);
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        BlackWhiteList blackWhiteList = RouteRule.convertToBlackWhiteList(accessDTO);
+        RoutingRule ruleDTO;
+        if (config == null) {
+            ruleDTO = new RoutingRule();
+            ruleDTO.setEnabled(true);
+            if (StringUtils.isNoneEmpty(accessDTO.getApplication())) {
+                ruleDTO.setScope(Constants.APPLICATION);
+            } else {
+                ruleDTO.setScope(Constants.SERVICE);
+            }
+            ruleDTO.setKey(id);
+            ruleDTO.setBlackWhiteList(blackWhiteList);
+        } else {
+            ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
+            if (ruleDTO.getBlackWhiteList() != null) {
+                //todo throw exception
+            }
+            ruleDTO.setBlackWhiteList(blackWhiteList);
+        }
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
+
+        //for 2.6
+        if (ruleDTO.getScope().equals("service")) {
+            Route route = RouteRule.convertAccessDTOtoRoute(accessDTO);
+            registry.register(route.toUrl());
+        }
+
+    }
+
+    @Override
+    public AccessDTO findAccess(String id) {
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
+            BlackWhiteList blackWhiteList = ruleDTO.getBlackWhiteList();
+            return RouteRule.convertToAccessDTO(blackWhiteList, ruleDTO.getScope(), ruleDTO.getKey());
+        }
+        return null;
+    }
+
+    @Override
+    public void updateAccess(AccessDTO accessDTO) {
+        String key = ConvertUtil.getIdFromDTO(accessDTO);
+        String path = getPath(key, Constants.CONDITION_ROUTE);
+        BlackWhiteList blackWhiteList = RouteRule.convertToBlackWhiteList(accessDTO);
+        BlackWhiteList old = null;
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
+            old = ruleDTO.getBlackWhiteList();
+            ruleDTO.setBlackWhiteList(blackWhiteList);
+            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
+        }
+
+        //2.6
+        if (StringUtils.isNotEmpty(accessDTO.getService())) {
+            Route oldRoute = RouteRule.convertBlackWhiteListtoRoute(old, Constants.SERVICE, key);
+            Route newRoute = RouteRule.convertAccessDTOtoRoute(accessDTO);
+            registry.unregister(oldRoute.toUrl());
+            registry.register(newRoute.toUrl());
+        }
+    }
+
+    @Override
+    public void enableConditionRoute(String id) {
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
+
+            if (ruleDTO.getScope().equals(Constants.SERVICE)) {
+                //for2.6
+                URL oldURL = convertRouteToOldRoute(RouteRule.createConditionRouteFromRule(ruleDTO)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true);
+                registry.unregister(oldURL);
+                oldURL = oldURL.addParameter("enabled", true);
+                registry.register(oldURL);
+            }
+
+            //2.7
+            ruleDTO.setEnabled(true);
+            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
+        }
+
+    }
+
+    @Override
+    public void disableConditionRoute(String serviceName) {
+        String path = getPath(serviceName, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            RoutingRule routeRule = YamlParser.loadObject(config, RoutingRule.class);
+
+            if (routeRule.getScope().equals(Constants.SERVICE)) {
+                //for 2.6
+                URL oldURL = convertRouteToOldRoute(RouteRule.createConditionRouteFromRule(routeRule)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG,true);
+                registry.unregister(oldURL);
+                oldURL = oldURL.addParameter("enabled", false);
+                registry.register(oldURL);
+            }
+
+            //2.7
+            routeRule.setEnabled(false);
+            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(routeRule));
+        }
+
+    }
+
+    @Override
+    public ConditionRouteDTO findConditionRoute(String id) {
+        String path = getPath(id, Constants.CONDITION_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            RoutingRule routingRule = YamlParser.loadObject(config, RoutingRule.class);
+            ConditionRouteDTO conditionRouteDTO = RouteRule.createConditionRouteFromRule(routingRule);
+            return conditionRouteDTO;
+        }
+        return null;
+    }
+
+    @Override
+    public void createTagRoute(TagRouteDTO tagRoute) {
+        String id = ConvertUtil.getIdFromDTO(tagRoute);
+        String path = getPath(id,Constants.TAG_ROUTE);
+        TagRoute store = RouteRule.convertTagroutetoStore(tagRoute);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(store));
+    }
+
+    @Override
+    public void updateTagRoute(TagRouteDTO tagRoute) {
+        String id = ConvertUtil.getIdFromDTO(tagRoute);
+        String path = getPath(id, Constants.TAG_ROUTE);
+        if (dynamicConfiguration.getConfig(path) == null) {
+            throw new ResourceNotFoundException("can not find tagroute: " + id);
+            //throw exception
+        }
+        TagRoute store = RouteRule.convertTagroutetoStore(tagRoute);
+        dynamicConfiguration.setConfig(path, YamlParser.dumpObject(store));
+
+    }
+
+    @Override
+    public void deleteTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        dynamicConfiguration.deleteConfig(path);
+    }
+
+    @Override
+    public void enableTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
+            tagRoute.setEnabled(true);
+            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(tagRoute));
+        }
+
+    }
+
+    @Override
+    public void disableTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
+            tagRoute.setEnabled(false);
+            dynamicConfiguration.setConfig(path, YamlParser.dumpObject(tagRoute));
+        }
+
+    }
+
+    @Override
+    public TagRouteDTO findTagRoute(String id) {
+        String path = getPath(id, Constants.TAG_ROUTE);
+        String config = dynamicConfiguration.getConfig(path);
+        if (config != null) {
+            TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
+            return RouteRule.convertTagroutetoDisplay(tagRoute);
+        }
+        return null;
+    }
+
+    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";
+        }
+    }
+
+    private String parseCondition(List<String> conditions) {
+        StringBuilder when = new StringBuilder();
+        StringBuilder then = new StringBuilder();
+        for (String condition : conditions) {
+            condition = condition.trim();
+            if (condition.contains("=>")) {
+                String[] array = condition.split("=>", 2);
+                String consumer = array[0].trim();
+                String provider = array[1].trim();
+                if (consumer != "") {
+                    if (when.length() != 0) {
+                        when.append(" & ").append(consumer);
+                    } else {
+                        when.append(consumer);
+                    }
+                }
+                if (provider != "") {
+                    if (then.length() != 0) {
+                        then.append(" & ").append(provider);
+                    } else {
+                        then.append(provider);
+                    }
+                }
+            }
+        }
+        return (when.append(" => ").append(then)).toString();
+    }
+
+    private Route convertRouteToOldRoute(ConditionRouteDTO route) {
+        Route old = new Route();
+        old.setService(route.getService());
+        old.setEnabled(route.isEnabled());
+        old.setForce(route.isForce());
+        old.setRuntime(route.isRuntime());
+        old.setPriority(route.getPriority());
+        String rule = parseCondition(route.getConditions());
+        old.setRule(rule);
+        return old;
+    }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/BaseController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/BaseController.java
deleted file mode 100644
index 41678fb..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/BaseController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.web.mvc;
-
-import com.alibaba.dubbo.common.logger.Logger;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.admin.governance.biz.common.i18n.MessageResourceService;
-import org.apache.dubbo.admin.governance.util.WebConstants;
-import org.apache.dubbo.admin.registry.common.domain.User;
-import org.apache.dubbo.admin.web.pulltool.RootContextPath;
-import org.apache.dubbo.admin.web.pulltool.Tool;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.ui.Model;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.regex.Pattern;
-
-public class BaseController {
-    protected static final Logger logger = LoggerFactory.getLogger(BaseController.class);
-
-    protected static final Pattern SPACE_SPLIT_PATTERN = Pattern.compile("\\s+");
-    //FIXME, to extract these auxiliary methods
-    protected String role = null;
-    protected String operator = null;
-    protected User currentUser = null;
-    protected String operatorAddress = null;
-    protected String currentRegistry = null;
-    @Autowired
-    private MessageResourceService messageResourceService;
-
-    @Autowired
-    protected Tool tool;
-
-    public void prepare(HttpServletRequest request, HttpServletResponse response, Model model,
-                        String methodName, String type) {
-        if (request.getSession().getAttribute(WebConstants.CURRENT_USER_KEY) != null) {
-            User user = (User) request.getSession().getAttribute(WebConstants.CURRENT_USER_KEY);
-            currentUser = user;
-            operator = user.getUsername();
-            role = user.getRole();
-            request.getSession().setAttribute(WebConstants.CURRENT_USER_KEY, user);
-        }
-        operatorAddress = request.getRemoteHost();
-        request.getMethod();
-        model.addAttribute("operator", operator);
-        model.addAttribute("operatorAddress", operatorAddress);
-
-        model.addAttribute("currentRegistry", currentRegistry);
-        model.addAttribute("rootContextPath", new RootContextPath(request.getContextPath()));
-        model.addAttribute("tool", tool);
-        model.addAttribute("_method", methodName);
-        model.addAttribute("helpUrl", WebConstants.HELP_URL);
-        model.addAttribute("_type", type);
-
-    }
-
-    public String getMessage(String key, Object... args) {
-        return messageResourceService.getMessage(key, args);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/RouterController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/RouterController.java
deleted file mode 100644
index 0a9a22c..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/RouterController.java
+++ /dev/null
@@ -1,344 +0,0 @@
-///*
-// * 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 com.alibaba.com.alibaba.dubboadmin.web.mvc;
-//
-//import java.lang.reflect.Method;
-//import java.util.Map;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//
-//import com.alibaba.com.alibaba.dubboadmin.SpringUtil;
-//import com.alibaba.com.alibaba.dubboadmin.governance.util.WebConstants;
-//import com.alibaba.com.alibaba.dubboadmin.web.mvc.governance.ServicesController;
-//
-//import org.apache.commons.lang.StringUtils;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.web.bind.annotation.PathVariable;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//
-//@Controller
-//public class RouterController {
-//
-//    @Autowired
-//    ServicesController servicesController;
-//
-//    private boolean isPrimitive(Class<?> cls) {
-//        return cls.isPrimitive() || cls == Boolean.class || cls == Byte.class
-//            || cls == Character.class || cls == Short.class || cls == Integer.class
-//            || cls == Long.class || cls == Float.class || cls == Double.class
-//            || cls == String.class;
-//    }
-//
-//    private Object convertPrimitive(Class<?> cls, String value) {
-//        if (cls == boolean.class || cls == Boolean.class) {
-//            return value == null || value.length() == 0 ? false : Boolean.valueOf(value);
-//        } else if (cls == byte.class || cls == Byte.class) {
-//            return value == null || value.length() == 0 ? 0 : Byte.valueOf(value);
-//        } else if (cls == char.class || cls == Character.class) {
-//            return value == null || value.length() == 0 ? '\0' : value.charAt(0);
-//        } else if (cls == short.class || cls == Short.class) {
-//            return value == null || value.length() == 0 ? 0 : Short.valueOf(value);
-//        } else if (cls == int.class || cls == Integer.class) {
-//            return value == null || value.length() == 0 ? 0 : Integer.valueOf(value);
-//        } else if (cls == long.class || cls == Long.class) {
-//            return value == null || value.length() == 0 ? 0 : Long.valueOf(value);
-//        } else if (cls == float.class || cls == Float.class) {
-//            return value == null || value.length() == 0 ? 0 : Float.valueOf(value);
-//        } else if (cls == double.class || cls == Double.class) {
-//            return value == null || value.length() == 0 ? 0 : Double.valueOf(value);
-//        }
-//        return value;
-//    }
-//
-//    //address mapping
-//    @RequestMapping("/governance/addresses/{ip:[0-9.]+:?[0-9]+}/{type}")
-//    public String addressRouter(@PathVariable("ip") String ip, @PathVariable("type") String type,
-//                                HttpServletRequest request, HttpServletResponse response, Model model) {
-//        model.addAttribute("address", ip);
-//        return appRouter(null, "addresses", ip, type, request, response, model);
-//    }
-//
-//    @RequestMapping("/governance/addresses/{ip:[0-9.]+:?[0-9]+}/{type}/{action}")
-//    public String addresswithIDRouter(@RequestParam Map<String, String> params, @PathVariable("ip") String ip, @PathVariable("type") String type,
-//                                      @PathVariable("action") String action, HttpServletRequest request,
-//                                      HttpServletResponse response, Model model) {
-//        model.addAttribute("address", ip);
-//        return appAction(params, null, "addresses",ip, type, action, request, response, model);
-//    }
-//
-//    @RequestMapping("/governance/addresses/{ip:[0-9.]+:?[0-9]+}/{type}/{id}/{action}")
-//    public String addressWithIDandAction(@PathVariable("ip") String ip, @PathVariable("type") String type,
-//                                         @PathVariable("id") String id, @PathVariable("action") String action,
-//                                         HttpServletRequest request, HttpServletResponse response, Model model) {
-//        model.addAttribute("address", ip);
-//        return appActionWithIdandAction(null, null, type, id, action, request, response, model);
-//    }
-//
-//
-//    // service mapping
-//    @RequestMapping("/governance/services/{service}/{type}")
-//    public String servicerRouter(@PathVariable("service") String service, @PathVariable("type") String type,
-//                                 HttpServletRequest request, HttpServletResponse response, Model model) {
-//        model.addAttribute("service", service);
-//        return appRouter(null, "services", service, type, request, response, model);
-//    }
-//
-//    @RequestMapping("/governance/services/{service}/{type}/{action}")
-//    public String serviceAction(@RequestParam Map<String, String> param,
-//                                @PathVariable("service") String service, @PathVariable("type") String type,
-//                                @PathVariable("action") String action, HttpServletRequest request,
-//                                HttpServletResponse response, Model model) {
-//        for (Map.Entry<String, String> entry : param.entrySet()) {
-//            System.out.println("key: " + entry.getKey());
-//            System.out.println("value: " + entry.getValue());
-//        }
-//        model.addAttribute("service", service);
-//        return appAction(param, null, "services", service, type, action, request, response, model);
-//    }
-//
-//    @RequestMapping("/governance/services/{service}/{type}/{id}/{action}")
-//    public String serviceActionWithId(@RequestParam Map<String, Object> param,
-//                                      @PathVariable("service") String service,
-//                                      @PathVariable("type") String type, @PathVariable("id") String id,
-//                                      @PathVariable("action") String action, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        String method = request.getMethod();
-//        String app = null;
-//        System.out.println("type: " + type);
-//        System.out.println("action: " + action);
-//        System.out.println("method: " + method);
-//        for (Map.Entry<String, Object> entry : param.entrySet()) {
-//            if (entry.getKey().equals("application")) {
-//                app = (String)entry.getValue();
-//            }
-//            System.out.println("key: " + entry.getKey());
-//            System.out.println("value: " + entry.getValue());
-//        }
-//        return appActionWithIdandAction(app, service, type, id, action, request, response, model);
-//    }
-//
-//    // app mapping all execute goes here
-//    //@RequestMapping("/governance/applications/{app}/services/{ids}/{action}")
-//    //public String serviceActionWithApp(@PathVariable("app") String app, @PathVariable("ids") String ids,
-//    //                                   @PathVariable("type") String type, HttpServletRequest request,
-//    //                                   HttpServletResponse response, Model model) {
-//    //    return "";
-//    //}
-//
-//    @RequestMapping("/governance/applications/{app}/{elements}/{element}/{type}")
-//    public String appRouter(@PathVariable("app") String app, @PathVariable("elements") String elements,
-//                            @PathVariable("element") String element, @PathVariable("type") String type,
-//                            HttpServletRequest request,
-//                            HttpServletResponse response, Model model) {
-//        if (app != null) {
-//            model.addAttribute("app", app);
-//        }
-//        if (StringUtils.isNumeric(element)) {
-//            //service action, shield, recover..
-//            Long[] ids = new Long[1];
-//            ids[0] = Long.valueOf(element);
-//            model.addAttribute("service", request.getParameter("service"));
-//            try {
-//                Method m = servicesController.getClass().getDeclaredMethod(type, Long[].class, HttpServletRequest.class,
-//                    HttpServletResponse.class, Model.class);
-//                Object result = m.invoke(servicesController, ids, request, response, model);
-//                return (String) result;
-//            } catch (Exception e) {
-//                e.printStackTrace();
-//            }
-//        }
-//        if (elements.equals("services")) {
-//            model.addAttribute("service", element);
-//        } else if (elements.equals("addresses")) {
-//            model.addAttribute("address", element);
-//        }
-//
-//        String name = WebConstants.mapper.get(type);
-//        if (name != null) {
-//            Object controller = SpringUtil.getBean(name);
-//            if (controller != null) {
-//                try {
-//                    Method index =  controller.getClass().getDeclaredMethod("index", HttpServletRequest.class, HttpServletResponse.class,
-//                         Model.class);
-//                    Object result =  index.invoke(controller, request, response, model);
-//                    return (String)result;
-//                } catch (Exception e) {
-//                    e.printStackTrace();
-//                }
-//            }
-//        }
-//        return "";
-//    }
-//
-//    @RequestMapping("/governance/applications/{app}/{type}")
-//    public String appWithService(@PathVariable("app") String app, @PathVariable("type") String type,
-//                                 HttpServletRequest request,
-//                                 HttpServletResponse response,
-//                                 Model model) {
-//        model.addAttribute("app", app);
-//        String name = WebConstants.mapper.get(type);
-//        if (name != null) {
-//            Object controller = SpringUtil.getBean(name);
-//            try {
-//                Method index = controller.getClass().getDeclaredMethod("index", HttpServletRequest.class,
-//                    HttpServletResponse.class, Model.class);
-//                Object result = index.invoke(controller, request, response, model);
-//                return (String) result;
-//            } catch (Exception e) {
-//                e.printStackTrace();
-//            }
-//
-//        }
-//        return "";
-//    }
-//
-//
-//    @RequestMapping("/governance/applications/{app}/{elements}/{element}/{type}/{action}")
-//    public String appAction(@RequestParam Map<String, String> params, @PathVariable("app") String app,
-//                            @PathVariable("elements") String elements, @PathVariable("element") String element,
-//                            @PathVariable("type") String type, @PathVariable("action") String action,
-//                            HttpServletRequest request, HttpServletResponse response, Model model) {
-//        if (app != null) {
-//            model.addAttribute("app", app);
-//        }
-//        if (elements.equals("services")) {
-//            model.addAttribute("service", element);
-//        } else if (elements.equals("addresses")) {
-//            model.addAttribute("address", element);
-//        }
-//
-//        String name = WebConstants.mapper.get(type);
-//        if (name != null) {
-//            Object controller = SpringUtil.getBean(name);
-//            if (controller != null) {
-//                if (request.getMethod().equals("POST")) {
-//                    Method[] methods = controller.getClass().getDeclaredMethods();
-//                    for (Method method : methods) {
-//                        if (method.getName().equals(action)) {
-//                            Class<?> param = method.getParameterTypes()[0];
-//                            try {
-//                                if (!param.isAssignableFrom(HttpServletRequest.class)) {
-//                                    Object value = param.newInstance();
-//                                    Method[] mms = param.getDeclaredMethods();
-//                                    for (Method m : mms) {
-//                                        if (m.getName().toLowerCase().startsWith("set")) {
-//                                            String methodName = m.getName();
-//                                            String key = methodName.substring(3).toLowerCase();
-//                                            String tmp = params.get(key);
-//                                            Object obj = tmp;
-//                                            if (tmp != null) {
-//                                                Class<?> t = m.getParameterTypes()[0];
-//                                                if (isPrimitive(t)) {
-//                                                    obj = convertPrimitive(t, tmp);
-//                                                }
-//                                                m.invoke(value, obj);
-//                                            }
-//
-//                                        }
-//                                    }
-//                                    return (String)method.invoke(controller, value, request, response, model);
-//                                } else {
-//                                    return (String)method.invoke(controller, request, response, model);
-//                                }
-//                            } catch (Exception e) {
-//                                e.printStackTrace();
-//                            }
-//
-//
-//                        }
-//                    }
-//                } else {
-//                    try {
-//                        if (StringUtils.isNumeric(action)) {
-//                            // action is id, call show method
-//                            Method show =  controller.getClass().getDeclaredMethod("show", Long.class, HttpServletRequest.class, HttpServletResponse.class,
-//                                Model.class);
-//                            Object result =  show.invoke(controller, Long.valueOf(action), request, response, model);
-//                            return (String)result;
-//                        } else {
-//                            Method m = controller.getClass().getDeclaredMethod(action, HttpServletRequest.class,
-//                                HttpServletResponse.class,
-//                                Model.class);
-//                            Object result =  m.invoke(controller, request, response, model);
-//                            return (String)result;
-//                        }
-//                    } catch (Exception e) {
-//                        e.printStackTrace();
-//                    }
-//                }
-//            }
-//        }
-//        return "";
-//    }
-//
-//
-//    @RequestMapping("/governance/applications/{app}/services/{service}/{type}/{id}/{action}")
-//    public String appActionWithIdandAction(@PathVariable("app") String app, @PathVariable("service") String service,
-//                               @PathVariable("type") String type, @PathVariable("id") String id,
-//                               @PathVariable("action") String action,
-//                               HttpServletRequest request, HttpServletResponse response, Model model) {
-//        if (app != null) {
-//            model.addAttribute("app", app);
-//        }
-//        model.addAttribute("service", service);
-//        String name = WebConstants.mapper.get(type);
-//        if (name != null) {
-//            Object controller = SpringUtil.getBean(name);
-//            if (controller != null) {
-//                try {
-//                    Object result = null;
-//                    if (StringUtils.isNumeric(id)) {
-//                        //single id
-//                        Method m = null;
-//                        try {
-//                            m = controller.getClass().getDeclaredMethod(action, Long.class, HttpServletRequest.class,
-//                                HttpServletResponse.class, Model.class);
-//                            result = m.invoke(controller, Long.valueOf(id), request, response, model);
-//                        } catch (NoSuchMethodException e) {
-//                            m = controller.getClass().getDeclaredMethod(action, Long[].class, HttpServletRequest.class,
-//                                HttpServletResponse.class, Model.class);
-//                            result = m.invoke(controller, new Long[]{Long.valueOf(id)}, request, response, model);
-//
-//                        }
-//                    } else {
-//                        //id array
-//                        String[] array = id.split(",");
-//                        Long[] ids = new Long[array.length];
-//                        for (int i = 0; i < array.length; i ++) {
-//                            ids[i] = Long.valueOf(array[i]);
-//                        }
-//
-//                        Method m = controller.getClass().getDeclaredMethod(action, Long[].class, HttpServletRequest.class,
-//                            HttpServletResponse.class, Model.class);
-//
-//                        result = m.invoke(controller, ids, request, response, model);
-//                    }
-//                    return (String)result;
-//                } catch (Exception e) {
-//                    e.printStackTrace();
-//                }
-//            }
-//        }
-//        return "";
-//
-//    }
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/common/auth/DubboUser.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/common/auth/DubboUser.java
deleted file mode 100644
index acf9e7f..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/common/auth/DubboUser.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.web.mvc.common.auth;
-
-import org.apache.dubbo.admin.registry.common.domain.User;
-
-import java.io.Serializable;
-
-/**
- * MinasUser: DubboUser
- *
- */
-public class DubboUser implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    private static final ThreadLocal<User> userHolder = new ThreadLocal<User>();
-
-    private DubboUser() {
-    }
-
-    public static final User getCurrentUser() {
-        return (User) userHolder.get();
-    }
-
-    public static final void setCurrentUser(User user) {
-        userHolder.set(user);
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/AddressesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/AddressesController.java
deleted file mode 100644
index 8e520ba..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/AddressesController.java
+++ /dev/null
@@ -1,66 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import org.apache.dubbo.admin.governance.service.ConsumerService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.registry.common.domain.Consumer;
-//import org.apache.dubbo.admin.registry.common.domain.Provider;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.util.List;
-//
-///**
-// * ProvidersController.
-// * URI: /services/$service/providers
-// *
-// */
-//@Controller
-//@RequestMapping("/governance/addresses")
-//public class AddressesController extends BaseController {
-//
-//    @Autowired
-//    private ProviderService providerService;
-//
-//    @Autowired
-//    private ConsumerService consumerService;
-//
-//    @Autowired
-//    ServicesController servicesController;
-//
-//
-//    @RequestMapping("")
-//    public String index(@RequestParam String ip, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "index", "addresses");
-//        List<Provider> providers = null;
-//        List<Consumer> consumers = null;
-//        providers = providerService.findByAddress(ip);
-//        consumers = consumerService.findByAddress(ip);
-//
-//        model.addAttribute("providers", providers);
-//        model.addAttribute("consumers", consumers);
-//        return "";
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/LoadbalancesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/LoadbalancesController.java
deleted file mode 100644
index fe2bda8..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/LoadbalancesController.java
+++ /dev/null
@@ -1,189 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import com.alibaba.dubbo.common.utils.CollectionUtils;
-//import org.apache.dubbo.admin.governance.service.OverrideService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.registry.common.domain.LoadBalance;
-//import org.apache.dubbo.admin.registry.common.domain.Provider;
-//import org.apache.dubbo.admin.registry.common.util.OverrideUtils;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.apache.dubbo.admin.web.pulltool.Tool;
-//import org.apache.commons.lang3.StringUtils;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.validation.support.BindingAwareModelMap;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.util.ArrayList;
-//import java.util.List;
-//
-///**
-// * ProvidersController.
-// * URI: /services/$service/loadbalances
-// *
-// */
-//@Controller
-//@RequestMapping("/governance/loadbalances")
-//public class LoadbalancesController extends BaseController {
-//
-//    @Autowired
-//    private OverrideService overrideService;
-//
-//    @Autowired
-//    private ProviderService providerService;
-//
-//    @RequestMapping("")
-//    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "index", "loadbalances");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//        service = StringUtils.trimToNull(service);
-//
-//        List<LoadBalance> loadbalances;
-//        if (service != null && service.length() > 0) {
-//            loadbalances = OverrideUtils.overridesToLoadBalances(overrideService.findByService(service));
-//        } else {
-//            loadbalances = OverrideUtils.overridesToLoadBalances(overrideService.findAll());
-//        }
-//        model.addAttribute("loadbalances", loadbalances);
-//        return "governance/screen/loadbalances/index";
-//    }
-//
-//    @RequestMapping("/detail")
-//    public String show(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "show", "loadbalances");
-//        LoadBalance loadbalance = OverrideUtils.overrideToLoadBalance(overrideService.findById(id));
-//        model.addAttribute("loadbalance", loadbalance);
-//        return "governance/screen/loadbalances/show";
-//    }
-//
-//    @RequestMapping("/add")
-//    public String add(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "add", "loadbalances");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//
-//        if (service != null && service.length() > 0 && !service.contains("*")) {
-//            List<Provider> providerList = providerService.findByService(service);
-//            List<String> addressList = new ArrayList<String>();
-//            for (Provider provider : providerList) {
-//                addressList.add(provider.getUrl().split("://")[1].split("/")[0]);
-//            }
-//            model.addAttribute("addressList", addressList);
-//            model.addAttribute("service", service);
-//            model.addAttribute("methods", CollectionUtils.sort(providerService.findMethodsByService(service)));
-//        } else {
-//            List<String> serviceList = Tool.sortSimpleName(providerService.findServices());
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//        //if (input != null) model.addAttribute("input", input);
-//        return "governance/screen/loadbalances/add";
-//    }
-//
-//    @RequestMapping("/edit")
-//    public String edit(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "edit", "loadbalances");
-//        String service = request.getParameter("service");
-//        String input = request.getParameter("input");
-//
-//        if (service != null && service.length() > 0 && !service.contains("*")) {
-//            List<Provider> providerList = providerService.findByService(service);
-//            List<String> addressList = new ArrayList<String>();
-//            for (Provider provider : providerList) {
-//                addressList.add(provider.getUrl().split("://")[1].split("/")[0]);
-//            }
-//            model.addAttribute("addressList", addressList);
-//            model.addAttribute("service", service);
-//            model.addAttribute("methods", CollectionUtils.sort(providerService.findMethodsByService(service)));
-//        } else {
-//            List<String> serviceList = Tool.sortSimpleName(providerService.findServices());
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//        if (input != null) model.addAttribute("input", input);
-//        LoadBalance loadbalance = OverrideUtils.overrideToLoadBalance(overrideService.findById(id));
-//        model.addAttribute("loadbalance", loadbalance);
-//        return "governance/screen/loadbalances/edit";
-//    }
-//
-//    @RequestMapping("/create")
-//    public String create(LoadBalance loadBalance, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "create", "loadbalances");
-//        boolean success = true;
-//        if (!super.currentUser.hasServicePrivilege(loadBalance.getService())) {
-//            model.addAttribute("message", getMessage("HaveNoServicePrivilege", loadBalance.getService()));
-//            success = false;
-//        } else {
-//            loadBalance.setUsername((String) ((BindingAwareModelMap)model).get("operator"));
-//            overrideService.saveOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../loadbalances");
-//        return "governance/screen/redirect";
-//    }
-//
-//
-//    @RequestMapping("/update")
-//    public String update(LoadBalance loadBalance, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "update", "loadbalances");
-//        boolean success = true;
-//        if (!super.currentUser.hasServicePrivilege(loadBalance.getService())) {
-//            model.addAttribute("message", getMessage("HaveNoServicePrivilege", loadBalance.getService()));
-//            success = false;
-//        } else {
-//            overrideService.updateOverride(OverrideUtils.loadBalanceToOverride(loadBalance));
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../loadbalances");
-//        return "governance/screen/redirect";
-//
-//    }
-//
-//    /**
-//     *
-//     * @param ids
-//     * @return
-//     */
-//    @RequestMapping("/delete")
-//    public String delete(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "delete", "loadbalances");
-//        boolean success = true;
-//        for (Long id : ids) {
-//            LoadBalance lb = OverrideUtils.overrideToLoadBalance(overrideService.findById(id));
-//            if (!super.currentUser.hasServicePrivilege(lb.getService())) {
-//                model.addAttribute("message", getMessage("HaveNoServicePrivilege", lb.getService()));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../loadbalances");
-//                return "governance/screen/redirect";
-//            }
-//        }
-//
-//        for (Long id : ids) {
-//            overrideService.deleteOverride(id);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../loadbalances");
-//        return "governance/screen/redirect";
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/OverridesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/OverridesController.java
deleted file mode 100644
index 8bf7f1d..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/OverridesController.java
+++ /dev/null
@@ -1,434 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import org.apache.dubbo.admin.registry.common.domain.Override;
-//import com.alibaba.dubbo.common.URL;
-//import com.alibaba.dubbo.common.utils.CollectionUtils;
-//import com.alibaba.dubbo.common.utils.StringUtils;
-//import org.apache.dubbo.admin.governance.service.ConsumerService;
-//import org.apache.dubbo.admin.governance.service.OverrideService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.validation.support.BindingAwareModelMap;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.util.*;
-//import java.util.Map.Entry;
-//import java.util.regex.Matcher;
-//import java.util.regex.Pattern;
-//
-//@Controller
-//@RequestMapping("/governance/overrides")
-//public class OverridesController extends BaseController {
-//    static final Pattern AND = Pattern.compile("\\&");
-//    static final Pattern EQUAL = Pattern.compile("([^=\\s]*)\\s*=\\s*(\\S*)");
-//    static final String DEFAULT_MOCK_JSON_KEY = "mock";
-//    static final String MOCK_JSON_KEY_POSTFIX = ".mock";
-//    static final String FORM_OVERRIDE_KEY = "overrideKey";
-//    static final String FORM_OVERRIDE_VALUE = "overrideValue";
-//    static final String FORM_DEFAULT_MOCK_METHOD_FORCE = "mockDefaultMethodForce";
-//    static final String FORM_DEFAULT_MOCK_METHOD_JSON = "mockDefaultMethodJson";
-//    static final String FORM_ORIGINAL_METHOD_FORCE_PREFIX = "mockMethodForce.";
-//    static final String FORM_ORIGINAL_METHOD_PREFIX = "mockMethod.";
-//    static final String FORM_DYNAMIC_METHOD_NAME_PREFIX = "mockMethodName";
-//    static final String FORM_DYNAMIC_METHOD_FORCE_PREFIX = "mockMethodForce";
-//    static final String FORM_DYNAMIC_METHOD_JSON_PREFIX = "mockMethodJson";
-//    @Autowired
-//    private OverrideService overrideService;
-//
-//    // FORM KEY
-//    @Autowired
-//    private ProviderService providerService;
-//    @Autowired
-//    private ConsumerService consumerService;
-//
-//    static Map<String, String> parseQueryString(String query) {
-//        HashMap<String, String> ret = new HashMap<String, String>();
-//        if (query == null || (query = query.trim()).length() == 0) return ret;
-//
-//        String[] kvs = AND.split(query);
-//        for (String kv : kvs) {
-//            Matcher matcher = EQUAL.matcher(kv);
-//            if (!matcher.matches()) continue;
-//            String key = matcher.group(1);
-//            String value = matcher.group(2);
-//            ret.put(key, value);
-//        }
-//
-//        return ret;
-//    }
-//
-//    @RequestMapping("")
-//    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "index", "overrides");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//        String application = (String)newModel.get("app");
-//        String address = (String)newModel.get("address");
-//        List<Override> overrides;
-//        if (StringUtils.isNotEmpty(service)) {
-//            overrides = overrideService.findByService(service);
-//        } else if (StringUtils.isNotEmpty(application)) {
-//            overrides = overrideService.findByApplication(application);
-//        } else if (StringUtils.isNotEmpty(address)) {
-//            overrides = overrideService.findByAddress(address);
-//        } else {
-//            overrides = overrideService.findAll();
-//        }
-//        model.addAttribute("overrides", overrides);
-//        return "governance/screen/overrides/index";
-//    }
-//
-//    @RequestMapping("/detail")
-//    public String show(@RequestParam Long id, HttpServletRequest request, HttpServletResponse response,
-//                       Model model) {
-//        prepare(request, response, model, "show", "overrides");
-//        Override override = overrideService.findById(id);
-//
-//        Map<String, String> parameters = parseQueryString(override.getParams());
-//
-//        if (parameters.get(DEFAULT_MOCK_JSON_KEY) != null) {
-//            String mock = URL.decode(parameters.get(DEFAULT_MOCK_JSON_KEY));
-//            String[] tokens = parseMock(mock);
-//            model.addAttribute(FORM_DEFAULT_MOCK_METHOD_FORCE, tokens[0]);
-//            model.addAttribute(FORM_DEFAULT_MOCK_METHOD_JSON, tokens[1]);
-//            parameters.remove(DEFAULT_MOCK_JSON_KEY);
-//        }
-//
-//        Map<String, String> method2Force = new LinkedHashMap<String, String>();
-//        Map<String, String> method2Json = new LinkedHashMap<String, String>();
-//
-//        for (Iterator<Entry<String, String>> iterator = parameters.entrySet().iterator(); iterator.hasNext(); ) {
-//            Map.Entry<String, String> e = iterator.next();
-//            String key = e.getKey();
-//
-//            if (key.endsWith(MOCK_JSON_KEY_POSTFIX)) {
-//                String m = key.substring(0, key.length() - MOCK_JSON_KEY_POSTFIX.length());
-//                parseMock(m, e.getValue(), method2Force, method2Json);
-//                iterator.remove();
-//            }
-//        }
-//
-//        model.addAttribute("methodForces", method2Force);
-//        model.addAttribute("methodJsons", method2Json);
-//        model.addAttribute("parameters", parameters);
-//        model.addAttribute("override", override);
-//        return "governance/screen/overrides/show";
-//    }
-//
-//    @RequestMapping("/add")
-//    public String add(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model,"add", "overrides");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String application = (String)newModel.get("app");
-//        String service = (String)newModel.get("service");
-//        List<String> serviceList = new ArrayList<String>();
-//        List<String> applicationList = new ArrayList<String>();
-//        if (StringUtils.isNotEmpty(application)) {
-//            serviceList.addAll(providerService.findServicesByApplication(application));
-//            serviceList.addAll(consumerService.findServicesByApplication(application));
-//            model.addAttribute("serviceList", serviceList);
-//        } else if (StringUtils.isNotEmpty(service)) {
-//            applicationList.addAll(providerService.findApplicationsByServiceName(service));
-//            applicationList.addAll(consumerService.findApplicationsByServiceName(service));
-//            model.addAttribute("applicationList", applicationList);
-//        } else {
-//            serviceList.addAll(providerService.findServices());
-//            serviceList.addAll(consumerService.findServices());
-//            providerService.findServicesByApplication(application);
-//            consumerService.findServicesByApplication(application);
-//        }
-//        model.addAttribute("serviceList", serviceList);
-//
-//        if (StringUtils.isNotEmpty(service) && !service.contains("*")) {
-//            model.addAttribute("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(service))));
-//        }
-//        return "governance/screen/overrides/add";
-//    }
-//
-//    @RequestMapping("/edit")
-//    public String edit(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response,
-//                     Model model) {
-//        prepare(request, response, model, "edit", "overrides");
-//        Override override = overrideService.findById(id);
-//
-//        Map<String, String> parameters = parseQueryString(override.getParams());
-//
-//        if (parameters.get(DEFAULT_MOCK_JSON_KEY) != null) {
-//            String mock = URL.decode(parameters.get(DEFAULT_MOCK_JSON_KEY));
-//            String[] tokens = parseMock(mock);
-//            model.addAttribute(FORM_DEFAULT_MOCK_METHOD_FORCE, tokens[0]);
-//            model.addAttribute(FORM_DEFAULT_MOCK_METHOD_JSON, tokens[1]);
-//            parameters.remove(DEFAULT_MOCK_JSON_KEY);
-//        }
-//
-//        Map<String, String> method2Force = new LinkedHashMap<String, String>();
-//        Map<String, String> method2Json = new LinkedHashMap<String, String>();
-//
-//        List<String> methods = CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(override.getService())));
-//        if (methods != null && methods.isEmpty()) {
-//            for (String m : methods) {
-//                parseMock(m, parameters.get(m + MOCK_JSON_KEY_POSTFIX), method2Force, method2Json);
-//                parameters.remove(m + MOCK_JSON_KEY_POSTFIX);
-//            }
-//        }
-//        for (Iterator<Entry<String, String>> iterator = parameters.entrySet().iterator(); iterator.hasNext(); ) {
-//            Map.Entry<String, String> e = iterator.next();
-//            String key = e.getKey();
-//
-//            if (key.endsWith(MOCK_JSON_KEY_POSTFIX)) {
-//                String m = key.substring(0, key.length() - MOCK_JSON_KEY_POSTFIX.length());
-//                parseMock(m, e.getValue(), method2Force, method2Json);
-//                iterator.remove();
-//            }
-//        }
-//
-//        model.addAttribute("methods", methods);
-//        model.addAttribute("methodForces", method2Force);
-//        model.addAttribute("methodJsons", method2Json);
-//        model.addAttribute("parameters", parameters);
-//        model.addAttribute("override", override);
-//        return "governance/screen/overrides/edit";
-//    }
-//
-//    private void parseMock(String m, String mock, Map<String, String> method2Force, Map<String, String> method2Json) {
-//        String[] tokens = parseMock(mock);
-//        method2Force.put(m, tokens[0]);
-//        method2Json.put(m, tokens[1]);
-//    }
-//
-//    private String[] parseMock(String mock) {
-//        mock = URL.decode(mock);
-//        String force;
-//        if (mock.startsWith("force:")) {
-//            force = "force";
-//            mock = mock.substring("force:".length());
-//        } else if (mock.startsWith("fail:")) {
-//            force = "fail";
-//            mock = mock.substring("fail:".length());
-//        } else {
-//            force = "fail";
-//        }
-//        String[] tokens = new String[2];
-//        tokens[0] = force;
-//        tokens[1] = mock;
-//        return tokens;
-//    }
-//
-//    boolean catchParams(Override override, HttpServletRequest request, Model model) {
-//        Map<String, String[]> map = request.getParameterMap();
-//        String service = map.get("service")[0];
-//        if (service == null || service.trim().length() == 0) {
-//            model.addAttribute("message", getMessage("service is blank!"));
-//            return false;
-//        }
-//        if (!super.currentUser.hasServicePrivilege(service)) {
-//            model.addAttribute("message", getMessage("HaveNoServicePrivilege", service));
-//            return false;
-//        }
-//
-//        String defaultMockMethodForce = map.get(FORM_DEFAULT_MOCK_METHOD_FORCE)[0];
-//        String defaultMockMethodJson = map.get(FORM_DEFAULT_MOCK_METHOD_JSON)[0];
-//
-//        Map<String, String> override2Value = new HashMap<String, String>();
-//        Map<String, String> method2Json = new HashMap<String, String>();
-//
-//        for (Map.Entry<String, String[]> param : map.entrySet()) {
-//            String key = param.getKey().trim();
-//            if(param.getValue().length != 1) continue;;
-//
-//            String value = param.getValue()[0];
-//
-//            if (key.startsWith(FORM_OVERRIDE_KEY) && value != null && value.trim().length() > 0) {
-//                String index = key.substring(FORM_OVERRIDE_KEY.length());
-//                String overrideValue = map.get(FORM_OVERRIDE_VALUE + index)[0];
-//                if (overrideValue != null && overrideValue.trim().length() > 0) {
-//                    override2Value.put(value.trim(), overrideValue.trim());
-//                }
-//            }
-//
-//            if (key.startsWith(FORM_ORIGINAL_METHOD_PREFIX) && value != null && value.trim().length() > 0) {
-//                String method = key.substring(FORM_ORIGINAL_METHOD_PREFIX.length());
-//                String force = map.get(FORM_ORIGINAL_METHOD_FORCE_PREFIX + method)[0];
-//                method2Json.put(method, force + ":" + value.trim());
-//            }
-//
-//            if (key.startsWith(FORM_DYNAMIC_METHOD_NAME_PREFIX) && value != null && value.trim().length() > 0) {
-//                String index = key.substring(FORM_DYNAMIC_METHOD_NAME_PREFIX.length());
-//                String force = map.get(FORM_DYNAMIC_METHOD_FORCE_PREFIX + index)[0];
-//                String json =  map.get(FORM_DYNAMIC_METHOD_JSON_PREFIX + index)[0];
-//
-//                if (json != null && json.trim().length() > 0) {
-//                    method2Json.put(value.trim(), force + ":" + json.trim());
-//                }
-//            }
-//        }
-//
-//        StringBuilder paramters = new StringBuilder();
-//        boolean isFirst = true;
-//        if (defaultMockMethodJson != null && defaultMockMethodJson.trim().length() > 0) {
-//            paramters.append("mock=").append(URL.encode(defaultMockMethodForce + ":" + defaultMockMethodJson.trim()));
-//            isFirst = false;
-//        }
-//        for (Map.Entry<String, String> e : method2Json.entrySet()) {
-//            if (isFirst) isFirst = false;
-//            else paramters.append("&");
-//
-//            paramters.append(e.getKey()).append(MOCK_JSON_KEY_POSTFIX).append("=").append(URL.encode(e.getValue()));
-//        }
-//        for (Map.Entry<String, String> e : override2Value.entrySet()) {
-//            if (isFirst) isFirst = false;
-//            else paramters.append("&");
-//
-//            paramters.append(e.getKey()).append("=").append(URL.encode(e.getValue()));
-//        }
-//
-//        String p = paramters.toString();
-//        if (p.trim().length() == 0) {
-//            model.addAttribute("message", getMessage("Please enter Parameters!"));
-//            return false;
-//        }
-//
-//        override.setParams(p);
-//        return true;
-//    }
-//
-//
-//    @RequestMapping("/create")
-//    public String create(Override override, HttpServletRequest request,
-//                         HttpServletResponse response, Model model) {
-//        prepare(request,response,model,"update", "overrides");
-//        boolean success = true;
-//        if (!catchParams(override, request, model)) {
-//            success =false;
-//        } else {
-//            overrideService.saveOverride(override);
-//        }
-//
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../overrides");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/update")
-//    public String update(Override override, HttpServletRequest request,
-//                         HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "update", "overrides");
-//        boolean  succcess = true;
-//        Override o = overrideService.findById(override.getId());
-//        override.setService(o.getService());
-//        override.setAddress(o.getAddress());
-//        override.setApplication(o.getApplication());
-//
-//        if (!catchParams(override, request, model)) {
-//            succcess = false;
-//        } else {
-//            overrideService.updateOverride(override);
-//        }
-//
-//        model.addAttribute("success", succcess);
-//        model.addAttribute("redirect", "../overrides");
-//        return "governance/screen/redirect";
-//
-//    }
-//
-//    @RequestMapping("/delete")
-//    public String delete(@RequestParam("ids") Long[] ids, HttpServletRequest request,
-//                              HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "delete", "overrides");
-//        for (Long id : ids) {
-//            overrideService.deleteOverride(id);
-//        }
-//
-//        model.addAttribute("success", true);
-//        model.addAttribute("redirect", "../../overrides");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/enable")
-//    public String enable(@RequestParam("ids") Long[] ids, HttpServletRequest request,
-//                          HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "enable", "overrides");
-//        boolean success = true;
-//        for (Long id : ids) {
-//            Override override = overrideService.findById(id);
-//            if (override == null) {
-//                model.addAttribute("message", getMessage("NoSuchOperationData", id));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../overrides");
-//                return "governance/screen/redirect";
-//            } else {
-//                if (!super.currentUser.hasServicePrivilege(override.getService())) {
-//                    model.addAttribute("message", getMessage("HaveNoServicePrivilege", override.getService()));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../overrides");
-//                    return "governance/screen/redirect";
-//                }
-//            }
-//        }
-//
-//        for (Long id : ids) {
-//            overrideService.enableOverride(id);
-//        }
-//
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../overrides");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/disable")
-//    public String disable(@RequestParam("ids") Long[] ids, HttpServletRequest request,
-//                           HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "disable", "overrides");
-//        boolean success = true;
-//        for (Long id : ids) {
-//            Override override = overrideService.findById(id);
-//            if (override == null) {
-//                model.addAttribute("message", getMessage("NoSuchOperationData", id));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../overrides");
-//                return "governance/screen/redirect";
-//            } else {
-//                if (!super.currentUser.hasServicePrivilege(override.getService())) {
-//                    model.addAttribute("message", getMessage("HaveNoServicePrivilege", override.getService()));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../overrides");
-//                    return "governance/screen/redirect";
-//                }
-//            }
-//        }
-//
-//        for (Long id : ids) {
-//            overrideService.disableOverride(id);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../overrides");
-//        return "governance/screen/redirect";
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/OwnersController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/OwnersController.java
deleted file mode 100644
index 083269e..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/OwnersController.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.web.mvc.governance;
-
-import org.apache.dubbo.admin.governance.service.OwnerService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.registry.common.domain.Owner;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.apache.dubbo.admin.web.pulltool.Tool;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.validation.support.BindingAwareModelMap;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * ProvidersController. URI: /services/$service/owners
- *
- */
-@Controller
-@RequestMapping("/governance/owners")
-public class OwnersController extends BaseController {
-
-    @Autowired
-    private OwnerService ownerService;
-
-    @Autowired
-    private ProviderService providerService;
-
-    @RequestMapping("")
-    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-        prepare(request, response, model, "index", "owners");
-        List<Owner> owners;
-        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-        String service = (String)newModel.get("service");
-        if (service != null && service.length() > 0) {
-            owners = ownerService.findByService(service);
-        } else {
-            owners = ownerService.findAll();
-        }
-        model.addAttribute("owners", owners);
-        return "governance/screen/owners/index";
-    }
-
-    @RequestMapping("/add")
-    public String add(HttpServletRequest request, HttpServletResponse response, Model model) {
-        prepare(request, response, model, "add", "owners");
-        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-        String service = (String)newModel.get("service");
-        if (service == null || service.length() == 0) {
-            List<String> serviceList = Tool.sortSimpleName(new ArrayList<String>(providerService.findServices()));
-            model.addAttribute("serviceList", serviceList);
-        }
-        return "governance/screen/owners/add";
-    }
-
-    @RequestMapping(value =  "/create", method = RequestMethod.POST)  //post
-    public String create(Owner owner, HttpServletRequest request, HttpServletResponse response, Model model) {
-        prepare(request, response, model, "create", "owners");
-        String service = owner.getService();
-        String username = owner.getUsername();
-        if (service == null || service.length() == 0
-                || username == null || username.length() == 0) {
-            model.addAttribute("message", getMessage("NoSuchOperationData"));
-            model.addAttribute("success", false);
-            model.addAttribute("redirect", "../owners");
-            return "governance/screen/redirect";
-        }
-        if (!super.currentUser.hasServicePrivilege(service)) {
-            model.addAttribute("message", getMessage("HaveNoServicePrivilege", service));
-            model.addAttribute("success", false);
-            model.addAttribute("redirect", "../owners");
-            return "governance/screen/redirect";
-        }
-        ownerService.saveOwner(owner);
-        model.addAttribute("success", true);
-        model.addAttribute("redirect", "../owners");
-        return "governance/screen/redirect";
-    }
-
-    @RequestMapping("/delete")
-    public String delete(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) {
-        prepare(request, response, model, "delete", "owners");
-
-        String service = request.getParameter("service");
-        String username = request.getParameter("username");
-        Owner owner = new Owner();
-        owner.setService(service);
-        owner.setUsername(username);
-        if (service == null || service.length() == 0
-                || username == null || username.length() == 0) {
-            model.addAttribute("message", getMessage("NoSuchOperationData"));
-            model.addAttribute("success", false);
-            model.addAttribute("redirect", "../../owners");
-            return "governance/screen/redirect";
-        }
-        if (!super.currentUser.hasServicePrivilege(service)) {
-            model.addAttribute("message", getMessage("HaveNoServicePrivilege", service));
-            model.addAttribute("success", false);
-            model.addAttribute("redirect", "../../owners");
-            return "governance/screen/redirect";
-        }
-        ownerService.deleteOwner(owner);
-        model.addAttribute("success", true);
-        model.addAttribute("redirect", "../../owners");
-        return "governance/screen/redirect";
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/RoutesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/RoutesController.java
deleted file mode 100644
index 9432736..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/RoutesController.java
+++ /dev/null
@@ -1,555 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import com.alibaba.dubbo.common.utils.CollectionUtils;
-//import com.alibaba.dubbo.common.utils.StringUtils;
-//import org.apache.dubbo.admin.governance.service.ConsumerService;
-//import org.apache.dubbo.admin.governance.service.OwnerService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.governance.service.RouteService;
-//import org.apache.dubbo.admin.registry.common.domain.Route;
-//import org.apache.dubbo.admin.registry.common.route.ParseUtils;
-//import org.apache.dubbo.admin.registry.common.route.RouteRule;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.apache.dubbo.admin.web.pulltool.Tool;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.validation.support.BindingAwareModelMap;
-//import org.springframework.web.bind.annotation.PathVariable;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.text.ParseException;
-//import java.util.*;
-//
-///**
-// * ProvidersController.
-// * URI: /services/$service/routes
-// *
-// */
-//@Controller
-//@RequestMapping("/routing")
-//public class RoutesController extends BaseController {
-//
-//    private static final int MAX_RULE_LENGTH = 1000;
-//    static String[][] when_names = {
-//            {"method", "method", "unmethod"},
-//            {"consumer.application", "consumerApplication", "unconsumerApplication"},
-//            {"consumer.cluster", "consumerCluster", "unconsumerCluster"},
-//            {"consumer.host", "consumerHost", "unconsumerHost"},
-//            {"consumer.version", "consumerVersion", "unconsumerVersion"},
-//            {"consumer.group", "consumerGroup", "unconsumerGroup"},
-//    };
-//    static String[][] then_names = {
-//            {"provider.application", "providerApplication", "unproviderApplication"},
-//            {"provider.cluster", "providerCluster", "unproviderCluster"}, // Must check if Cluster exists
-//            {"provider.host", "providerHost", "unproviderHost"},
-//            {"provider.protocol", "providerProtocol", "unproviderProtocol"},
-//            {"provider.port", "providerPort", "unproviderPort"},
-//            {"provider.version", "providerVersion", "unproviderVersion"},
-//            {"provider.group", "providerGroup", "unproviderGroup"}
-//    };
-//    @Autowired
-//    private RouteService routeService;
-//    @Autowired
-//    private ProviderService providerService;
-//    @Autowired
-//    private ConsumerService consumerService;
-//
-//    static void checkService(String service) {
-//        if (service.contains(",")) throw new IllegalStateException("service(" + service + ") contain illegale ','");
-//
-//        String interfaceName = service;
-//        int gi = interfaceName.indexOf("/");
-//        if (gi != -1) interfaceName = interfaceName.substring(gi + 1);
-//        int vi = interfaceName.indexOf(':');
-//        if (vi != -1) interfaceName = interfaceName.substring(0, vi);
-//
-//        if (interfaceName.indexOf('*') != -1 && interfaceName.indexOf('*') != interfaceName.length() - 1) {
-//            throw new IllegalStateException("service(" + service + ") only allow 1 *, and must be last char!");
-//        }
-//    }
-//
-//    /**
-//     * add owners related with service
-//     *
-//     * @param usernames   the usernames to add
-//     * @param serviceName no wildcards
-//     */
-//    public static void addOwnersOfService(Set<String> usernames, String serviceName,
-//                                          OwnerService ownerDAO) {
-//        List<String> serviceNamePatterns = ownerDAO.findAllServiceNames();
-//        for (String p : serviceNamePatterns) {
-//            if (ParseUtils.isMatchGlobPattern(p, serviceName)) {
-//                List<String> list = ownerDAO.findUsernamesByServiceName(p);
-//                usernames.addAll(list);
-//            }
-//        }
-//    }
-//
-//    /**
-//     * add owners related with service pattern
-//     *
-//     * @param usernames          the usernames to add
-//     * @param serviceNamePattern service pattern, Glob
-//     */
-//    public static void addOwnersOfServicePattern(Set<String> usernames, String serviceNamePattern,
-//                                                 OwnerService ownerDAO) {
-//        List<String> serviceNamePatterns = ownerDAO.findAllServiceNames();
-//        for (String p : serviceNamePatterns) {
-//            if (ParseUtils.hasIntersection(p, serviceNamePattern)) {
-//                List<String> list = ownerDAO.findUsernamesByServiceName(p);
-//                usernames.addAll(list);
-//            }
-//        }
-//    }
-//
-//    /**
-//     * Routing module home page
-//     *
-//     */
-//    @RequestMapping("")
-//    public String index(@RequestParam(required = false) String service,
-//                        @RequestParam(required = false) String app,
-//                        HttpServletRequest request, HttpServletResponse response, Model model) {
-//        model.addAttribute("service", service);
-//        model.addAttribute("app", app);
-//        if (service != null) {
-//            model.addAttribute("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(service))));
-//        }  else {
-//            List<String> serviceList = Tool.sortSimpleName(new ArrayList<String>(providerService.findServices()));
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//        return "routingRules";
-//    }
-//
-//    /**
-//     * Display routing details
-//     *
-//     */
-//    @RequestMapping("/detail")
-//    public String show(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        try {
-//            prepare(request, response, model, "show", "routes");
-//            Route route = routeService.findRoute(id);
-//
-//            if (route == null) {
-//                throw new IllegalArgumentException("The route is not existed.");
-//            }
-//            if (route.getService() != null && !route.getService().isEmpty()) {
-//                model.addAttribute("service", route.getService());
-//            }
-//
-//            RouteRule routeRule = RouteRule.parse(route);
-//
-//            @SuppressWarnings("unchecked")
-//            Map<String, RouteRule.MatchPair>[] paramArray = new Map[]{
-//                    routeRule.getWhenCondition(), routeRule.getThenCondition()};
-//            String[][][] namesArray = new String[][][]{when_names, then_names};
-//
-//            for (int i = 0; i < paramArray.length; ++i) {
-//                Map<String, RouteRule.MatchPair> param = paramArray[i];
-//                String[][] names = namesArray[i];
-//                for (String[] name : names) {
-//                    RouteRule.MatchPair matchPair = param.get(name[0]);
-//                    if (matchPair == null) {
-//                        continue;
-//                    }
-//
-//                    if (!matchPair.getMatches().isEmpty()) {
-//                        String m = RouteRule.join(matchPair.getMatches());
-//                        model.addAttribute(name[1], m);
-//                    }
-//                    if (!matchPair.getUnmatches().isEmpty()) {
-//                        String u = RouteRule.join(matchPair.getUnmatches());
-//                        model.addAttribute(name[2], u);
-//                    }
-//                }
-//            }
-//            model.addAttribute("route", route);
-//            model.addAttribute("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(route.getService()))));
-//        } catch (ParseException e) {
-//            e.printStackTrace();
-//        }
-//        return "governance/screen/routes/show";
-//    }
-//
-//    /**
-//     * Load new route page
-//     *
-//     */
-//    @RequestMapping("/add")
-//    public String add(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "add", "routes");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//        if (service != null && service.length() > 0 && !service.contains("*")) {
-//            model.addAttribute("service", service);
-//            model.addAttribute("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(service))));
-//        } else {
-//            List<String> serviceList = Tool.sortSimpleName(new ArrayList<String>(providerService.findServices()));
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//
-//        //if (input != null) model.addAttribute("input", input);
-//        return "governance/screen/routes/add";
-//    }
-//
-//    /**
-//     * Load modified routing page
-//     *
-//     */
-//
-//    @RequestMapping("/edit")
-//    public String edit(@RequestParam("id") Long id, @RequestParam(required = false) String service,
-//                     @RequestParam(required = false) String input,
-//                     HttpServletRequest request, HttpServletResponse response, Model model) {
-//
-//        prepare(request, response, model, "edit", "routes");
-//        if (service != null && service.length() > 0 && !service.contains("*")) {
-//            model.addAttribute("service", service);
-//            model.addAttribute("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(service))));
-//        } else {
-//            List<String> serviceList = Tool.sortSimpleName(new ArrayList<String>(providerService.findServices()));
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//
-//        if (input != null) model.addAttribute("input", input);
-//        Route route = routeService.findRoute(id);
-//
-//        if (route == null) {
-//            throw new IllegalArgumentException("The route is not existed.");
-//        }
-//        if (route.getService() != null && !route.getService().isEmpty()) {
-//            model.addAttribute("service", route.getService());
-//        }
-//
-//        RouteRule routeRule = null;
-//        try {
-//            routeRule = RouteRule.parse(route);
-//        } catch (ParseException e) {
-//            e.printStackTrace();
-//        }
-//
-//        @SuppressWarnings("unchecked")
-//        Map<String, RouteRule.MatchPair>[] paramArray = new Map[]{
-//            routeRule.getWhenCondition(), routeRule.getThenCondition()};
-//        String[][][] namesArray = new String[][][]{when_names, then_names};
-//
-//        for (int i = 0; i < paramArray.length; ++i) {
-//            Map<String, RouteRule.MatchPair> param = paramArray[i];
-//            String[][] names = namesArray[i];
-//            for (String[] name : names) {
-//                RouteRule.MatchPair matchPair = param.get(name[0]);
-//                if (matchPair == null) {
-//                    continue;
-//                }
-//
-//                if (!matchPair.getMatches().isEmpty()) {
-//                    String m = RouteRule.join(matchPair.getMatches());
-//                    model.addAttribute(name[1], m);
-//                }
-//                if (!matchPair.getUnmatches().isEmpty()) {
-//                    String u = RouteRule.join(matchPair.getUnmatches());
-//                    model.addAttribute(name[2], u);
-//                }
-//            }
-//        }
-//        model.addAttribute("route", route);
-//        model.addAttribute("methods", CollectionUtils.sort(new ArrayList<String>(providerService.findMethodsByService(route.getService()))));
-//
-//        return "governance/screen/routes/edit";
-//    }
-//
-//    /**
-//     * Save the routing information to the database
-//     *
-//     * @return
-//     */
-//
-//    @RequestMapping("/create")
-//    public String create(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "update", "routes");
-//        boolean success = true;
-//
-//        String name = request.getParameter("name");
-//        String service = request.getParameter("service");
-//        if (StringUtils.isNotEmpty(service)
-//                && StringUtils.isNotEmpty(name)) {
-//            checkService(service);
-//
-//            Map<String, String> when_name2valueList = new HashMap<String, String>();
-//            Map<String, String> notWhen_name2valueList = new HashMap<String, String>();
-//            for (String[] names : when_names) {
-//                when_name2valueList.put(names[0],  request.getParameter(names[1]));
-//                notWhen_name2valueList.put(names[0], request.getParameter(names[2])); // TODO. We should guarantee value is never null in here, will be supported later
-//            }
-//
-//            Map<String, String> then_name2valueList = new HashMap<String, String>();
-//            Map<String, String> notThen_name2valueList = new HashMap<String, String>();
-//            for (String[] names : then_names) {
-//                then_name2valueList.put(names[0], request.getParameter(names[1]));
-//                notThen_name2valueList.put(names[0], request.getParameter(names[2]));
-//            }
-//
-//            RouteRule routeRule = RouteRule.createFromNameAndValueListString(
-//                    when_name2valueList, notWhen_name2valueList,
-//                    then_name2valueList, notThen_name2valueList);
-//
-//            if (routeRule.getThenCondition().isEmpty()) {
-//                model.addAttribute("message", getMessage("Add route error! then is empty."));
-//                model.addAttribute("success", false);
-//                model.addAttribute("redirect", "../routes");
-//                return "governance/screen/redirect";
-//            }
-//
-//            String matchRule = routeRule.getWhenConditionString();
-//            String filterRule = routeRule.getThenConditionString();
-//
-//            // Limit the length of the expression
-//            if (matchRule.length() > MAX_RULE_LENGTH) {
-//                model.addAttribute("message", getMessage("When rule is too long!"));
-//                model.addAttribute("success", false);
-//                model.addAttribute("redirect", "../routes");
-//                return "governance/screen/redirect";
-//            }
-//            if (filterRule.length() > MAX_RULE_LENGTH) {
-//                model.addAttribute("message", getMessage("Then rule is too long!"));
-//                model.addAttribute("success", false);
-//                model.addAttribute("redirect", "../routes");
-//                return "governance/screen/redirect";
-//            }
-//
-//            Route route = new Route();
-//            route.setService(service);
-//            route.setName(name);
-//            route.setUsername(request.getParameter("operator"));
-//            route.setOperator(request.getParameter("operatorAddress"));
-//            route.setRule(routeRule.toString());
-//            if (StringUtils.isNotEmpty(request.getParameter("priority"))) {
-//                route.setPriority(Integer.parseInt(request.getParameter("priority")));
-//            }
-//            routeService.createRoute(route);
-//
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../routes");
-//        return "governance/screen/redirect";
-//    }
-//
-//    /**
-//     * Save the update data to the database
-//     *
-//     * @return
-//     */
-//    @RequestMapping("/update")
-//    public String update(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "update", "routes");
-//        boolean success = true;
-//        String idStr = String.valueOf(id);
-//        if (idStr != null && idStr.length() > 0) {
-//            String[] blacks = request.getParameterMap().get("black");
-//            //String[] blacks = (String[]) context.get("black");
-//            boolean black = false;
-//            if (blacks != null && blacks.length > 0) {
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../routes");
-//                return "governance/screen/redirect";
-//            }
-//
-//            Route oldRoute = routeService.findRoute(Long.valueOf(idStr));
-//            if (null == oldRoute) {
-//                model.addAttribute("message", getMessage("NoSuchRecord"));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../routes");
-//                return "governance/screen/redirect";
-//            }
-//            // Check parameters, patchwork rule
-//            if (StringUtils.isNotEmpty((String) request.getParameter("name"))) {
-//                String service = oldRoute.getService();
-//                if (((BindingAwareModelMap)model).get("operator") == null) {
-//                    model.addAttribute("message", getMessage("HaveNoServicePrivilege", service));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../routes");
-//                    return "governance/screen/redirect";
-//                }
-//
-//                Map<String, String> when_name2valueList = new HashMap<String, String>();
-//                Map<String, String> notWhen_name2valueList = new HashMap<String, String>();
-//                for (String[] names : when_names) {
-//                    when_name2valueList.put(names[0], (String) request.getParameter(names[1]));
-//                    notWhen_name2valueList.put(names[0], (String) request.getParameter(names[2]));
-//                }
-//
-//                Map<String, String> then_name2valueList = new HashMap<String, String>();
-//                Map<String, String> notThen_name2valueList = new HashMap<String, String>();
-//                for (String[] names : then_names) {
-//                    then_name2valueList.put(names[0], (String) request.getParameter(names[1]));
-//                    notThen_name2valueList.put(names[0], (String) request.getParameter(names[2]));
-//                }
-//
-//                RouteRule routeRule = RouteRule.createFromNameAndValueListString(
-//                        when_name2valueList, notWhen_name2valueList,
-//                        then_name2valueList, notThen_name2valueList);
-//
-//                RouteRule result = null;
-//                if (black) {
-//                    RouteRule.MatchPair matchPair = routeRule.getThenCondition().get("black");
-//                    Map<String, RouteRule.MatchPair> then = null;
-//                    if (null == matchPair) {
-//                        matchPair = new RouteRule.MatchPair();
-//                        then = new HashMap<String, RouteRule.MatchPair>();
-//                        then.put("black", matchPair);
-//                    } else {
-//                        matchPair.getMatches().clear();
-//                    }
-//                    matchPair.getMatches().add(String.valueOf(black));
-//                    result = RouteRule.copyWithReplace(routeRule, null, then);
-//                }
-//
-//                if (result == null) {
-//                    result = routeRule;
-//                }
-//
-//                if (result.getThenCondition().isEmpty()) {
-//                    model.addAttribute("message", getMessage("Update route error! then is empty."));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../routes");
-//                    return "governance/screen/redirect";
-//                }
-//
-//                String matchRule = result.getWhenConditionString();
-//                String filterRule = result.getThenConditionString();
-//
-//                // Limit the length of the expression
-//                if (matchRule.length() > MAX_RULE_LENGTH) {
-//                    model.addAttribute("message", getMessage("When rule is too long!"));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../routes");
-//                    return "governance/screen/redirect";
-//                }
-//                if (filterRule.length() > MAX_RULE_LENGTH) {
-//                    model.addAttribute("message", getMessage("Then rule is too long!"));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../routes");
-//                    return "governance/screen/redirect";
-//                }
-//
-//                int priority = 0;
-//                if (StringUtils.isNotEmpty((String) request.getParameter("priority"))) {
-//                    priority = Integer.parseInt((String) request.getParameter("priority"));
-//                }
-//
-//                Route route = new Route();
-//                route.setRule(result.toString());
-//                route.setService(service);
-//                route.setPriority(priority);
-//                route.setName((String) request.getParameter("name"));
-//                route.setUsername((String) request.getParameter("operator"));
-//                route.setOperator((String) request.getParameter("operatorAddress"));
-//                route.setId(Long.valueOf(idStr));
-//                route.setPriority(Integer.parseInt((String) request.getParameter("priority")));
-//                route.setEnabled(oldRoute.isEnabled());
-//                routeService.updateRoute(route);
-//
-//                Set<String> usernames = new HashSet<String>();
-//                usernames.add((String) request.getParameter("operator"));
-//                usernames.add(route.getUsername());
-//                //RelateUserUtils.addOwnersOfService(usernames, route.getService(), ownerDAO);
-//
-//                Map<String, Object> params = new HashMap<String, Object>();
-//                params.put("action", "update");
-//                params.put("route", route);
-//
-//            } else {
-//                model.addAttribute("message", getMessage("MissRequestParameters", "name"));
-//            }
-//        } else {
-//            model.addAttribute("message", getMessage("MissRequestParameters", "id"));
-//        }
-//
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../routes");
-//        return "governance/screen/redirect";
-//    }
-//
-//    /**
-//     * Remove the route rule for the specified ID
-//     *
-//     * @param ids
-//     * @return
-//     */
-//    @RequestMapping("/{ids}/delete")
-//    public String delete(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response,
-//                          Model model) {
-//        prepare(request, response, model, "delete", "routes");
-//        for (Long id : ids) {
-//            routeService.deleteRoute(id);
-//        }
-//        model.addAttribute("success", true);
-//        model.addAttribute("redirect", "../../routes");
-//        return "governance/screen/redirect";
-//
-//    }
-//
-//    /**
-//     * Enable the specified route ID rules (batch processing)
-//     *
-//     * @param ids
-//     * @return
-//     */
-//    @RequestMapping("/{ids}/enable")
-//    public String enable(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response,
-//                          Model model) {
-//        prepare(request, response, model, "enable", "routes");
-//        for (Long id : ids) {
-//            routeService.enableRoute(id);
-//        }
-//        model.addAttribute("success", true);
-//        model.addAttribute("redirect", "../../routes");
-//        return "governance/screen/redirect";
-//    }
-//
-//    /**
-//     * Disabling route rules for specified IDs (can be batch processed)
-//     *
-//     * @param ids
-//     * @return
-//     */
-//    @RequestMapping("/{ids}/disable")
-//    public String disable(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response,
-//                           Model model) {
-//        prepare(request, response, model, "disable", "routes");
-//        for (Long id : ids) {
-//            routeService.disableRoute(id);
-//        }
-//        model.addAttribute("success", true);
-//        model.addAttribute("redirect", "../../routes");
-//        return "governance/screen/redirect";
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/ServiceDetailController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/ServiceDetailController.java
deleted file mode 100644
index 918bcc2..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/ServiceDetailController.java
+++ /dev/null
@@ -1,527 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import com.alibaba.dubbo.common.URL;
-//import com.alibaba.dubbo.common.utils.StringUtils;
-//import org.apache.dubbo.admin.governance.service.ConsumerService;
-//import org.apache.dubbo.admin.governance.service.OverrideService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.governance.service.RouteService;
-//import org.apache.dubbo.admin.registry.common.domain.Consumer;
-//import org.apache.dubbo.admin.registry.common.domain.Override;
-//import org.apache.dubbo.admin.registry.common.domain.Provider;
-//import org.apache.dubbo.admin.registry.common.domain.Route;
-//import org.apache.dubbo.admin.registry.common.route.OverrideUtils;
-//import org.apache.dubbo.admin.registry.common.route.RouteRule;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.apache.dubbo.admin.web.pulltool.Tool;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.web.bind.annotation.*;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.util.*;
-//
-//
-//@Controller
-//public class ServiceDetailController extends BaseController{
-//
-//    @Autowired
-//    private ProviderService providerService;
-//
-//    @Autowired
-//    private ConsumerService consumerService;
-//
-//    @Autowired
-//    private OverrideService overrideService;
-//
-//    @Autowired
-//    private RouteService routeService;
-//
-//    @RequestMapping("/serviceDetail")
-//    public String serviceDetail(@RequestParam(required = false) String app,
-//                                @RequestParam(required = false) String service,
-//                                HttpServletRequest request,
-//                                HttpServletResponse response, Model model) {
-//        model.addAttribute("service", service);
-//        model.addAttribute("app", app);
-//        return "serviceDetail";
-//    }
-//
-//
-//    @RequestMapping(value =  "/create", method = RequestMethod.POST)  //post
-//    public boolean create(@RequestParam String service, @ModelAttribute Provider provider,
-//                          HttpServletRequest request, HttpServletResponse response,
-//                          Model model) {
-//        prepare(request, response, model,"create" ,"providers");
-//        boolean success = true;
-//        if (provider.getService() == null) {
-//            provider.setService(service);
-//        }
-//        if (provider.getParameters() == null) {
-//            String url = provider.getUrl();
-//            if (url != null) {
-//                int i = url.indexOf('?');
-//                if (i > 0) {
-//                    provider.setUrl(url.substring(0, i));
-//                    provider.setParameters(url.substring(i + 1));
-//                }
-//            }
-//        }
-//        provider.setDynamic(false); // Provider add through web page must be static
-//        providerService.create(provider);
-//        return true;
-//    }
-//
-//    @RequestMapping(value = "/update", method = RequestMethod.POST) //post
-//    public boolean update(@ModelAttribute Provider newProvider, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        boolean success = true;
-//        Long id = newProvider.getId();
-//        String parameters = newProvider.getParameters();
-//        Provider provider = providerService.findProvider(id);
-//        if (provider == null) {
-//            return false;
-//        }
-//        String service = provider.getService();
-//        Map<String, String> oldMap = StringUtils.parseQueryString(provider.getParameters());
-//        Map<String, String> newMap = StringUtils.parseQueryString(parameters);
-//        for (Map.Entry<String, String> entry : oldMap.entrySet()) {
-//            if (entry.getValue().equals(newMap.get(entry.getKey()))) {
-//                newMap.remove(entry.getKey());
-//            }
-//        }
-//        if (provider.isDynamic()) {
-//            String address = provider.getAddress();
-//            List<Override> overrides = overrideService.findByServiceAndAddress(provider.getService(), provider.getAddress());
-//            OverrideUtils.setProviderOverrides(provider, overrides);
-//            Override override = provider.getOverride();
-//            if (override != null) {
-//                if (newMap.size() > 0) {
-//                    override.setParams(StringUtils.toQueryString(newMap));
-//                    override.setEnabled(true);
-//                    override.setOperator(operator);
-//                    override.setOperatorAddress(operatorAddress);
-//                    overrideService.updateOverride(override);
-//                } else {
-//                    overrideService.deleteOverride(override.getId());
-//                }
-//            } else {
-//                override = new Override();
-//                override.setService(service);
-//                override.setAddress(address);
-//                override.setParams(StringUtils.toQueryString(newMap));
-//                override.setEnabled(true);
-//                override.setOperator(operator);
-//                override.setOperatorAddress(operatorAddress);
-//                overrideService.saveOverride(override);
-//            }
-//        } else {
-//            provider.setParameters(parameters);
-//            providerService.updateProvider(provider);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../providers");
-//        return true;
-//    }
-//
-//    @RequestMapping("/delete")
-//    public String delete(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        //prepare(request, response, model, "delete", "providers");
-//        boolean success = true;
-//        for (Long id : ids) {
-//            Provider provider = providerService.findProvider(id);
-//            if (provider == null) {
-//                model.addAttribute("message", getMessage("NoSuchOperationData", id));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            } else if (provider.isDynamic()) {
-//                model.addAttribute("message", getMessage("CanNotDeleteDynamicData", id));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            }
-//            else if (!super.currentUser.hasServicePrivilege(provider.getService())) {
-//                model.addAttribute("message", getMessage("HaveNoServicePrivilege", provider.getService()));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            }
-//        }
-//        for (Long id : ids) {
-//            providerService.deleteStaticProvider(id);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../providers");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/enable")
-//    public String enable(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "enable", "providers");
-//        boolean success = true;
-//        Map<Long, Provider> id2Provider = new HashMap<Long, Provider>();
-//        for (Long id : ids) {
-//            Provider provider = providerService.findProvider(id);
-//            if (provider == null) {
-//                model.addAttribute("message", getMessage("NoSuchOperationData", id));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            }
-//            else if (!super.currentUser.hasServicePrivilege(provider.getService())) {
-//                model.addAttribute("message", getMessage("HaveNoServicePrivilege", provider.getService()));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            }
-//            id2Provider.put(id, provider);
-//        }
-//        for (Long id : ids) {
-//            providerService.enableProvider(id);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../providers");
-//        return "governance/screen/redirect";
-//    }
-//
-//
-//    @RequestMapping("/disable")
-//    public String disable(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response,  Model model) {
-//        //prepare(request, response, model, "disable", "providers");
-//        boolean success = true;
-//        for (Long id : ids) {
-//            Provider provider = providerService.findProvider(id);
-//            if (provider == null) {
-//                model.addAttribute("message", getMessage("NoSuchOperationData", id));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            }
-//            else if (!super.currentUser.hasServicePrivilege(provider.getService())) {
-//                success = false;
-//                model.addAttribute("message", getMessage("HaveNoServicePrivilege", provider.getService()));
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../providers");
-//                return "governance/screen/redirect";
-//            }
-//        }
-//        for (Long id : ids) {
-//            providerService.disableProvider(id);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../providers");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/shield")
-//    public String shield(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return mock(ids, "force:return null", "shield", request, response, model);
-//    }
-//
-//    @RequestMapping("/tolerant")
-//    public String tolerant(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return mock(ids, "fail:return null", "tolerant", request, response, model);
-//    }
-//
-//    @RequestMapping("/recover")
-//    public String recover(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return mock(ids,  "", "recover", request, response, model);
-//    }
-//
-//    private String mock(Long[] ids, String mock, String methodName, HttpServletRequest request,
-//                        HttpServletResponse response, Model model) throws Exception {
-//        prepare(request, response, model, methodName, "consumers");
-//        boolean success = true;
-//        if (ids == null || ids.length == 0) {
-//            model.addAttribute("message", getMessage("NoSuchOperationData"));
-//            success = false;
-//            model.addAttribute("success", success);
-//            model.addAttribute("redirect", "../../consumers");
-//            return "governance/screen/redirect";
-//        }
-//        List<Consumer> consumers = new ArrayList<Consumer>();
-//        for (Long id : ids) {
-//            Consumer c = consumerService.findConsumer(id);
-//            if (c != null) {
-//                consumers.add(c);
-//                if (!super.currentUser.hasServicePrivilege(c.getService())) {
-//                    model.addAttribute("message", getMessage("HaveNoServicePrivilege", c.getService()));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../consumers");
-//                    return "governance/screen/redirect";
-//                }
-//            }
-//        }
-//        for (Consumer consumer : consumers) {
-//            String service = consumer.getService();
-//            String address = Tool.getIP(consumer.getAddress());
-//            List<Override> overrides = overrideService.findByServiceAndAddress(service, address);
-//            if (overrides != null && overrides.size() > 0) {
-//                for (Override override : overrides) {
-//                    Map<String, String> map = StringUtils.parseQueryString(override.getParams());
-//                    if (mock == null || mock.length() == 0) {
-//                        map.remove("mock");
-//                    } else {
-//                        map.put("mock", URL.encode(mock));
-//                    }
-//                    if (map.size() > 0) {
-//                        override.setParams(StringUtils.toQueryString(map));
-//                        override.setEnabled(true);
-//                        //override.setOperator(operator);
-//                        override.setOperatorAddress(operatorAddress);
-//                        overrideService.updateOverride(override);
-//                    } else {
-//                        overrideService.deleteOverride(override.getId());
-//                    }
-//                }
-//            } else if (mock != null && mock.length() > 0) {
-//                Override override = new Override();
-//                override.setService(service);
-//                override.setAddress(address);
-//                override.setParams("mock=" + URL.encode(mock));
-//                override.setEnabled(true);
-//                override.setOperator(operator);
-//                override.setOperatorAddress(operatorAddress);
-//                overrideService.saveOverride(override);
-//            }
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../consumers");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/allshield")
-//    public String allshield(@RequestParam(required = false) String service, HttpServletRequest request,
-//                            HttpServletResponse response, Model model) throws Exception {
-//        return allmock(service,  "force:return null", "allshield",request, response, model);
-//    }
-//
-//    @RequestMapping("/alltolerant")
-//    public String alltolerant(@RequestParam(required = false) String service, HttpServletRequest request,
-//                              HttpServletResponse response, Model model) throws Exception {
-//        return allmock(service, "fail:return null", "alltolerant", request, response, model);
-//    }
-//
-//    @RequestMapping("/allrecover")
-//    public String allrecover(@RequestParam(required = false) String service, HttpServletRequest request,
-//                             HttpServletResponse response, Model model) throws Exception {
-//        return allmock(service, "", "allrecover", request, response, model);
-//    }
-//
-//    private String allmock(String service, String mock, String methodName, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        String operatorAddress = request.getRemoteAddr();
-//        prepare(request, response, model, methodName,"consumers");
-//        boolean success = true;
-//        if (service == null || service.length() == 0) {
-//            model.addAttribute("message", getMessage("NoSuchOperationData"));
-//            success = false;
-//            model.addAttribute("success", success);
-//            model.addAttribute("redirect", "../consumers");
-//            return "governance/screen/redirect";
-//        }
-//        if (!super.currentUser.hasServicePrivilege(service)) {
-//            model.addAttribute("message", getMessage("HaveNoServicePrivilege", service));
-//            success = false;
-//            model.addAttribute("success", success);
-//            model.addAttribute("redirect", "../consumers");
-//            return "governance/screen/redirect";
-//        }
-//        List<Override> overrides = overrideService.findByService(service);
-//        Override allOverride = null;
-//        if (overrides != null && overrides.size() > 0) {
-//            for (Override override : overrides) {
-//                if (override.isDefault()) {
-//                    allOverride = override;
-//                    break;
-//                }
-//            }
-//        }
-//        if (allOverride != null) {
-//            Map<String, String> map = StringUtils.parseQueryString(allOverride.getParams());
-//            if (mock == null || mock.length() == 0) {
-//                map.remove("mock");
-//            } else {
-//                map.put("mock", URL.encode(mock));
-//            }
-//            if (map.size() > 0) {
-//                allOverride.setParams(StringUtils.toQueryString(map));
-//                allOverride.setEnabled(true);
-//                //allOverride.setOperator(operator);
-//                allOverride.setOperatorAddress(operatorAddress);
-//                overrideService.updateOverride(allOverride);
-//            } else {
-//                overrideService.deleteOverride(allOverride.getId());
-//            }
-//        } else if (mock != null && mock.length() > 0) {
-//            Override override = new Override();
-//            override.setService(service);
-//            override.setParams("mock=" + URL.encode(mock));
-//            override.setEnabled(true);
-//            override.setOperator(operator);
-//            override.setOperatorAddress(operatorAddress);
-//            overrideService.saveOverride(override);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../consumers");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/{ids}/allow")
-//    public String allow(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return access(request, response, ids, model, true, false, "allow");
-//    }
-//
-//    @RequestMapping("/{ids}/forbid")
-//    public String forbid(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return access(request, response, ids, model, false, false, "forbid");
-//    }
-//
-//    @RequestMapping("/{ids}/onlyallow")
-//    public String onlyallow(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return access(request, response, ids, model, true, true, "onlyallow");
-//    }
-//
-//    @RequestMapping("/{ids}/onlyforbid")
-//    public String onlyforbid(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return access(request, response, ids, model, false, true, "onlyforbid");
-//    }
-//
-//    private String access(HttpServletRequest request, HttpServletResponse response, Long[] ids,
-//                          Model model, boolean allow, boolean only, String methodName) throws Exception {
-//        prepare(request, response, model, methodName, "consumers");
-//        boolean success = true;
-//        if (ids == null || ids.length == 0) {
-//            model.addAttribute("message", getMessage("NoSuchOperationData"));
-//            success = false;
-//            model.addAttribute("success", success);
-//            model.addAttribute("redirect", "../../consumers");
-//            return "governance/screen/redirect";
-//        }
-//        List<Consumer> consumers = new ArrayList<Consumer>();
-//        for (Long id : ids) {
-//            Consumer c = consumerService.findConsumer(id);
-//            if (c != null) {
-//                consumers.add(c);
-//                if (!super.currentUser.hasServicePrivilege(c.getService())) {
-//                    model.addAttribute("message", getMessage("HaveNoServicePrivilege", c.getService()));
-//                    success = false;
-//                    model.addAttribute("success", success);
-//                    model.addAttribute("redirect", "../../consumers");
-//                    return "governance/screen/redirect";
-//                }
-//            }
-//        }
-//        Map<String, Set<String>> serviceAddresses = new HashMap<String, Set<String>>();
-//        for (Consumer consumer : consumers) {
-//            String service = consumer.getService();
-//            String address = Tool.getIP(consumer.getAddress());
-//            Set<String> addresses = serviceAddresses.get(service);
-//            if (addresses == null) {
-//                addresses = new HashSet<String>();
-//                serviceAddresses.put(service, addresses);
-//            }
-//            addresses.add(address);
-//        }
-//        for (Map.Entry<String, Set<String>> entry : serviceAddresses.entrySet()) {
-//            String service = entry.getKey();
-//            boolean isFirst = false;
-//            List<Route> routes = routeService.findForceRouteByService(service);
-//            Route route = null;
-//            if (routes == null || routes.size() == 0) {
-//                isFirst = true;
-//                route = new Route();
-//                route.setService(service);
-//                route.setForce(true);
-//                route.setName(service + " blackwhitelist");
-//                route.setFilterRule("false");
-//                route.setEnabled(true);
-//            } else {
-//                route = routes.get(0);
-//            }
-//            Map<String, RouteRule.MatchPair> when = null;
-//            RouteRule.MatchPair matchPair = null;
-//            if (isFirst) {
-//                when = new HashMap<String, RouteRule.MatchPair>();
-//                matchPair = new RouteRule.MatchPair(new HashSet<String>(), new HashSet<String>());
-//                when.put("consumer.host", matchPair);
-//            } else {
-//                when = RouteRule.parseRule(route.getMatchRule());
-//                matchPair = when.get("consumer.host");
-//            }
-//            if (only) {
-//                matchPair.getUnmatches().clear();
-//                matchPair.getMatches().clear();
-//                if (allow) {
-//                    matchPair.getUnmatches().addAll(entry.getValue());
-//                } else {
-//                    matchPair.getMatches().addAll(entry.getValue());
-//                }
-//            } else {
-//                for (String consumerAddress : entry.getValue()) {
-//                    if (matchPair.getUnmatches().size() > 0) { // whitelist take effect
-//                        matchPair.getMatches().remove(consumerAddress); // remove data in blacklist
-//                        if (allow) { // if allowed
-//                            matchPair.getUnmatches().add(consumerAddress); // add to whitelist
-//                        } else { // if not allowed
-//                            matchPair.getUnmatches().remove(consumerAddress); // remove from whitelist
-//                        }
-//                    } else { // blacklist take effect
-//                        if (allow) { // if allowed
-//                            matchPair.getMatches().remove(consumerAddress); // remove from blacklist
-//                        } else { // if not allowed
-//                            matchPair.getMatches().add(consumerAddress); // add to blacklist
-//                        }
-//                    }
-//                }
-//            }
-//            StringBuilder sb = new StringBuilder();
-//            RouteRule.contidionToString(sb, when);
-//            route.setMatchRule(sb.toString());
-//            route.setUsername(operator);
-//            if (matchPair.getMatches().size() > 0 || matchPair.getUnmatches().size() > 0) {
-//                if (isFirst) {
-//                    routeService.createRoute(route);
-//                } else {
-//                    routeService.updateRoute(route);
-//                }
-//            } else if (!isFirst) {
-//                routeService.deleteRoute(route.getId());
-//            }
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../consumers");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/metaData")
-//    public List<String> metaData(@RequestParam String app, @RequestParam String service) {
-//        return null;
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/ServicesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/ServicesController.java
deleted file mode 100644
index 291dba1..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/ServicesController.java
+++ /dev/null
@@ -1,227 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import com.alibaba.dubbo.common.URL;
-//import com.alibaba.dubbo.common.utils.StringUtils;
-//import org.apache.dubbo.admin.governance.service.ConsumerService;
-//import org.apache.dubbo.admin.governance.service.OverrideService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.registry.common.domain.Override;
-//import org.apache.dubbo.admin.registry.common.route.OverrideUtils;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.apache.dubbo.admin.web.pulltool.Tool;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.validation.support.BindingAwareModelMap;
-//import org.springframework.web.bind.annotation.PathVariable;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.util.*;
-//
-///**
-// * ProvidersController. URI: /services/$service/providers /addresses/$address/services /application/$application/services
-// *
-// */
-//@Controller
-//@RequestMapping("/governance/services")
-//public class ServicesController extends BaseController {
-//
-//    @Autowired
-//    private ProviderService providerService;
-//
-//    @Autowired
-//    private ConsumerService consumerService;
-//
-//    @Autowired
-//    private OverrideService overrideService;
-//
-//
-//    @RequestMapping("")
-//    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "index", "services");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//        String application = (String)newModel.get("app");
-//        String address = (String)newModel.get("address");
-//        String keyword = request.getParameter("keyword");
-//
-//        if (service == null
-//                && application == null
-//                && address == null) {
-//            model.addAttribute("service", "*");
-//        }
-//
-//        List<String> providerServices = null;
-//        List<String> consumerServices = null;
-//        List<Override> overrides = null;
-//        if (application != null && application.length() > 0) {
-//            model.addAttribute("app", application);
-//            providerServices = providerService.findServicesByApplication(application);
-//            consumerServices = consumerService.findServicesByApplication(application);
-//            overrides = overrideService.findByApplication(application);
-//        } else if (address != null && address.length() > 0) {
-//            providerServices = providerService.findServicesByAddress(address);
-//            consumerServices = consumerService.findServicesByAddress(address);
-//            overrides = overrideService.findByAddress(Tool.getIP(address));
-//        } else {
-//            providerServices = providerService.findServices();
-//            consumerServices = consumerService.findServices();
-//            overrides = overrideService.findAll();
-//        }
-//
-//        Set<String> services = new TreeSet<String>();
-//        if (providerServices != null) {
-//            services.addAll(providerServices);
-//        }
-//        if (consumerServices != null) {
-//            services.addAll(consumerServices);
-//        }
-//
-//        Map<String, List<Override>> service2Overrides = new HashMap<String, List<Override>>();
-//        if (overrides != null && overrides.size() > 0
-//                && services != null && services.size() > 0) {
-//            for (String s : services) {
-//                if (overrides != null && overrides.size() > 0) {
-//                    for (Override override : overrides) {
-//                        List<Override> serOverrides = new ArrayList<Override>();
-//                        if (override.isMatch(s, address, application)) {
-//                            serOverrides.add(override);
-//                        }
-//                        Collections.sort(serOverrides, OverrideUtils.OVERRIDE_COMPARATOR);
-//                        service2Overrides.put(s, serOverrides);
-//                    }
-//                }
-//            }
-//        }
-//
-//        model.addAttribute("providerServices", providerServices);
-//        model.addAttribute("consumerServices", consumerServices);
-//        model.addAttribute("services", services);
-//        model.addAttribute("overrides", service2Overrides);
-//
-//
-//        if (keyword != null && !"*".equals(keyword)) {
-//            keyword = keyword.toLowerCase();
-//            Set<String> newList = new HashSet<String>();
-//            Set<String> newProviders = new HashSet<String>();
-//            Set<String> newConsumers = new HashSet<String>();
-//
-//            for (String o : services) {
-//                if (o.toLowerCase().toLowerCase().indexOf(keyword) != -1) {
-//                    newList.add(o);
-//                }
-//                if (o.toLowerCase().toLowerCase().equals(keyword.toLowerCase())) {
-//                    service = o;
-//                }
-//            }
-//            for (String o : providerServices) {
-//                if (o.toLowerCase().indexOf(keyword) != -1) {
-//                    newProviders.add(o);
-//                }
-//            }
-//            for (String o : consumerServices) {
-//                if (o.toLowerCase().indexOf(keyword) != -1) {
-//                    newConsumers.add(o);
-//                }
-//            }
-//            model.addAttribute("services", newList);
-//            model.addAttribute("keyword", keyword);
-//            model.addAttribute("providerServices", newProviders);
-//            model.addAttribute("consumerServices", newConsumers);
-//        }
-//        return "governance/screen/services/index";
-//    }
-//
-//
-//    @RequestMapping("/{ids}/shield")
-//    public String shield(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return mock(ids, "force:return null", "shield", request, response, model);
-//    }
-//
-//    @RequestMapping("/{ids}/tolerant")
-//    public String tolerant(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return mock(ids, "fail:return null", "tolerant", request, response, model);
-//    }
-//
-//    @RequestMapping("/{ids}/recover")
-//    public String recover(@PathVariable("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        return mock(ids,  "", "recover", request, response, model);
-//    }
-//
-//    private String mock(Long[] ids, String mock, String methodName, HttpServletRequest request,
-//                        HttpServletResponse response, Model model) throws Exception {
-//        prepare(request, response, model, methodName, "services");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String services = (String) newModel.get("service");
-//        String application = (String) newModel.get("app");
-//
-//        if (services == null || services.length() == 0
-//                || application == null || application.length() == 0) {
-//            model.addAttribute("message", getMessage("NoSuchOperationData"));
-//            model.addAttribute("success", false);
-//            model.addAttribute("redirect", "../../services");
-//            return "governance/screen/redirect";
-//        }
-//        for (String service : SPACE_SPLIT_PATTERN.split(services)) {
-//            if (!super.currentUser.hasServicePrivilege(service)) {
-//                model.addAttribute("message", getMessage("HaveNoServicePrivilege", service));
-//                model.addAttribute("success", false);
-//                model.addAttribute("redirect", "../../services");
-//                return "governance/screen/redirect";
-//            }
-//        }
-//        for (String service : SPACE_SPLIT_PATTERN.split(services)) {
-//            List<Override> overrides = overrideService.findByServiceAndApplication(service, application);
-//            if (overrides != null && overrides.size() > 0) {
-//                for (Override override : overrides) {
-//                    Map<String, String> map = StringUtils.parseQueryString(override.getParams());
-//                    if (mock == null || mock.length() == 0) {
-//                        map.remove("mock");
-//                    } else {
-//                        map.put("mock", URL.encode(mock));
-//                    }
-//                    if (map.size() > 0) {
-//                        override.setParams(StringUtils.toQueryString(map));
-//                        override.setEnabled(true);
-//                        override.setOperator(operator);
-//                        override.setOperatorAddress(operatorAddress);
-//                        overrideService.updateOverride(override);
-//                    } else {
-//                        overrideService.deleteOverride(override.getId());
-//                    }
-//                }
-//            } else if (mock != null && mock.length() > 0) {
-//                Override override = new Override();
-//                override.setService(service);
-//                override.setApplication(application);
-//                override.setParams("mock=" + URL.encode(mock));
-//                override.setEnabled(true);
-//                override.setOperator(operator);
-//                override.setOperatorAddress(operatorAddress);
-//                overrideService.saveOverride(override);
-//            }
-//        }
-//        model.addAttribute("success", true);
-//        model.addAttribute("redirect", "../../services");
-//        return "governance/screen/redirect";
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/WeightsController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/WeightsController.java
deleted file mode 100644
index ca18add..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/governance/WeightsController.java
+++ /dev/null
@@ -1,288 +0,0 @@
-///*
-// * 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.web.mvc.governance;
-//
-//import com.alibaba.dubbo.common.utils.CollectionUtils;
-//import org.apache.dubbo.admin.governance.service.OverrideService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.apache.dubbo.admin.registry.common.domain.Provider;
-//import org.apache.dubbo.admin.registry.common.domain.Weight;
-//import org.apache.dubbo.admin.registry.common.util.OverrideUtils;
-//import org.apache.dubbo.admin.web.mvc.BaseController;
-//import org.apache.dubbo.admin.web.pulltool.Tool;
-//import org.apache.commons.lang3.StringUtils;
-//import org.apache.commons.lang3.math.NumberUtils;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.validation.support.BindingAwareModelMap;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestMethod;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//import java.io.BufferedReader;
-//import java.io.StringReader;
-//import java.util.ArrayList;
-//import java.util.HashSet;
-//import java.util.List;
-//import java.util.Set;
-//import java.util.regex.Pattern;
-//
-///**
-// * ProvidersController.
-// * URI: /services/$service/weights
-// *
-// */
-//@Controller
-//@RequestMapping("/governance/weights")
-//public class WeightsController extends BaseController {
-//
-//    private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3}$");
-//    private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$");
-//    private static final Pattern ALL_IP_PATTERN = Pattern.compile("0{1,3}(\\.0{1,3}){3}$");
-//    @Autowired
-//    private OverrideService overrideService;
-//    @Autowired
-//    private ProviderService providerService;
-//
-//    @RequestMapping("")
-//    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "index", "weights");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//        String address = (String)newModel.get("address");
-//        service = StringUtils.trimToNull(service);
-//        address = Tool.getIP(address);
-//        List<Weight> weights;
-//        if (service != null && service.length() > 0) {
-//            weights = OverrideUtils.overridesToWeights(overrideService.findByService(service));
-//        } else if (address != null && address.length() > 0) {
-//            weights = OverrideUtils.overridesToWeights(overrideService.findByAddress(address));
-//        } else {
-//            weights = OverrideUtils.overridesToWeights(overrideService.findAll());
-//        }
-//        model.addAttribute("weights", weights);
-//        return "governance/screen/weights/index";
-//    }
-//
-//    /**
-//     * load page for the adding
-//     *
-//     */
-//    @RequestMapping("/add")
-//    public String add(HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "add", "weights");
-//        BindingAwareModelMap newModel = (BindingAwareModelMap)model;
-//        String service = (String)newModel.get("service");
-//        String input = request.getParameter("input");
-//        if (service != null && service.length() > 0 && !service.contains("*")) {
-//            List<Provider> providerList = providerService.findByService(service);
-//            List<String> addressList = new ArrayList<String>();
-//            for (Provider provider : providerList) {
-//                addressList.add(provider.getUrl().split("://")[1].split("/")[0]);
-//            }
-//            model.addAttribute("addressList", addressList);
-//            model.addAttribute("service", service);
-//            model.addAttribute("methods", CollectionUtils.sort(providerService.findMethodsByService(service)));
-//        } else {
-//            List<String> serviceList = Tool.sortSimpleName(providerService.findServices());
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//        if (input != null) model.addAttribute("input", input);
-//        return "governance/screen/weights/add";
-//    }
-//
-//
-//    @RequestMapping("/create")
-//    public String create(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-//        prepare(request, response, model, "create", "weights");
-//        String addr = request.getParameter("address");
-//        String services = request.getParameter("multiservice");
-//        if (services == null || services.trim().length() == 0) {
-//            services = request.getParameter("service");
-//        }
-//        String weight = request.getParameter("weight");
-//
-//        int w = Integer.parseInt(weight);
-//
-//        Set<String> addresses = new HashSet<String>();
-//        BufferedReader reader = new BufferedReader(new StringReader(addr));
-//        while (true) {
-//            String line = reader.readLine();
-//            if (null == line)
-//                break;
-//
-//            String[] split = line.split("[\\s,;]+");
-//            for (String s : split) {
-//                if (s.length() == 0)
-//                    continue;
-//
-//                String ip = s;
-//                String port = null;
-//                if (s.indexOf(":") != -1) {
-//                    ip = s.substring(0, s.indexOf(":"));
-//                    port = s.substring(s.indexOf(":") + 1, s.length());
-//                    if (port.trim().length() == 0) port = null;
-//                }
-//                if (!IP_PATTERN.matcher(ip).matches()) {
-//                    model.addAttribute("message", "illegal IP: " + s);
-//                    model.addAttribute("success", false);
-//                    model.addAttribute("redirect", "../weights");
-//                    return "governance/screen/redirect";
-//                }
-//                if (LOCAL_IP_PATTERN.matcher(ip).matches() || ALL_IP_PATTERN.matcher(ip).matches()) {
-//                    model.addAttribute("message", "local IP or any host ip is illegal: " + s);
-//                    model.addAttribute("success", false);
-//                    model.addAttribute("redirect", "../weights");
-//                    return "governance/screen/redirect";
-//                }
-//                if (port != null) {
-//                    if (!NumberUtils.isDigits(port)) {
-//                        model.addAttribute("message", "illegal port: " + s);
-//                        model.addAttribute("success", false);
-//                        model.addAttribute("redirect", "../weights");
-//                        return "governance/screen/redirect";
-//                    }
-//                }
-//                addresses.add(s);
-//            }
-//        }
-//
-//        Set<String> aimServices = new HashSet<String>();
-//        reader = new BufferedReader(new StringReader(services));
-//        while (true) {
-//            String line = reader.readLine();
-//            if (null == line)
-//                break;
-//
-//            String[] split = line.split("[\\s,;]+");
-//            for (String s : split) {
-//                if (s.length() == 0)
-//                    continue;
-//                if (!super.currentUser.hasServicePrivilege(s)) {
-//                    model.addAttribute("message", getMessage("HaveNoServicePrivilege", s));
-//                    model.addAttribute("success", false);
-//                    model.addAttribute("redirect", "../weights");
-//                    return "governance/screen/redirect";
-//                }
-//                aimServices.add(s);
-//            }
-//        }
-//
-//        for (String aimService : aimServices) {
-//            for (String a : addresses) {
-//                Weight wt = new Weight();
-//                wt.setUsername((String) ((BindingAwareModelMap)model).get("operator"));
-//                wt.setAddress(Tool.getIP(a));
-//                wt.setService(aimService);
-//                wt.setWeight(w);
-//                overrideService.saveOverride(OverrideUtils.weightToOverride(wt));
-//            }
-//        }
-//        model.addAttribute("success", true);
-//        model.addAttribute("redirect", "../weights");
-//        return "governance/screen/redirect";
-//    }
-//
-//    @RequestMapping("/edit")
-//    public String edit(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "edit", "weights");
-//        String service = request.getParameter("service");
-//        String input = request.getParameter("input");
-//
-//        if (service != null && service.length() > 0 && !service.contains("*")) {
-//            List<Provider> providerList = providerService.findByService(service);
-//            List<String> addressList = new ArrayList<String>();
-//            for (Provider provider : providerList) {
-//                addressList.add(provider.getUrl().split("://")[1].split("/")[0]);
-//            }
-//            model.addAttribute("addressList", addressList);
-//            model.addAttribute("service", service);
-//            model.addAttribute("methods", CollectionUtils.sort(providerService.findMethodsByService(service)));
-//        } else {
-//            List<String> serviceList = Tool.sortSimpleName(providerService.findServices());
-//            model.addAttribute("serviceList", serviceList);
-//        }
-//        if (input != null) model.addAttribute("input", input);
-//        Weight weight = OverrideUtils.overrideToWeight(overrideService.findById(id));
-//        model.addAttribute("weight", weight);
-//        model.addAttribute("service", overrideService.findById(id).getService());
-//        return "governance/screen/weights/edit";
-//    }
-//
-//    /**
-//     * load weight for editing
-//     *
-//     * @param id
-//
-//     */
-//    @RequestMapping("/detail")
-//    public String show(@RequestParam("id") Long id, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "show", "weights");
-//        Weight weight = OverrideUtils.overrideToWeight(overrideService.findById(id));
-//        model.addAttribute("weight", weight);
-//        return "governance/screen/weights/show";
-//    }
-//
-//    @RequestMapping(value = "/update", method = RequestMethod.POST) //post
-//    public String update(Weight weight, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "update", "weights");
-//        boolean success = true;
-//        if (!super.currentUser.hasServicePrivilege(weight.getService())) {
-//            model.addAttribute("message", getMessage("HaveNoServicePrivilege", weight.getService()));
-//            success = false;
-//        } else {
-//            weight.setAddress(Tool.getIP(weight.getAddress()));
-//            overrideService.updateOverride(OverrideUtils.weightToOverride(weight));
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "governance/weights");
-//        return "governance/screen/redirect";
-//    }
-//
-//    /**
-//     * delete
-//     *
-//     * @param ids
-//     * @return
-//     */
-//    @RequestMapping("/delete")
-//    public String delete(@RequestParam("ids") Long[] ids, HttpServletRequest request, HttpServletResponse response, Model model) {
-//        prepare(request, response, model, "delete", "weights");
-//        boolean success = true;
-//        for (Long id : ids) {
-//            Weight w = OverrideUtils.overrideToWeight(overrideService.findById(id));
-//            if (!super.currentUser.hasServicePrivilege(w.getService())) {
-//                model.addAttribute("message", getMessage("HaveNoServicePrivilege", w.getService()));
-//                success = false;
-//                model.addAttribute("success", success);
-//                model.addAttribute("redirect", "../../weights");
-//                return "governance/screen/redirect";
-//            }
-//        }
-//
-//        for (Long id : ids) {
-//            overrideService.deleteOverride(id);
-//        }
-//        model.addAttribute("success", success);
-//        model.addAttribute("redirect", "../../weights");
-//        return "governance/screen/redirect";
-//    }
-//
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/home/IndexController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/home/IndexController.java
deleted file mode 100644
index 5c83a0a..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/home/IndexController.java
+++ /dev/null
@@ -1,48 +0,0 @@
-//package org.apache.dubbo.admin.web.mvc.home;
-//
-//import org.apache.dubbo.admin.governance.service.ConsumerService;
-//import org.apache.dubbo.admin.governance.service.ProviderService;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.stereotype.Controller;
-//import org.springframework.ui.Model;
-//import org.springframework.web.bind.annotation.RequestMapping;
-//import org.springframework.web.bind.annotation.RequestParam;
-//
-//import javax.servlet.http.HttpServletRequest;
-//import javax.servlet.http.HttpServletResponse;
-//
-///**
-// * @author zmx ON 2018/7/20
-// */
-//
-//@Controller
-//public class IndexController {
-//
-//    @Autowired
-//    private ProviderService providerService;
-//
-//    @Autowired
-//    private ConsumerService consumerService;
-//
-//    @RequestMapping("/")
-//    public String search(@RequestParam(required = false) String filter,
-//                                  @RequestParam(required = false, defaultValue = "") String pattern,
-//                                  HttpServletRequest request,
-//                                  HttpServletResponse response, Model model) {
-//        if ("app".equals(pattern)) {
-//            model.addAttribute("active", "app");
-//        } else if ("ip".equals(pattern)) {
-//            model.addAttribute("active", "ip");
-//        } else {
-//            model.addAttribute("active", "service");
-//        }
-//
-//        return "serviceSearch";
-//
-//    }
-//
-//    @RequestMapping("/index")
-//    public String index() {
-//        return "index";
-//    }
-//}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/DumpController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/DumpController.java
deleted file mode 100644
index fb1433f..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/DumpController.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.web.mvc.sysinfo;
-
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.governance.service.ConsumerService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.*;
-
-@Controller
-@RequestMapping("/sysinfo/dump")
-public class DumpController extends BaseController {
-
-    @Autowired
-    ProviderService providerDAO;
-
-    @Autowired
-    ConsumerService consumerDAO;
-
-
-    @RequestMapping("/noProviders")
-    public void noProviders(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
-        prepare(request, response, model, "noProviders", "dump");
-        PrintWriter writer = response.getWriter();
-        List<String> sortedService = getNoProviders();
-        Collections.sort(sortedService);
-        writer.println(sortedService.size() + " services don't have provider");
-        for (String noProvider : sortedService) {
-            writer.println(noProvider);
-        }
-        writer.flush();
-        response.setContentType("text/plain");
-    }
-
-    @RequestMapping("/services")
-    public void services(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
-        prepare(request, response, model, "noProviders", "services");
-        PrintWriter writer = response.getWriter();
-        List<String> sortedService = providerDAO.findServices();
-        Collections.sort(sortedService);
-        writer.println(sortedService.size() + " services");
-        for (String service : sortedService) {
-            writer.println(service + (providerDAO.findByService(service).size()));
-        }
-        writer.flush();
-        response.setContentType("text/plain");
-    }
-
-    @RequestMapping("/providers")
-    public void providers(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
-        PrintWriter writer = response.getWriter();
-        List<Provider> providers = providerDAO.findAll();
-        List<String> sortedProviders = new ArrayList<String>();
-        for (Provider provider : providers) {
-            sortedProviders.add(provider.getUrl() + " " + provider.getService());
-        }
-        Collections.sort(sortedProviders);
-        writer.println(sortedProviders.size() + " provider instance");
-        for (String provider : sortedProviders) {
-            writer.println(provider);
-        }
-        writer.flush();
-        response.setContentType("text/plain");
-    }
-
-    @RequestMapping("/consumers")
-    public void consumers(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
-        PrintWriter writer = response.getWriter();
-        List<Consumer> consumers = consumerDAO.findAll();
-        List<String> sortedConsumerss = new ArrayList<String>();
-        for (Consumer consumer : consumers) {
-            sortedConsumerss.add(consumer.getAddress() + " " + consumer.getService());
-        }
-        Collections.sort(sortedConsumerss);
-        writer.println(sortedConsumerss.size() + " consumer instance");
-        for (String consumer : sortedConsumerss) {
-            writer.println(consumer);
-        }
-        writer.flush();
-        response.setContentType("text/plain");
-    }
-
-    @RequestMapping("/versions")
-    public void versions(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
-        PrintWriter writer = response.getWriter();
-        List<Provider> providers = providerDAO.findAll();
-        List<Consumer> consumers = consumerDAO.findAll();
-        Set<String> parametersSet = new HashSet<String>();
-        Map<String, Set<String>> versions = new HashMap<String, Set<String>>();
-        for (Provider provider : providers) {
-            parametersSet.add(provider.getParameters());
-        }
-        for (Consumer consumer : consumers) {
-            parametersSet.add(consumer.getParameters());
-        }
-        Iterator<String> temp = parametersSet.iterator();
-        while (temp.hasNext()) {
-            Map<String, String> parameter = StringUtils.parseQueryString(temp.next());
-            if (parameter != null) {
-                String dubboversion = parameter.get("dubbo");
-                String app = parameter.get("application");
-                if (versions.get(dubboversion) == null) {
-                    Set<String> apps = new HashSet<String>();
-                    versions.put(dubboversion, apps);
-                }
-                versions.get(dubboversion).add(app);
-            }
-        }
-        for (String version : versions.keySet()) {
-            writer.println("dubbo version: " + version);
-            writer.println(StringUtils.join(versions.get(version), "\n"));
-            writer.println("\n");
-        }
-        model.addAttribute("versions", versions);
-        writer.flush();
-        response.setContentType("text/plain");
-    }
-
-    private List<String> getNoProviders() {
-        List<String> providerServices = providerDAO.findServices();
-        List<String> consumerServices = consumerDAO.findServices();
-        List<String> noProviderServices = new ArrayList<String>();
-        if (consumerServices != null) {
-            noProviderServices.addAll(consumerServices);
-            noProviderServices.removeAll(providerServices);
-        }
-        return noProviderServices;
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/DumpsController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/DumpsController.java
deleted file mode 100644
index 2357c81..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/DumpsController.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.web.mvc.sysinfo;
-
-import org.apache.dubbo.admin.governance.service.ConsumerService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.ArrayList;
-import java.util.List;
-
-@Controller
-@RequestMapping("/sysinfo/dumps")
-public class DumpsController extends BaseController {
-
-    @Autowired
-    ProviderService providerDAO;
-
-    @Autowired
-    ConsumerService consumerDAO;
-
-    @Autowired
-    HttpServletResponse response;
-
-    @RequestMapping("")
-    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-        prepare(request, response, model, "index", "dumps");
-        model.addAttribute("noProviderServices", getNoProviders());
-        model.addAttribute("services", providerDAO.findServices());
-        model.addAttribute("providers", providerDAO.findAll());
-        model.addAttribute("consumers", consumerDAO.findAll());
-        return "sysinfo/screen/dumps/index";
-    }
-
-    private List<String> getNoProviders() {
-        List<String> providerServices = providerDAO.findServices();
-        List<String> consumerServices = consumerDAO.findServices();
-        List<String> noProviderServices = new ArrayList<String>();
-        if (consumerServices != null) {
-            noProviderServices.addAll(consumerServices);
-            noProviderServices.removeAll(providerServices);
-        }
-        return noProviderServices;
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/EnvsController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/EnvsController.java
deleted file mode 100644
index 840c610..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/EnvsController.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.web.mvc.sysinfo;
-
-import com.alibaba.dubbo.common.Version;
-import com.alibaba.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.lang.management.ManagementFactory;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
-
-@Controller
-@RequestMapping("/sysinfo/envs")
-public class EnvsController extends BaseController {
-
-    private static final long SECOND = 1000;
-    private static final long MINUTE = 60 * SECOND;
-    private static final long HOUR = 60 * MINUTE;
-    private static final long DAY = 24 * HOUR;
-
-    @RequestMapping("")
-    public String index(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-        prepare(request, response, model, "index", "envs");
-        Map<String, String> properties = new TreeMap<String, String>();
-        StringBuilder msg = new StringBuilder();
-        msg.append("Version: ");
-        msg.append(Version.getVersion(EnvsController.class, "2.2.0"));
-        properties.put("Registry", msg.toString());
-        String address = NetUtils.getLocalHost();
-        properties.put("Host", NetUtils.getHostName(address) + "/" + address);
-        properties.put("Java", System.getProperty("java.runtime.name") + " " + System.getProperty("java.runtime.version"));
-        properties.put("OS", System.getProperty("os.name") + " "
-                + System.getProperty("os.version"));
-        properties.put("CPU", System.getProperty("os.arch", "") + ", "
-                + String.valueOf(Runtime.getRuntime().availableProcessors()) + " cores");
-        properties.put("Locale", Locale.getDefault().toString() + "/"
-                + System.getProperty("file.encoding"));
-        properties.put("Uptime", formatUptime(ManagementFactory.getRuntimeMXBean().getUptime())
-                + " From " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z").format(new Date(
-            ManagementFactory.getRuntimeMXBean().getStartTime()))
-                + " To " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z").format(new Date()));
-        model.addAttribute("properties", properties);
-        return "sysinfo/screen/envs/index";
-    }
-
-    private String formatUptime(long uptime) {
-        StringBuilder buf = new StringBuilder();
-        if (uptime > DAY) {
-            long days = (uptime - uptime % DAY) / DAY;
-            buf.append(days);
-            buf.append(" Days");
-            uptime = uptime % DAY;
-        }
-        if (uptime > HOUR) {
-            long hours = (uptime - uptime % HOUR) / HOUR;
-            if (buf.length() > 0) {
-                buf.append(", ");
-            }
-            buf.append(hours);
-            buf.append(" Hours");
-            uptime = uptime % HOUR;
-        }
-        if (uptime > MINUTE) {
-            long minutes = (uptime - uptime % MINUTE) / MINUTE;
-            if (buf.length() > 0) {
-                buf.append(", ");
-            }
-            buf.append(minutes);
-            buf.append(" Minutes");
-            uptime = uptime % MINUTE;
-        }
-        if (uptime > SECOND) {
-            long seconds = (uptime - uptime % SECOND) / SECOND;
-            if (buf.length() > 0) {
-                buf.append(", ");
-            }
-            buf.append(seconds);
-            buf.append(" Seconds");
-            uptime = uptime % SECOND;
-        }
-        if (uptime > 0) {
-            if (buf.length() > 0) {
-                buf.append(", ");
-            }
-            buf.append(uptime);
-            buf.append(" Milliseconds");
-        }
-        return buf.toString();
-    }
-
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/LogsController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/LogsController.java
deleted file mode 100644
index 34c2034..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/LogsController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.web.mvc.sysinfo;
-
-import com.alibaba.dubbo.common.logger.Level;
-import com.alibaba.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.File;
-import java.io.FileInputStream;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-@Controller
-@RequestMapping("/sysinfo/logs")
-public class LogsController extends BaseController {
-
-    private static final int SHOW_LOG_LENGTH = 30000;
-
-    @RequestMapping("")
-    public String index(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-        prepare(request, response, model, "index", "logs");
-        long size;
-        String content;
-        String modified;
-        File file = LoggerFactory.getFile();
-        if (file != null && file.exists()) {
-            FileInputStream fis = new FileInputStream(file);
-            FileChannel channel = fis.getChannel();
-            size = channel.size();
-            ByteBuffer bb;
-            if (size <= SHOW_LOG_LENGTH) {
-                bb = ByteBuffer.allocate((int) size);
-                channel.read(bb, 0);
-            } else {
-                int pos = (int) (size - SHOW_LOG_LENGTH);
-                bb = ByteBuffer.allocate(SHOW_LOG_LENGTH);
-                channel.read(bb, pos);
-            }
-            bb.flip();
-            content = new String(bb.array()).replace("<", "&lt;").replace(">", "&gt;");
-            modified = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(file.lastModified()));
-        } else {
-            size = 0;
-            content = "";
-            modified = "Not exist";
-        }
-        Level level = LoggerFactory.getLevel();
-        model.addAttribute("name", file == null ? "" : file.getAbsoluteFile());
-        model.addAttribute("size", String.valueOf(size));
-        model.addAttribute("level", level == null ? "" : level);
-        model.addAttribute("modified", modified);
-        model.addAttribute("content", content);
-        return "sysinfo/screen/logs/index";
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/StatusesController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/StatusesController.java
deleted file mode 100644
index de98ce9..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/StatusesController.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.web.mvc.sysinfo;
-
-import com.alibaba.dubbo.common.extension.ExtensionLoader;
-import com.alibaba.dubbo.common.status.Status;
-import com.alibaba.dubbo.common.status.StatusChecker;
-import org.apache.dubbo.admin.registry.common.StatusManager;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-@Controller
-@RequestMapping("/sysinfo/statuses")
-public class StatusesController extends BaseController {
-
-    @RequestMapping("")
-    public String index(HttpServletRequest request, HttpServletResponse response, Model model) throws Exception {
-
-        prepare(request, response, model, "index", "status");
-        ExtensionLoader<StatusChecker> loader = ExtensionLoader.getExtensionLoader(StatusChecker.class);
-        Map<String, Status> statusList = new LinkedHashMap<String, Status>();
-        for (String name : loader.getSupportedExtensions()) {
-            com.alibaba.dubbo.common.status.Status status = loader.getExtension(name).check();
-            if (status.getLevel() != null && status.getLevel() != com.alibaba.dubbo.common.status.Status.Level.UNKNOWN) {
-                statusList.put(name, status);
-            }
-        }
-        statusList.put("summary", StatusManager.getStatusSummary(statusList));
-        model.addAttribute("statusList", statusList);
-        return "sysinfo/screen/statuses/index";
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/VersionsController.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/VersionsController.java
deleted file mode 100644
index 6a601f9..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/mvc/sysinfo/VersionsController.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.web.mvc.sysinfo;
-
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.governance.service.ConsumerService;
-import org.apache.dubbo.admin.governance.service.ProviderService;
-import org.apache.dubbo.admin.registry.common.domain.Consumer;
-import org.apache.dubbo.admin.registry.common.domain.Provider;
-import org.apache.dubbo.admin.web.mvc.BaseController;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.*;
-
-@Controller
-@RequestMapping("/sysinfo")
-public class VersionsController extends BaseController {
-    @Autowired
-    private ProviderService providerService;
-
-    @Autowired
-    private ConsumerService consumerService;
-
-    @RequestMapping("/versions")
-    public String index(HttpServletRequest request, HttpServletResponse response, Model model) {
-        prepare(request, response, model, "index", "versions");
-        List<Provider> providers = providerService.findAll();
-        List<Consumer> consumers = consumerService.findAll();
-        Set<String> parametersSet = new HashSet<String>();
-        for (Provider provider : providers) {
-            parametersSet.add(provider.getParameters());
-        }
-        for (Consumer consumer : consumers) {
-            parametersSet.add(consumer.getParameters());
-        }
-        Map<String, Set<String>> versions = new HashMap<String, Set<String>>();
-        Iterator<String> temp = parametersSet.iterator();
-        while (temp.hasNext()) {
-            Map<String, String> parameter = StringUtils.parseQueryString(temp.next());
-            if (parameter != null) {
-                String dubbo = parameter.get("dubbo");
-                if (dubbo == null) dubbo = "0.0.0";
-                String application = parameter.get("application");
-                if (versions.get(dubbo) == null) {
-                    Set<String> apps = new HashSet<String>();
-                    versions.put(dubbo, apps);
-                }
-                versions.get(dubbo).add(application);
-            }
-        }
-        model.addAttribute("versions", versions);
-        return "sysinfo/screen/versions/index";
-    }
-
-    @RequestMapping("/version/{version}/versions/show")
-    public String show(@PathVariable("version") String version, HttpServletRequest request, HttpServletResponse response,
-                     Model model) {
-        prepare(request, response, model, "show", "versions");
-        if (version != null && version.length() > 0) {
-            List<Provider> providers = providerService.findAll();
-            List<Consumer> consumers = consumerService.findAll();
-            Set<String> parametersSet = new HashSet<String>();
-            Set<String> applications = new HashSet<String>();
-            for (Provider provider : providers) {
-                parametersSet.add(provider.getParameters());
-            }
-            for (Consumer consumer : consumers) {
-                parametersSet.add(consumer.getParameters());
-            }
-            Iterator<String> temp = parametersSet.iterator();
-            while (temp.hasNext()) {
-                Map<String, String> parameter = StringUtils.parseQueryString(temp.next());
-                if (parameter != null) {
-                    String dubbo = parameter.get("dubbo");
-                    if (dubbo == null) dubbo = "0.0.0";
-                    String application = parameter.get("application");
-                    if (version.equals(dubbo)) {
-                        applications.add(application);
-                    }
-                }
-            }
-            model.addAttribute("applications", applications);
-        }
-        return "sysinfo/screen/versions/show";
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/DateFormatUtil.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/DateFormatUtil.java
deleted file mode 100644
index ba35bea..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/DateFormatUtil.java
+++ /dev/null
@@ -1,74 +0,0 @@
-
-/*
- * 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.web.pulltool;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * DateFormat Utility
- *
- */
-public class DateFormatUtil {
-
-    private static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
-
-    private static final ThreadLocal<Map<String, DateFormat>> tl = new ThreadLocal<Map<String, DateFormat>>();
-
-    /**
-     * According to the specified format, Get a DateFormat
-     *
-     * @param format
-     * @return
-     */
-    public static DateFormat getDateFormat(String format) {
-        Map<String, DateFormat> map = tl.get();
-
-        if (map == null) {
-            map = new HashMap<String, DateFormat>();
-            tl.set(map);
-        }
-
-        if (StringUtils.isEmpty(format)) {
-            format = DEFAULT_FORMAT;
-        }
-
-        DateFormat ret = map.get(format);
-
-        if (ret == null) {
-            ret = new SimpleDateFormat(format);
-            map.put(format, ret);
-        }
-
-        return ret;
-    }
-
-    /**
-     * Get Default DateFormat
-     *
-     * @return
-     */
-    public static DateFormat getDateFormat() {
-        return getDateFormat(null);
-    }
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/RootContextPath.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/RootContextPath.java
deleted file mode 100644
index 2e9ed1d..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/RootContextPath.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.web.pulltool;
-
-public class RootContextPath {
-
-    private String contextPath;
-
-    public RootContextPath(String contextPath) {
-        this.contextPath = contextPath;
-    }
-
-    public String getURI(String uri) {
-        String prefix;
-        if (contextPath != null && contextPath.length() > 0 && !"/".equals(contextPath)) {
-            prefix = contextPath;
-        } else {
-            prefix = "";
-        }
-        if (uri.startsWith("/")) {
-            return prefix + uri;
-        } else {
-            return prefix + "/" + uri;
-        }
-    }
-
-}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/Tool.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/Tool.java
deleted file mode 100644
index bbf9450..0000000
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/web/pulltool/Tool.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * 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.web.pulltool;
-
-import com.alibaba.dubbo.common.Constants;
-import com.alibaba.dubbo.common.URL;
-import com.alibaba.dubbo.common.utils.NetUtils;
-import com.alibaba.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.admin.governance.service.OverrideService;
-import org.apache.dubbo.admin.governance.service.RouteService;
-import org.apache.dubbo.admin.registry.common.domain.*;
-import org.apache.dubbo.admin.registry.common.domain.Override;
-import org.apache.dubbo.admin.registry.common.route.ParseUtils;
-import org.apache.dubbo.admin.registry.common.route.RouteRule;
-import org.apache.dubbo.admin.registry.common.util.StringEscapeUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Array;
-import java.net.InetAddress;
-import java.net.URLEncoder;
-import java.net.UnknownHostException;
-import java.text.ParseException;
-import java.util.*;
-
-/**
- * Tool
- *
- */
-@Component
-public class Tool {
-
-    private static final Comparator<String> SIMPLE_NAME_COMPARATOR = new Comparator<String>() {
-        public int compare(String s1, String s2) {
-            if (s1 == null && s2 == null) {
-                return 0;
-            }
-            if (s1 == null) {
-                return -1;
-            }
-            if (s2 == null) {
-                return 1;
-            }
-            s1 = getSimpleName(s1);
-            s2 = getSimpleName(s2);
-            return s1.compareToIgnoreCase(s2);
-        }
-    };
-    @Autowired
-    private OverrideService overrideService;
-    @Autowired
-    private RouteService routeService;
-
-    public static String toStackTraceString(Throwable t) {
-        StringWriter writer = new StringWriter();
-        PrintWriter pw = new PrintWriter(writer);
-        t.printStackTrace(pw);
-        return writer.toString();
-    }
-
-    public static boolean isContains(String[] values, String value) {
-        return StringUtils.isContains(values, value);
-    }
-
-    public static boolean startWith(String value, String prefix) {
-        return value.startsWith(prefix);
-    }
-
-    public static String getHostPrefix(String address) {
-        if (address != null && address.length() > 0) {
-            String hostname = getHostName(address);
-            if (!address.startsWith(hostname)) {
-                return "(" + hostname + ")";
-            }
-        }
-        return "";
-    }
-
-    public static String getHostName(String address) {
-        return NetUtils.getHostName(address);
-    }
-
-    public static String getHostAddress(String address) {
-        if (address != null && address.length() > 0) {
-            int i = address.indexOf(':');
-            String port = address.substring(i + 1);
-            String hostname = NetUtils.getHostName(address);
-            if (!address.equals(hostname)) {
-                return hostname + ":" + port;
-            }
-        }
-        return "";
-    }
-
-    public static String getPath(String url) {
-        try {
-            return URL.valueOf(url).getPath();
-        } catch (Throwable t) {
-            return url;
-        }
-    }
-
-    public static String getAddress(String url) {
-        try {
-            return URL.valueOf(url).getAddress();
-        } catch (Throwable t) {
-            return url;
-        }
-    }
-
-    public static String getInterface(String service) {
-        if (service != null && service.length() > 0) {
-            int i = service.indexOf('/');
-            if (i >= 0) {
-                service = service.substring(i + 1);
-            }
-            i = service.lastIndexOf(':');
-            if (i >= 0) {
-                service = service.substring(0, i);
-            }
-        }
-        return service;
-    }
-
-    public static String getGroup(String service) {
-        if (service != null && service.length() > 0) {
-            int i = service.indexOf('/');
-            if (i >= 0) {
-                return service.substring(0, i);
-            }
-        }
-        return null;
-    }
-
-    public static String getVersion(String service) {
-        if (service != null && service.length() > 0) {
-            int i = service.lastIndexOf(':');
-            if (i >= 0) {
-                return service.substring(i + 1);
-            }
-        }
-        return null;
-    }
-
-    public static String getIP(String address) {
-        if (address != null && address.length() > 0) {
-            int i = address.indexOf("://");
-            if (i >= 0) {
-                address = address.substring(i + 3);
-            }
-            i = address.indexOf('/');
-            if (i >= 0) {
-                address = address.substring(0, i);
-            }
-            i = address.indexOf('@');
-            if (i >= 0) {
-                address = address.substring(i + 1);
-            }
-            i = address.indexOf(':');
-            if (i >= 0) {
-                address = address.substring(0, i);
-            }
-            if (address.matches("[a-zA-Z]+")) {
-                try {
-                    address = InetAddress.getByName(address).getHostAddress();
-                } catch (UnknownHostException e) {
-                }
-            }
-        }
-        return address;
-    }
-
-    public static String encode(String url) {
-        try {
-            return URLEncoder.encode(url, "UTF-8");
-        } catch (UnsupportedEncodingException e) {
-            return url;
-        }
-    }
-
-    public static String escape(String html) {
-        return StringEscapeUtils.escapeHtml(html);
-    }
-
-    public static String unescape(String html) {
-        return StringEscapeUtils.unescapeHtml(html);
-    }
-
-    public static String encodeUrl(String url) {
-        return URL.encode(url);
-    }
-
-    public static String decodeUrl(String url) {
-        return URL.decode(url);
-    }
-
-    public static String encodeHtml(String html) {
-        return StringEscapeUtils.escapeHtml(html);
-    }
-
-    public static int countMapValues(Map<?, ?> map) {
-        int total = 0;
-        if (map != null && map.size() > 0) {
-            for (Object value : map.values()) {
-                if (value != null) {
-                    if (value instanceof Number) {
-                        total += ((Number) value).intValue();
-                    } else if (value.getClass().isArray()) {
-                        total += Array.getLength(value);
-                    } else if (value instanceof Collection) {
-                        total += ((Collection<?>) value).size();
-                    } else if (value instanceof Map) {
-                        total += ((Map<?, ?>) value).size();
-                    } else {
-                        total += 1;
-                    }
-                }
-            }
-        }
-        return total;
-    }
-
-    public static List<String> sortSimpleName(List<String> list) {
-        if (list != null && list.size() > 0) {
-            Collections.sort(list, SIMPLE_NAME_COMPARATOR);
-        }
-        return list;
-    }
-
-    public static String getSimpleName(String name) {
-        if (name != null && name.length() > 0) {
-            final int ip = name.indexOf('/');
-            String v = ip != -1 ? name.substring(0, ip + 1) : "";
-
-            int i = name.lastIndexOf(':');
-            int j = (i >= 0 ? name.lastIndexOf('.', i) : name.lastIndexOf('.'));
-            if (j >= 0) {
-                name = name.substring(j + 1);
-            }
-            name = v + name;
-        }
-        return name;
-    }
-
-    public static String getParameter(String parameters, String key) {
-        String value = "";
-        if (parameters != null && parameters.length() > 0) {
-            String[] pairs = parameters.split("&");
-            for (String pair : pairs) {
-                String[] kv = pair.split("=");
-                if (key.equals(kv[0])) {
-                    value = kv[1];
-                    break;
-                }
-            }
-        }
-        return value;
-    }
-
-    public static Map<String, String> toParameterMap(String parameters) {
-        return StringUtils.parseQueryString(parameters);
-    }
-
-    /**
-     * Get the version value from the paramters parameter of provider
-     *
-     * @param parameters
-     * @return
-     */
-    public static String getVersionFromPara(String parameters) {
-        String version = "";
-        if (parameters != null && parameters.length() > 0) {
-            String[] params = parameters.split("&");
-            for (String o : params) {
-                String[] kv = o.split("=");
-                if ("version".equals(kv[0])) {
-                    version = kv[1];
-                    break;
-                }
-            }
-        }
-        return version;
-    }
-
-    public static boolean isProviderEnabled(Provider provider, List<Override> oList) {
-        for (Override o : oList) {
-            if (o.isMatch(provider)) {
-                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
-                String disbaled = params.get(Constants.DISABLED_KEY);
-                if (disbaled != null && disbaled.length() > 0) {
-                    return !"true".equals(disbaled);
-                }
-            }
-        }
-        return provider.isEnabled();
-    }
-
-    public static int getProviderWeight(Provider provider, List<Override> oList) {
-        for (Override o : oList) {
-            if (o.isMatch(provider)) {
-                Map<String, String> params = StringUtils.parseQueryString(o.getParams());
-                String weight = params.get(Constants.WEIGHT_KEY);
-                if (weight != null && weight.length() > 0) {
-                    return Integer.parseInt(weight);
-                }
-            }
-        }
-        return provider.getWeight();
-    }
-
-    public void setOverrideService(OverrideService overrideService) {
-        this.overrideService = overrideService;
-    }
-
-    public void setRouteService(RouteService routeService) {
-        this.routeService = routeService;
-    }
-
-    public String formatTimestamp(String timestamp) {
-        if (timestamp == null || timestamp.length() == 0) {
-            return "";
-        }
-        return formatDate(new Date(Long.valueOf(timestamp)));
-    }
-
-    //format date
-    public String formatDate(Date date) {
-        if (date == null) {
-            return "";
-        }
-        return DateFormatUtil.getDateFormat().format(date);
-    }
-
-    public String formatDate(Date date, String template) {
-        if (date == null || template == null) {
-            return "";
-        }
-        return DateFormatUtil.getDateFormat(template).format(date);
-    }
-
-    public boolean beforeNow(Date date) {
-        Date now = new Date();
-        if (now.after(date)) {
-            return true;
-        }
-        return false;
-    }
-
-    //minus of date
-    public long dateMinus(Date date1, Date date2) {
-        return (date1.getTime() - date1.getTime()) / 1000;
-    }
-
-    public boolean isProviderEnabled(Provider provider) {
-        List<Override> oList = overrideService.findByServiceAndAddress(provider.getService(), provider.getAddress());
-        return isProviderEnabled(provider, oList);
-    }
-
-    public int getProviderWeight(Provider provider) {
-        List<Override> oList = overrideService.findByServiceAndAddress(provider.getService(), provider.getAddress());
-        return getProviderWeight(provider, oList);
-    }
-
-    public boolean isInBlackList(Consumer consumer) {
-        String service = consumer.getService();
-        List<Route> routes = routeService.findForceRouteByService(service);
-        if (routes == null || routes.size() == 0) {
-            return false;
-        }
-        String ip = getIP(consumer.getAddress());
-        for (Route route : routes) {
-            try {
-                if (!route.isEnabled()) {
-                    continue;
-                }
-                String filterRule = route.getFilterRule();
-                if (filterRule == null || filterRule.length() == 0 || "false".equals(filterRule)) {
-                    Map<String, RouteRule.MatchPair> rule = RouteRule.parseRule(route.getMatchRule());
-                    RouteRule.MatchPair pair = rule.get("consumer.host");
-                    if (pair == null) {
-                        pair = rule.get("host");
-                    }
-                    if (pair != null) {
-                        if (pair.getMatches() != null && pair.getMatches().size() > 0) {
-                            for (String host : pair.getMatches()) {
-                                if (ParseUtils.isMatchGlobPattern(host, ip)) {
-                                    return true;
-                                }
-                            }
-                        }
-                        if (pair.getUnmatches() != null && pair.getUnmatches().size() > 0) {
-                            boolean forbid = true;
-                            for (String host : pair.getUnmatches()) {
-                                if (ParseUtils.isMatchGlobPattern(host, ip)) {
-                                    forbid = false;
-                                }
-                            }
-                            if (forbid) {
-                                return true;
-                            }
-                        }
-                    }
-                }
-            } catch (ParseException e) {
-                throw new RuntimeException(e.getMessage(), e);
-            }
-        }
-        return false;
-    }
-
-    public String getConsumerMock(Consumer consumer) {
-        return getOverridesMock(consumer.getOverrides());
-    }
-
-    public String getOverridesMock(List<Override> overrides) {
-        if (overrides != null && overrides.size() > 0) {
-            for (Override override : overrides) {
-                Map<String, String> params = StringUtils.parseQueryString(override.getParams());
-                String mock = params.get("mock");
-                if (mock != null && mock.length() > 0) {
-                    return mock;
-                }
-            }
-        }
-        return "";
-    }
-
-    public boolean checkUrl(User user, String uri) {
-        return true;
-        /*if(!User.ROOT.equals(user.getRole())){
-            List<String> disabledSysinfo = new ArrayList<String>();
-            List<String> disabledSysmanage = new ArrayList<String>();
-            Map<String, Boolean> features = daoCache.getFeatures();
-            if (features.size() > 0){
-                for(Entry<String,Boolean> feature : features.entrySet()){
-                    if(feature.getKey().startsWith("Sysinfo") && !feature.getValue()){
-                        disabledSysinfo.add(feature.getKey().replace(".", "/").toLowerCase());
-                    }else if(feature.getKey().startsWith("Sysmanage") && !feature.getValue()){
-                        disabledSysmanage.add(feature.getKey().replace(".", "/").toLowerCase());
-                    }
-                }
-                if(uri.startsWith("/sysinfo")){
-                    for(String disabled : disabledSysinfo){
-                        if (uri.contains(disabled)){
-                            return false;
-                        }
-                    }
-                }
-                if(uri.startsWith("/sysmanage")){
-                    for(String disabled : disabledSysmanage){
-                        if (uri.contains(disabled)){
-                            return false;
-                        }
-                    }
-                }
-            }else{
-                return true;
-            }
-        }
-        return true;*/
-    }
-}
diff --git a/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.config.GovernanceConfiguration b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.config.GovernanceConfiguration
new file mode 100644
index 0000000..12783c4
--- /dev/null
+++ b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.config.GovernanceConfiguration
@@ -0,0 +1,2 @@
+zookeeper=org.apache.dubbo.admin.data.config.impl.ZookeeperConfiguration
+apollo=org.apache.dubbo.admin.data.config.impl.ZookeeperConfiguration
diff --git a/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.metadata.MetaDataCollector b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.metadata.MetaDataCollector
new file mode 100644
index 0000000..0009f5d
--- /dev/null
+++ b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.metadata.MetaDataCollector
@@ -0,0 +1,2 @@
+zookeeper=org.apache.dubbo.admin.data.metadata.impl.ZookeeperMetaDataCollector
+redis=org.apache.dubbo.admin.data.metadata.impl.RedisMetaDataCollector
\ No newline at end of file
diff --git a/dubbo-admin-backend/src/main/resources/application.properties b/dubbo-admin-backend/src/main/resources/application.properties
index 12809f4..892d167 100644
--- a/dubbo-admin-backend/src/main/resources/application.properties
+++ b/dubbo-admin-backend/src/main/resources/application.properties
@@ -15,5 +15,10 @@
 # limitations under the License.
 #
 
-dubbo.registry.address=zookeeper://127.0.0.1:2181
 dubbo.registry.group=dubbo
+dubbo.configcenter=zookeeper://127.0.0.1:2181
+dubbo.apollo.token=e16e5cd903fd0c97a116c873b448544b9d086de9
+dubbo.apollo.appId=test
+dubbo.apollo.env=dev
+dubbo.apollo.cluster=default
+dubbo.apollo.namespace=dubbo
diff --git a/dubbo-admin-backend/src/main/resources/dubbo-admin.xml b/dubbo-admin-backend/src/main/resources/dubbo-admin.xml
deleted file mode 100644
index d0dce31..0000000
--- a/dubbo-admin-backend/src/main/resources/dubbo-admin.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~ 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.
-  -->
-
-<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
-       xmlns="http://www.springframework.org/schema/beans"
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
-       http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
-
-    <dubbo:application name="dubbo-admin"/>
-    <dubbo:registry address="${dubbo.registry.address}" group="${dubbo.registry.group}"/>
-    <dubbo:reference id="registryService" interface="com.alibaba.dubbo.registry.RegistryService" check="false"/>
-</beans>
\ No newline at end of file
diff --git a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/governance/util/UrlUtilsTest.java b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/governance/util/UrlUtilsTest.java
index 0a76271..faf4bd7 100644
--- a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/governance/util/UrlUtilsTest.java
+++ b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/governance/util/UrlUtilsTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.admin.governance.util;
 
+import org.apache.dubbo.admin.common.util.UrlUtils;
 import org.junit.Assert;
 import org.junit.Test;
 
diff --git a/dubbo-admin-backend/src/test/main/java/org/apache/dubbo/admin/common/util/YamlParserTest.java b/dubbo-admin-backend/src/test/main/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
new file mode 100644
index 0000000..80604d7
--- /dev/null
+++ b/dubbo-admin-backend/src/test/main/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.dto.DynamicConfigDTO;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class YamlParserTest {
+
+    private String streamToString(InputStream stream) {
+        try {
+            byte[] bytes = new byte[stream.available()];
+            stream.read(bytes);
+            return new String(bytes);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Test
+    public void parseLoadBalanceTest() {
+        InputStream yamlStream = this.getClass().getResourceAsStream("/LoadBalance.yml");
+        DynamicConfigDTO overrideDTO = YamlParser.loadObject(streamToString(yamlStream), DynamicConfigDTO.class);
+        if ("weight".equals(null)) {
+            System.out.println("aa");
+        }
+        overrideDTO.getConfigs();
+    }
+
+
+}
diff --git a/dubbo-admin-backend/src/test/main/resources/LoadBalance.yml b/dubbo-admin-backend/src/test/main/resources/LoadBalance.yml
new file mode 100644
index 0000000..bbf1742
--- /dev/null
+++ b/dubbo-admin-backend/src/test/main/resources/LoadBalance.yml
@@ -0,0 +1,15 @@
+---
+apiVersion: v2.7
+scope: application
+key: governance-consumer
+enabled: false
+configs:
+  - addresses: ["0.0.0.0:20880"]
+    side: provider
+    parameters:
+      timeout: 2000
+  - type: balancing
+    enabled: true
+    parameters:
+      method: '*'
+      strategy: random
diff --git a/dubbo-admin-frontend/src/api/menu.js b/dubbo-admin-frontend/src/api/menu.js
index 2aadcfc..05f1660 100644
--- a/dubbo-admin-frontend/src/api/menu.js
+++ b/dubbo-admin-frontend/src/api/menu.js
@@ -23,6 +23,7 @@
     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/ServiceDetail.vue b/dubbo-admin-frontend/src/components/ServiceDetail.vue
index b671b4e..74130ec 100644
--- a/dubbo-admin-frontend/src/components/ServiceDetail.vue
+++ b/dubbo-admin-frontend/src/components/ServiceDetail.vue
@@ -91,11 +91,15 @@
         <v-data-table
           class="elevation-1"
           :headers="metaHeaders"
-          :items="metadata">
+          :items="methodMetaData">
           <template slot="items" slot-scope="props">
-            <td>{{props.item.method}}</td>
-            <td>{{props.item.parameter}}</td>
-            <td>{{props.item.returnType}}</td>
+            <td>{{props.item.name}}</td>
+            <td>
+              <v-chip v-for="(type, index) in props.item.parameterTypes" :key="type.id" label>{{type}}</v-chip>
+            </td>
+            <td>
+              <v-chip label>{{props.item.returnType}}</v-chip>
+            </td>
           </template>
         </v-data-table>
       </v-flex>
@@ -163,7 +167,7 @@
       },
       providerDetails: [],
       consumerDetails: [],
-      metadata: [],
+      methodMetaData: [],
       basic: []
     }),
     methods: {
@@ -172,6 +176,9 @@
             .then(response => {
               this.providerDetails = response.data.providers
               this.consumerDetails = response.data.consumers
+              if (response.data.metadata !== null) {
+                this.methodMetaData = response.data.metadata.methods
+              }
             })
       },
       getIp: function (address) {
@@ -179,6 +186,13 @@
       },
       getPort: function (address) {
         return address.split(':')[1]
+      },
+      getParameters: function (parameterTypes) {
+        let result = ''
+        for (let i = 0; i < parameterTypes.length; i++) {
+          result = result + parameterTypes[i] + ' '
+        }
+        return result.trim()
       }
     },
     mounted: function () {
diff --git a/dubbo-admin-frontend/src/components/ServiceSearch.vue b/dubbo-admin-frontend/src/components/ServiceSearch.vue
index 02f2928..3725115 100644
--- a/dubbo-admin-frontend/src/components/ServiceSearch.vue
+++ b/dubbo-admin-frontend/src/components/ServiceSearch.vue
@@ -37,24 +37,23 @@
                   label="Search Dubbo Services"
                   @keyup.enter="submit"
                 ></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>
@@ -80,8 +79,36 @@
                 <td>{{props.item.group}}</td>
                 <td>{{props.item.version}}</td>
                 <td>{{props.item.appName}}</td>
-                <td class="text-xs-center px-0"><v-btn small color='primary' :href='getHref(props.item.service, props.item.appName,
-                                                                                            props.item.group, props.item.version)'>Detail</v-btn></td>
+                <td class="text-xs-center px-0" nowrap>
+                  <v-btn
+                    small
+                    color='primary'
+                    :href='getHref(props.item.service, props.item.appName, props.item.group, props.item.version)'
+                  >
+                    Detail
+                  </v-btn>
+                  <v-menu
+                  >
+                    <v-btn
+                      slot="activator"
+                      color="primary"
+                      small
+                      dark
+                    >
+                      More
+                      <v-icon>expand_more</v-icon>
+                    </v-btn>
+                    <v-list>
+                      <v-list-tile
+                        v-for="(item, i) in options"
+                        :key="i"
+                        :href='governanceHref(item.value, props.item.service, props.item.group, props.item.version)'
+                      >
+                        <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      </v-list-tile>
+                    </v-list>
+                  </v-menu>
+                </td>
               </template>
             </v-data-table>
           </template>
@@ -95,10 +122,30 @@
   export default {
     data: () => ({
       items: [
-        {id: 0, title: 'service name', value: 'serviceName'},
+        {id: 0, title: 'service name', value: 'service'},
         {id: 1, title: 'IP', value: 'ip'},
         {id: 2, title: 'application', value: 'application'}
       ],
+      options: [
+        { title: 'Routing Rule',
+          value: 'routingRule'
+        },
+        { title: 'Tag Rule',
+          value: 'tagRule'
+        },
+        { title: 'Dynamic Config',
+          value: 'config'
+        },
+        { title: 'Access Control',
+          value: 'access'
+        },
+        { title: 'Weight Adjust',
+          value: 'weight'
+        },
+        { title: 'Load Balance',
+          value: 'loadbalance'
+        }
+      ],
       timerID: null,
       loading: false,
       selected: 0,
@@ -191,6 +238,20 @@
         }
         return '/#/serviceDetail?' + query
       },
+      governanceHref: function (type, service, group, version) {
+        let base = '/#/governance/' + type
+        let query = service
+        if (group !== null) {
+          query = group + '/' + query
+        }
+        if (version !== null) {
+          query = query + ':' + version
+        }
+        if (type === 'tagRule') {
+          return base + '?application=' + query
+        }
+        return base + '?service=' + query
+      },
       submit () {
         this.filter = document.querySelector('#serviceSearch').value.trim()
         if (this.filter) {
@@ -229,7 +290,7 @@
       })
       if (filter != null && pattern != null) {
         this.filter = filter
-        if (pattern === 'serviceName') {
+        if (pattern === 'service') {
           this.selected = 0
         } else if (pattern === 'application') {
           this.selected = 2
@@ -237,10 +298,16 @@
           this.selected = 1
         }
         this.search(filter, pattern, false)
+      } else {
+        // display all existing services by default
+        this.filter = '*'
+        this.selected = 0
+        pattern = 'service'
+        this.search(this.filter, pattern, true)
       }
       this.$axios.get('/service', {
         params: {
-          pattern: 'serviceName',
+          pattern: 'service',
           filter: '*'
         }
       }).then(response => {
diff --git a/dubbo-admin-frontend/src/components/governance/AccessControl.vue b/dubbo-admin-frontend/src/components/governance/AccessControl.vue
index 8284639..bfbb274 100644
--- a/dubbo-admin-frontend/src/components/governance/AccessControl.vue
+++ b/dubbo-admin-frontend/src/components/governance/AccessControl.vue
@@ -20,10 +20,40 @@
                fluid>
     <v-layout row
               wrap>
-      <v-flex xs12>
-        <search v-model="filter"
-                :submit="search"
-                label="Search Access Control 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="search" color="primary" large>Search</v-btn>
+
+              </v-layout>
+            </v-form>
+          </v-card-text>
+        </v-card>
       </v-flex>
     </v-layout>
 
@@ -42,9 +72,8 @@
                  class="mb-2">CREATE</v-btn>
         </v-toolbar>
 
-        <v-card-text class="pa-0">
-          <v-data-table v-model="selected"
-                        :headers="headers"
+        <v-card-text class="pa-0" v-if="selected == 0">
+          <v-data-table :headers="serviceHeaders"
                         :items="accesses"
                         :loading="loading"
                         hide-actions
@@ -73,6 +102,36 @@
             </template>
           </v-data-table>
         </v-card-text>
+        <v-card-text class="pa-0" v-if="selected == 1">
+          <v-data-table :headers="appHeaders"
+                        :items="accesses"
+                        :loading="loading"
+                        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-icon small
+                          class="mr-2"
+                          color="blue"
+                          slot="activator"
+                          @click="toEdit(props.item)">edit</v-icon>
+                  <span>Edit</span>
+                </v-tooltip>
+                <v-tooltip bottom>
+                  <v-icon small
+                          class="mr-2"
+                          slot="activator"
+                          color="red"
+                          @click="toDelete(props.item)">delete</v-icon>
+                  <span>Delete</span>
+                </v-tooltip>
+              </td>
+            </template>
+          </v-data-table>
+        </v-card-text>
       </v-card>
     </v-flex>
 
@@ -87,9 +146,14 @@
           <v-form ref="modalForm">
             <v-text-field label="Service Unique ID"
                           hint="A service ID in form of group/service:version, group and version are optional"
-                          :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>
@@ -134,10 +198,14 @@
 export default {
   name: 'AccessControl',
   data: () => ({
-    selected: [],
+    items: [
+      {id: 0, title: 'service name', value: 'service'},
+      {id: 1, title: 'application', value: 'application'}
+    ],
+    selected: 0,
     filter: null,
     loading: false,
-    headers: [
+    serviceHeaders: [
       {
         text: 'Service Name',
         value: 'service',
@@ -150,8 +218,20 @@
         width: '115px'
       }
     ],
+    appHeaders: [
+      {
+        text: 'Application Name',
+        value: 'application',
+        align: 'left'
+      },
+      {
+        text: 'Operation',
+        value: 'operation',
+        sortable: false,
+        width: '115px'
+      }
+    ],
     accesses: [],
-    required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
     modal: {
       enable: false,
       title: 'Create New',
@@ -159,6 +239,7 @@
       click: () => {},
       id: null,
       service: null,
+      application: null,
       content: '',
       template:
         'blacklist:\n' +
@@ -182,25 +263,32 @@
   }),
   methods: {
     search () {
-      if (this.filter == null) {
-        this.filter = ''
+      this.filter = document.querySelector('#serviceSearch').value.trim()
+      if (!this.filter) {
+        return
       }
+      let type = this.items[this.selected].value
       this.loading = true
-      this.$router.push({
-        path: 'access',
-        query: { service: this.filter }
-      })
-      this.$axios.get('/rules/access', {
-        params: {
-          service: this.filter
-        }
-      }).then(response => {
-        this.accesses = response.data
-        this.loading = false
-      }).catch(error => {
-        this.showSnackbar('error', error.response.data.message)
-        this.loading = false
-      })
+      if (this.selected === 0) {
+        this.$router.push({
+          path: 'access',
+          query: {service: this.filter}
+        })
+      } else if (this.selected === 1) {
+        this.$router.push({
+          path: 'access',
+          query: {application: this.filter}
+        })
+      }
+      let url = '/rules/access/?' + type + '=' + this.filter
+      this.$axios.get(url)
+        .then(response => {
+          this.accesses = response.data
+          this.loading = false
+        }).catch(error => {
+          this.showSnackbar('error', error.response.data.message)
+          this.loading = false
+        })
     },
     closeModal () {
       this.modal.enable = false
@@ -219,47 +307,88 @@
     createItem () {
       let doc = yaml.load(this.modal.content)
       this.filter = ''
-      if (this.modal.service === '' || this.modal.service === null) {
+      if (!this.modal.service && !this.modal.application) {
+        this.$notify.error('Either service or application is needed')
         return
       }
+      let vm = this
       this.$axios.post('/rules/access', {
         service: this.modal.service,
+        application: this.modal.application,
         whitelist: doc.whitelist,
         blacklist: doc.blacklist
       }).then(response => {
-        this.closeModal()
-        this.search(this.filter)
+        if (response.status === 201) {
+          if (vm.modal.service) {
+            vm.selected = 0
+            vm.filter = vm.modal.service
+          } else {
+            vm.selected = 1
+            vm.filter = vm.modal.application
+          }
+          this.search()
+          this.closeModal()
+        }
         this.showSnackbar('success', 'Create success')
       }).catch(error => this.showSnackbar('error', error.response.data.message))
     },
     toEdit (item) {
+      let itemId = null
+      if (this.selected === 0) {
+        itemId = item.service
+      } else {
+        itemId = item.application
+      }
+      if (itemId.includes('/')) {
+        itemId = itemId.replace('/', '*')
+      }
       Object.assign(this.modal, {
         enable: true,
         title: 'Edit',
         saveBtn: 'Update',
         click: this.editItem,
-        id: item.id,
+        id: itemId,
         service: item.service,
+        application: item.application,
         content: yaml.safeDump({blacklist: item.blacklist, whitelist: item.whitelist})
       })
     },
     editItem () {
       let doc = yaml.load(this.modal.content)
+      let vm = this
       this.$axios.put('/rules/access/' + this.modal.id, {
         whitelist: doc.whitelist,
-        blacklist: doc.blacklist
+        blacklist: doc.blacklist,
+        application: this.modal.application,
+        service: this.modal.service
+
       }).then(response => {
-        this.closeModal()
-        this.search(this.filter)
+        if (response.status === 200) {
+          if (vm.modal.service) {
+            vm.selected = 0
+            vm.filter = vm.modal.service
+          } else {
+            vm.selected = 1
+            vm.filter = vm.modal.application
+          }
+          vm.closeModal()
+          vm.search()
+        }
         this.showSnackbar('success', 'Update success')
       }).catch(error => this.showSnackbar('error', error.response.data.message))
     },
     toDelete (item) {
+      let itemId = null
+      if (this.selected === 0) {
+        itemId = item.service
+      } else {
+        itemId = item.application
+      }
       Object.assign(this.confirm, {
         enable: true,
         title: 'Are you sure to Delete Access Control',
-        text: `Service: ${item.service}`,
-        id: item.id
+        text: `Id: ${itemId}`,
+        id: itemId
       })
     },
     deleteItem (id) {
@@ -272,15 +401,24 @@
     showSnackbar (color, message) {
       this.$notify(message, color)
       this.confirm.enable = false
-      this.selected = []
+    }
+  },
+  computed: {
+    queryBy () {
+      return 'by ' + this.items[this.selected].title
     }
   },
   mounted () {
     let query = this.$route.query
     if ('service' in query) {
       this.filter = query['service']
-      this.search()
+      this.selected = 0
     }
+    if ('application' in query) {
+      this.filter = query['application']
+      this.selected = 1
+    }
+    this.search()
   },
   components: {
     AceEditor,
diff --git a/dubbo-admin-frontend/src/components/governance/LoadBalance.vue b/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
index 15b2dd0..650cc8f 100644
--- a/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
+++ b/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
@@ -18,9 +18,40 @@
 <template>
   <v-container grid-list-xl fluid >
     <v-layout row wrap>
-      <v-flex xs12 >
-        <search v-model="filter" :submit="submit" label="Search Load Balance 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 Balancing 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>
 
@@ -32,9 +63,9 @@
           <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"
+            :headers="serviceHeaders"
             :items="loadBalances"
             hide-actions
             class="elevation-0"
@@ -53,6 +84,28 @@
             </template>
           </v-data-table>
         </v-card-text>
+
+        <v-card-text class="pa-0" v-if="selected == 1">
+          <v-data-table
+            :headers="appHeaders"
+            :items="loadBalances"
+            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.methodName }}</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)">
+                    {{op.icon}}
+                  </v-icon>
+                  <span>{{op.tooltip}}</span>
+                </v-tooltip>
+              </td>
+            </template>
+          </v-data-table>
+        </v-card-text>
       </v-card>
     </v-flex>
 
@@ -65,9 +118,13 @@
           <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"/>
 
@@ -105,6 +162,11 @@
       Search
     },
     data: () => ({
+      items: [
+        {id: 0, title: 'service name', value: 'service'},
+        {id: 1, title: 'application', value: 'application'}
+      ],
+      selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
       ruleKeys: ['method', 'strategy'],
       pattern: 'Service',
@@ -125,13 +187,12 @@
       ],
       loadBalances: [
       ],
-      required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
       template:
-        'methodName: sayHello  # 0 for all methods\n' +
+        'methodName: *  # * for all methods\n' +
         'strategy:  # leastactive, random, roundrobin',
       ruleText: '',
       readonly: false,
-      headers: [
+      serviceHeaders: [
         {
           text: 'Service Name',
           value: 'service',
@@ -149,23 +210,46 @@
           sortable: false,
           width: '115px'
         }
+      ],
+      appHeaders: [
+        {
+          text: 'Application Name',
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: 'Method',
+          value: 'method',
+          align: 'left'
+
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
       ]
     }),
     methods: {
       submit: function () {
+        this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
       },
       search: function (filter, rewrite) {
-        this.$axios.get('/rules/balancing', {
-          params: {
-            service: filter
-          }
-        }).then(response => {
-          this.loadBalances = response.data
-          if (rewrite) {
-            this.$router.push({path: 'loadbalance', query: {service: filter}})
-          }
-        })
+        let type = this.items[this.selected].value
+        let url = '/rules/balancing/?' + type + '=' + filter
+        this.$axios.get(url)
+          .then(response => {
+            this.loadBalances = response.data
+            if (rewrite) {
+              if (this.selected === 0) {
+                this.$router.push({path: 'loadbalance', query: {service: filter}})
+              } else if (this.selected === 1) {
+                this.$router.push({path: 'loadbalance', query: {application: filter}})
+              }
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -188,12 +272,16 @@
         this.warn = false
       },
       saveItem: function () {
+        this.ruleText = this.verifyRuleText(this.ruleText)
         let balancing = yaml.safeLoad(this.ruleText)
-        if (this.service === '') {
+        if (!this.service && !this.application) {
+          this.$notify.error('Either service or application is needed')
           return
         }
+        let vm = this
         balancing.service = this.service
-        if (this.updateId !== '') {
+        balancing.application = this.application
+        if (this.updateId) {
           if (this.updateId === 'close') {
             this.closeDialog()
           } else {
@@ -201,8 +289,15 @@
             this.$axios.put('/rules/balancing/' + balancing.id, balancing)
               .then(response => {
                 if (response.status === 200) {
-                  this.search(this.service, true)
-                  this.filter = this.service
+                  if (vm.service) {
+                    vm.selected = 0
+                    vm.search(vm.service, true)
+                    vm.filter = vm.service
+                  } else {
+                    vm.selected = 1
+                    vm.search(vm.application, true)
+                    vm.filter = vm.application
+                  }
                   this.closeDialog()
                   this.$notify.success('Update success')
                 }
@@ -212,8 +307,15 @@
           this.$axios.post('/rules/balancing', balancing)
             .then(response => {
               if (response.status === 201) {
-                this.search(this.service, true)
-                this.filter = this.service
+                if (vm.service) {
+                  vm.selected = 0
+                  vm.search(vm.service, true)
+                  vm.filter = vm.service
+                } else {
+                  vm.selected = 1
+                  vm.search(vm.application, true)
+                  vm.filter = vm.application
+                }
                 this.closeDialog()
                 this.$notify.success('Create success')
               }
@@ -221,9 +323,18 @@
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = ''
+        if (this.selected === 0) {
+          itemId = item.service
+        } else {
+          itemId = item.application
+        }
+        if (itemId.includes('/')) {
+          itemId = itemId.replace('/', '*')
+        }
         switch (icon) {
           case 'visibility':
-            this.$axios.get('/rules/balancing/' + item.id)
+            this.$axios.get('/rules/balancing/' + itemId)
               .then(response => {
                 let balancing = response.data
                 this.handleBalance(balancing, true)
@@ -231,22 +342,24 @@
               })
             break
           case 'edit':
-            this.$axios.get('/rules/balancing/' + item.id)
+            this.$axios.get('/rules/balancing/' + itemId)
               .then(response => {
                 let balancing = response.data
                 this.handleBalance(balancing, false)
-                this.updateId = item.id
+                this.updateId = itemId
               })
             break
           case 'delete':
-            this.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + item.service)
+            this.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + itemId)
             this.warnStatus.operation = 'delete'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
         }
       },
       handleBalance: function (balancing, readonly) {
         this.service = balancing.service
+        this.application = balancing.application
         delete balancing.service
+        delete balancing.application
         delete balancing.id
         this.ruleText = yaml.safeDump(balancing)
         this.readonly = readonly
@@ -264,23 +377,44 @@
               this.$notify.success('Delete success')
             }
           })
+      },
+      verifyRuleText: function (ruleText) {
+        let lines = ruleText.split('\n')
+        for (let i = 0; i < lines.length; i++) {
+          if (lines[i].includes('methodName') && lines[i].includes('*')) {
+            lines[i] = "methodName: '*'"
+          }
+        }
+        let newText = lines.join('\n')
+        return newText
       }
     },
     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/Overrides.vue b/dubbo-admin-frontend/src/components/governance/Overrides.vue
index 9c0c9e2..89c9aa4 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: 'service'},
+        {id: 1, title: 'application', value: 'application'}
+      ],
+      selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
       pattern: 'Service',
       filter: '',
@@ -117,24 +180,22 @@
       warnStatus: {},
       height: 0,
       operations: operations,
-      configs: [
+      serviceConfigs: [
       ],
-      required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
+      appConfigs: [
+      ],
       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\'',
+
+        'configVersion: v2.7\n' +
+        'enabled: true\n' +
+        'configs: \n' +
+        '  - addresses: [0.0.0.0]  # 0.0.0.0 for all addresses\n' +
+        '    side: consumer        # effective side, consumer or addresses\n' +
+        '    parameters: \n' +
+        '      timeout: 6000       # dynamic config parameter\n',
       ruleText: '',
       readonly: false,
-      headers: [
+      serviceHeaders: [
         {
           text: 'Service Name',
           value: 'service',
@@ -146,23 +207,44 @@
           sortable: false,
           width: '115px'
         }
+      ],
+      appHeaders: [
+        {
+          text: 'Application Name',
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
       ]
     }),
     methods: {
       submit: function () {
+        this.filter = document.querySelector('#serviceSearch').value.trim()
         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: {service: filter}})
+              } else if (this.selected === 1) {
+                this.$router.push({path: 'config', query: {application: filter}})
+              }
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -186,19 +268,29 @@
       },
       saveItem: function () {
         let override = yaml.safeLoad(this.ruleText)
-        if (this.service === '') {
+        if (!this.service && !this.application) {
+          this.$notify.error('Either service or application is needed')
           return
         }
         override.service = this.service
-        if (this.updateId !== '') {
+        override.application = this.application
+        let vm = this
+        if (this.updateId) {
           if (this.updateId === 'close') {
             this.closeDialog()
           } else {
             this.$axios.put('/rules/override/' + this.updateId, override)
               .then(response => {
                 if (response.status === 200) {
-                  this.search(this.service, true)
-                  this.filter = this.service
+                  if (vm.service) {
+                    vm.selected = 0
+                    vm.search(this.service, true)
+                    vm.filter = vm.service
+                  } else {
+                    vm.selected = 1
+                    vm.search(vm.application, true)
+                    vm.filter = vm.application
+                  }
                   this.$notify.success('Update success')
                   this.closeDialog()
                 }
@@ -208,8 +300,15 @@
           this.$axios.post('/rules/override', override)
             .then(response => {
               if (response.status === 201) {
-                this.search(this.service, true)
-                this.filter = this.service
+                if (this.service) {
+                  vm.selected = 0
+                  vm.search(vm.service, true)
+                  vm.filter = vm.service
+                } else {
+                  vm.selected = 1
+                  vm.search(vm.application, true)
+                  vm.filter = vm.application
+                }
                 this.$notify.success('Create success')
                 this.closeDialog()
               }
@@ -217,9 +316,18 @@
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = ''
+        if (this.selected === 0) {
+          itemId = item.service
+        } else {
+          itemId = item.application
+        }
+        if (itemId.includes('/')) {
+          itemId = itemId.replace('/', '*')
+        }
         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,33 +335,39 @@
               })
             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
+        for (let i = 0; i < config.configs.length; i++) {
+          delete config.configs[i].enabled
+        }
+        this.removeEmpty(config)
         this.ruleText = yaml.safeDump(config)
         this.readonly = readonly
         this.dialog = true
@@ -261,6 +375,15 @@
       setHeight: function () {
         this.height = window.innerHeight * 0.5
       },
+      removeEmpty: function (obj) {
+        Object.keys(obj).forEach(key => {
+          if (obj[key] && typeof obj[key] === 'object') {
+            this.removeEmpty(obj[key])
+          } else if (obj[key] == null) {
+            delete obj[key]
+          }
+        })
+      },
       deleteItem: function (warnStatus) {
         let id = warnStatus.id
         let operation = warnStatus.operation
@@ -297,18 +420,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..d87ae45 100644
--- a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
+++ b/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
@@ -17,12 +17,43 @@
 
 <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 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,17 +62,37 @@
           <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"
           >
             <template slot="items" slot-scope="props">
               <td class="text-xs-left">{{ props.item.service }}</td>
               <td class="text-xs-left">{{ props.item.group }}</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-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.enabled }}</td>
               <td class="text-xs-center px-0">
                 <v-tooltip bottom v-for="op in operations" :key="op.id">
@@ -66,7 +117,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,16 +155,19 @@
 <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: 'service'},
+        {id: 1, title: 'application', value: 'application'}
+      ],
+      selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
-      ruleKeys: ['enabled', 'force', 'dynamic', 'runtime', 'group', 'version', 'rule', 'priority'],
+      ruleKeys: ['enabled', 'force', 'runtime', 'group', 'version', 'rule'],
       pattern: 'Service',
       filter: '',
       dialog: false,
@@ -127,24 +180,37 @@
       warnStatus: {},
       height: 0,
       operations: operations,
-      routingRules: [
+      serviceRoutingRules: [
       ],
-      required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
+      appRoutingRules: [
+      ],
       template:
-        'enabled: true/false\n' +
-        'priority:\n' +
-        'runtime: false/true\n' +
-        'force: true/false\n' +
-        'dynamic: true/false\n' +
+        'enabled: true\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: 'Enabled',
+          value: 'enabled',
+          sortable: false
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
+      ],
+      serviceHeaders: [
         {
           text: 'Service Name',
           value: 'service',
@@ -157,11 +223,6 @@
 
         },
         {
-          text: 'Priority',
-          value: 'priority',
-          sortable: false
-        },
-        {
           text: 'Enabled',
           value: 'enabled',
           sortable: false
@@ -176,19 +237,27 @@
     }),
     methods: {
       submit: function () {
+        this.filter = document.querySelector('#serviceSearch').value.trim()
         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: {service: filter}})
+              } else if (this.selected === 1) {
+                this.$router.push({path: 'routingRule', query: {application: filter}})
+              }
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -213,30 +282,48 @@
       },
       saveItem: function () {
         let rule = yaml.safeLoad(this.ruleText)
-        if (rule.service === '') {
+        if (!this.service && !this.application) {
+          this.$notify.error('Either service or application is needed')
           return
         }
+        let vm = this
         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)
+                  if (vm.service) {
+                    vm.selected = 0
+                    vm.search(vm.service, true)
+                    vm.filter = vm.service
+                  } else {
+                    vm.selected = 1
+                    vm.search(vm.application, true)
+                    vm.filter = vm.application
+                  }
                   this.closeDialog()
                   this.$notify.success('Update success')
                 }
               })
           }
         } 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)
-                this.filter = this.service
+                if (vm.service) {
+                  vm.selected = 0
+                  vm.search(vm.service, true)
+                  vm.filter = vm.service
+                } else {
+                  vm.selected = 1
+                  vm.search(vm.application, true)
+                  vm.filter = vm.application
+                }
                 this.closeDialog()
                 this.$notify.success('Create success')
               }
@@ -247,48 +334,58 @@
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = ''
+        if (this.selected === 0) {
+          itemId = item.service
+        } else {
+          itemId = item.application
+        }
+        if (itemId.includes('/')) {
+          itemId = itemId.replace('/', '*')
+        }
         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)
+            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.openWarn(' Are you sure to block Routing Rule', 'service: ' + itemId)
             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.openWarn(' Are you sure to enable Routing Rule', 'service: ' + itemId)
             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.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + itemId)
             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
+        delete conditionRoute.priority
+        this.ruleText = yaml.safeDump(conditionRoute)
         this.readonly = readonly
         this.dialog = true
       },
@@ -299,7 +396,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 +405,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 +414,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 +428,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/TagRule.vue b/dubbo-admin-frontend/src/components/governance/TagRule.vue
new file mode 100644
index 0000000..17b3bb2
--- /dev/null
+++ b/dubbo-admin-frontend/src/components/governance/TagRule.vue
@@ -0,0 +1,329 @@
+<!--
+  - 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.
+  -->
+
+<template>
+  <v-container grid-list-xl fluid >
+    <v-layout row wrap>
+      <v-flex xs12 >
+        <search id="serviceSearch" v-model="filter" :submit="submit" label="Search Routing Rule by application name"></search>
+      </v-flex>
+    </v-layout>
+    <v-flex lg12>
+      <v-card>
+        <v-toolbar flat color="transparent" class="elevation-0">
+          <v-toolbar-title><span class="headline">Search Result</span></v-toolbar-title>
+          <v-spacer></v-spacer>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
+        </v-toolbar>
+
+        <v-card-text class="pa-0" >
+          <v-data-table
+            :headers="headers"
+            :items="tagRoutingRules"
+            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.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>
+
+    <v-dialog   v-model="dialog" width="800px" persistent >
+      <v-card>
+        <v-card-title class="justify-center">
+          <span class="headline">Create New Routing Rule</span>
+        </v-card-title>
+        <v-card-text >
+          <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>
+
+        </v-card-text>
+        <v-card-actions>
+          <v-spacer></v-spacer>
+          <v-btn flat @click.native="closeDialog">Close</v-btn>
+          <v-btn depressed color="primary" @click.native="saveItem">Save</v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-dialog>
+
+    <v-dialog v-model="warn" persistent max-width="500px">
+      <v-card>
+        <v-card-title class="headline">{{this.warnTitle}}</v-card-title>
+        <v-card-text >{{this.warnText}}</v-card-text>
+        <v-card-actions>
+          <v-spacer></v-spacer>
+          <v-btn flat @click.native="closeWarn">CANCLE</v-btn>
+          <v-btn depressed color="primary" @click.native="deleteItem(warnStatus)">CONFIRM</v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-dialog>
+
+  </v-container>
+
+</template>
+<script>
+  import yaml from 'js-yaml'
+  import AceEditor from '@/components/public/AceEditor'
+  import operations from '@/api/operation'
+  import Search from '@/components/public/Search'
+
+  export default {
+    components: {
+      AceEditor,
+      Search
+    },
+    data: () => ({
+      dropdown_font: [ 'Service', 'App', 'IP' ],
+      ruleKeys: ['enabled', 'force', 'dynamic', 'runtime', 'group', 'version', 'rule'],
+      pattern: 'Service',
+      filter: '',
+      dialog: false,
+      warn: false,
+      updateId: '',
+      application: '',
+      warnTitle: '',
+      warnText: '',
+      warnStatus: {},
+      height: 0,
+      operations: operations,
+      tagRoutingRules: [
+      ],
+      template:
+        'force: false\n' +
+        'enabled: true\n' +
+        'runtime: false\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: 'Application Name',
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: 'Enabled',
+          value: 'enabled',
+          sortable: false
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
+      ]
+    }),
+    methods: {
+      submit: function () {
+        this.filter = document.querySelector('#serviceSearch').value.trim()
+        this.search(this.filter, true)
+      },
+      search: function (filter, rewrite) {
+        let url = '/rules/route/tag/?application' + '=' + filter
+        this.$axios.get(url)
+          .then(response => {
+            this.tagRoutingRules = response.data
+            if (rewrite) {
+              this.$router.push({path: 'tagRule', query: {application: filter}})
+            }
+          })
+      },
+      closeDialog: function () {
+        this.ruleText = this.template
+        this.updateId = ''
+        this.application = ''
+        this.dialog = false
+        this.readonly = false
+      },
+      openDialog: function () {
+        this.dialog = true
+      },
+      openWarn: function (title, text) {
+        this.warnTitle = title
+        this.warnText = text
+        this.warn = true
+      },
+      closeWarn: function () {
+        this.warnTitle = ''
+        this.warnText = ''
+        this.warn = false
+      },
+      saveItem: function () {
+        let rule = yaml.safeLoad(this.ruleText)
+        if (!this.application) {
+          this.$notify.error('application is required')
+          return
+        }
+        rule.application = this.application
+        let vm = this
+        if (this.updateId) {
+          if (this.updateId === 'close') {
+            this.closeDialog()
+          } else {
+            rule.id = this.updateId
+            this.$axios.put('/rules/route/tag/' + rule.id, rule)
+              .then(response => {
+                if (response.status === 200) {
+                  vm.search(vm.application, true)
+                  vm.closeDialog()
+                  vm.$notify.success('Update success')
+                }
+              })
+          }
+        } else {
+          this.$axios.post('/rules/route/tag/', rule)
+            .then(response => {
+              if (response.status === 201) {
+                vm.search(vm.application, true)
+                vm.filter = vm.application
+                vm.closeDialog()
+                vm.$notify.success('Create success')
+              }
+            })
+            .catch(error => {
+              console.log(error)
+            })
+        }
+      },
+      itemOperation: function (icon, item) {
+        let itemId = item.application
+        switch (icon) {
+          case 'visibility':
+            this.$axios.get('/rules/route/tag/' + itemId)
+              .then(response => {
+                let tagRoute = response.data
+                this.handleBalance(tagRoute, true)
+                this.updateId = 'close'
+              })
+            break
+          case 'edit':
+            let id = {}
+            id.id = itemId
+            this.$axios.get('/rules/route/tag/' + itemId)
+              .then(response => {
+                let conditionRoute = response.data
+                this.handleBalance(conditionRoute, false)
+                this.updateId = itemId
+              })
+            break
+          case 'block':
+            this.openWarn(' Are you sure to block Routing Rule', 'application: ' + item.application)
+            this.warnStatus.operation = 'disable'
+            this.warnStatus.id = itemId
+            break
+          case 'check_circle_outline':
+            this.openWarn(' Are you sure to enable Routing Rule', 'application: ' + item.application)
+            this.warnStatus.operation = 'enable'
+            this.warnStatus.id = itemId
+            break
+          case 'delete':
+            this.openWarn(' Are you sure to Delete Routing Rule', 'application: ' + item.application)
+            this.warnStatus.operation = 'delete'
+            this.warnStatus.id = itemId
+        }
+      },
+      handleBalance: function (tagRoute, readonly) {
+        this.application = tagRoute.application
+        delete tagRoute.id
+        delete tagRoute.app
+        delete tagRoute.group
+        delete tagRoute.application
+        delete tagRoute.service
+        delete tagRoute.priority
+        this.ruleText = yaml.safeDump(tagRoute)
+        this.readonly = readonly
+        this.dialog = true
+      },
+      setHeight: function () {
+        this.height = window.innerHeight * 0.5
+      },
+      deleteItem: function (warnStatus) {
+        let id = warnStatus.id
+        let operation = warnStatus.operation
+        if (operation === 'delete') {
+          this.$axios.delete('/rules/route/tag/' + id)
+            .then(response => {
+              if (response.status === 200) {
+                this.warn = false
+                this.search(this.filter, false)
+                this.$notify.success('Delete success')
+              }
+            })
+        } else if (operation === 'disable') {
+          this.$axios.put('/rules/route/tag/disable/' + id)
+            .then(response => {
+              if (response.status === 200) {
+                this.warn = false
+                this.search(this.filter, false)
+                this.$notify.success('Disable success')
+              }
+            })
+        } else if (operation === 'enable') {
+          this.$axios.put('/rules/route/tag/enable/' + id)
+            .then(response => {
+              if (response.status === 200) {
+                this.warn = false
+                this.search(this.filter, false)
+                this.$notify.success('Enable success')
+              }
+            })
+        }
+      }
+    },
+    created () {
+      this.setHeight()
+    },
+    mounted: function () {
+      this.ruleText = this.template
+      let query = this.$route.query
+      let filter = null
+      Object.keys(query).forEach(function (key) {
+        if (key === 'application') {
+          filter = query[key]
+        }
+      })
+      if (filter !== null) {
+        this.filter = filter
+        this.search(filter, false)
+      }
+    }
+
+  }
+</script>
diff --git a/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue b/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
index 0112c22..433ba02 100644
--- a/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
+++ b/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
@@ -18,9 +18,40 @@
 <template>
   <v-container grid-list-xl fluid >
     <v-layout row wrap>
-      <v-flex xs12 >
-        <search v-model="filter" :submit="submit" label="Search Weight 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>
 
@@ -32,16 +63,37 @@
           <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"
+            :headers="serviceHeaders"
             :items="weights"
             hide-actions
             class="elevation-0"
           >
             <template slot="items" slot-scope="props">
               <td class="text-xs-left">{{ props.item.service }}</td>
-              <td class="text-xs-left">{{ props.item.method }}</td>
+              <td class="text-xs-left">{{ props.item.weight }}</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)">
+                    {{op.icon}}
+                  </v-icon>
+                  <span>{{op.tooltip}}</span>
+                </v-tooltip>
+              </td>
+            </template>
+          </v-data-table>
+        </v-card-text>
+        <v-card-text class="pa-0" v-if="selected == 1">
+          <v-data-table
+            :headers="appHeaders"
+            :items="weights"
+            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.weight }}</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)">
@@ -65,9 +117,13 @@
           <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"></ace-editor>
@@ -106,6 +162,11 @@
       Search
     },
     data: () => ({
+      items: [
+        {id: 0, title: 'service name', value: 'service'},
+        {id: 1, title: 'application', value: 'application'}
+      ],
+      selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
       ruleKeys: ['weight', 'address'],
       pattern: 'Service',
@@ -126,15 +187,14 @@
       ],
       weights: [
       ],
-      required: value => !!value || 'Service ID is required, in form of group/service:version, group and version are optional',
       template:
         'weight: 100  # 100 for default\n' +
-        'provider:   # provider\'s ip\n' +
+        'addresses:   # addresses\'s ip\n' +
         '  - 192.168.0.1\n' +
         '  - 192.168.0.2',
       ruleText: '',
       readonly: false,
-      headers: [
+      serviceHeaders: [
         {
           text: 'Service Name',
           value: 'service',
@@ -152,23 +212,46 @@
           sortable: false,
           width: '115px'
         }
+      ],
+      appHeaders: [
+        {
+          text: 'Application Name',
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: 'Weight',
+          value: 'weight',
+          align: 'left'
+
+        },
+        {
+          text: 'Operation',
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
       ]
     }),
     methods: {
       submit: function () {
+        this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
       },
       search: function (filter, rewrite) {
-        this.$axios.get('/rules/weight/', {
-          params: {
-            service: filter
-          }
-        }).then(response => {
-          this.weights = response.data
-          if (rewrite) {
-            this.$router.push({path: 'weight', query: {service: filter}})
-          }
-        })
+        let type = this.items[this.selected].value
+        let url = '/rules/weight/?' + type + '=' + filter
+        this.$axios.get(url)
+          .then(response => {
+            this.weights = response.data
+            if (rewrite) {
+              if (this.selected === 0) {
+                this.$router.push({path: 'weight', query: {service: filter}})
+              } else if (this.selected === 1) {
+                this.$router.push({path: 'weight', query: {application: filter}})
+              }
+            }
+          })
       },
       closeDialog: function () {
         this.ruleText = this.template
@@ -191,11 +274,14 @@
       },
       saveItem: function () {
         let weight = yaml.safeLoad(this.ruleText)
-        if (this.service === '') {
+        if (!this.service && !this.application) {
+          this.$notify.error('Either service or application is needed')
           return
         }
         weight.service = this.service
-        if (this.updateId !== '') {
+        weight.application = this.application
+        let vm = this
+        if (this.updateId) {
           if (this.updateId === 'close') {
             this.closeDialog()
           } else {
@@ -203,8 +289,15 @@
             this.$axios.put('/rules/weight/' + weight.id, weight)
               .then(response => {
                 if (response.status === 200) {
-                  this.search(this.service, true)
-                  this.filter = this.service
+                  if (vm.service) {
+                    vm.selected = 0
+                    vm.search(vm.service, true)
+                    vm.filter = vm.service
+                  } else {
+                    vm.selected = 1
+                    vm.search(vm.application, true)
+                    vm.filter = vm.application
+                  }
                   this.closeDialog()
                   this.$notify.success('Update success')
                 }
@@ -213,19 +306,35 @@
         } else {
           this.$axios.post('/rules/weight', weight)
             .then(response => {
-              if (response.status === 200) {
-                this.search(this.service, true)
-                this.filter = this.service
-                this.closeDialog()
-                this.$notify.success('Create success')
+              if (response.status === 201) {
+                if (this.service) {
+                  vm.selected = 0
+                  vm.search(vm.service, true)
+                  vm.filter = vm.service
+                } else {
+                  vm.selected = 1
+                  vm.search(vm.application, true)
+                  vm.filter = vm.application
+                }
+                vm.closeDialog()
+                vm.$notify.success('Create success')
               }
             })
         }
       },
       itemOperation: function (icon, item) {
+        let itemId = ''
+        if (this.selected === 0) {
+          itemId = item.service
+        } else {
+          itemId = item.application
+        }
+        if (itemId.includes('/')) {
+          itemId = itemId.replace('/', '*')
+        }
         switch (icon) {
           case 'visibility':
-            this.$axios.get('/rules/weight/' + item.id)
+            this.$axios.get('/rules/weight/' + itemId)
                 .then(response => {
                   let weight = response.data
                   this.handleWeight(weight, true)
@@ -233,22 +342,24 @@
                 })
             break
           case 'edit':
-            this.$axios.get('/rules/weight/' + item.id)
+            this.$axios.get('/rules/weight/' + itemId)
                 .then(response => {
                   let weight = response.data
                   this.handleWeight(weight, false)
-                  this.updateId = item.id
+                  this.updateId = itemId
                 })
             break
           case 'delete':
-            this.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + item.service)
+            this.openWarn(' Are you sure to Delete Routing Rule', 'service: ' + itemId)
             this.warnStatus.operation = 'delete'
-            this.warnStatus.id = item.id
+            this.warnStatus.id = itemId
         }
       },
       handleWeight: function (weight, readonly) {
         this.service = weight.service
+        this.application = weight.application
         delete weight.service
+        delete weight.application
         this.ruleText = yaml.safeDump(weight)
         this.readonly = readonly
         this.dialog = true
@@ -270,18 +381,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/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 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 @@
       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 3e66a5f..44eb93a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,27 +39,66 @@
 		<relativePath/> <!-- lookup parent from repository -->
 	</parent>
 
+	<repositories>
+		<repository>
+			<id>apache.snapshots.https</id>
+			<name>Apache Development Snapshot Repository</name>
+			<url>https://repository.apache.org/content/repositories/snapshots</url>
+			<releases>
+				<enabled>false</enabled>
+			</releases>
+			<snapshots>
+				<enabled>true</enabled>
+			</snapshots>
+		</repository>
+	</repositories>
+
 	<properties>
 		<main.basedir>${project.basedir}</main.basedir>
         <commons-lang3-version>3.7</commons-lang3-version>
-		<dubbo-version>2.6.4</dubbo-version>
+		<dubbo-version>2.7.0-SNAPSHOT</dubbo-version>
 		<curator-version>2.12.0</curator-version>
 		<fastjson-version>1.2.46</fastjson-version>
 		<springfox-swagger-version>2.9.2</springfox-swagger-version>
 		<netty-version>4.1.30.Final</netty-version>
 		<jacoco-version>0.8.2</jacoco-version>
+		<jedis-version>2.9.0</jedis-version>
+        <apollo-version>1.2.0</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>
+			</dependency>
+			<dependency>
 				<groupId>org.apache.commons</groupId>
 				<artifactId>commons-lang3</artifactId>
 				<version>${commons-lang3-version}</version>
 			</dependency>
 
 			<dependency>
-				<groupId>com.alibaba</groupId>
+				<groupId>com.ctrip.framework.apollo</groupId>
+				<artifactId>apollo-openapi</artifactId>
+				<version>${apollo-version}</version>
+			</dependency>
+
+			<dependency>
+				<groupId>org.apache.dubbo</groupId>
+				<artifactId>dubbo-metadata-report-api</artifactId>
+                <version>${dubbo-version}</version>
+			</dependency>
+
+			<dependency>
+				<groupId>org.apache.dubbo</groupId>
 				<artifactId>dubbo</artifactId>
 				<version>${dubbo-version}</version>
 			</dependency>