Merge branch 'develop' into service-test

# Conflicts:
#	dubbo-admin-frontend/src/components/test/ServiceTest.vue
diff --git a/README.md b/README.md
index db5a673..9ed9950 100644
--- a/README.md
+++ b/README.md
@@ -21,6 +21,7 @@
 
 * 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
+* [configurations in application.properties](https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin-configuration)
 * force update under root path(incubator-dubbo-ops) for the first building: `mvn -Dmaven.test.skip=true clean -U package`
 
 
@@ -31,7 +32,10 @@
 3. Build
 
     > - `mvn clean package`
-4. Start `mvn --projects dubbo-admin-backend spring-boot:run`
+4. Start 
+    * `mvn --projects dubbo-admin-backend spring-boot:run`  
+    OR
+    * `cd dubbo-admin-backend/target`;   `java -jar dubbo-admin-backend-0.0.1-SNAPSHOT.jar`
 5. Visit `http://localhost:8080`
 ---
 
diff --git a/README_ZH.md b/README_ZH.md
index cbaec11..f6879dc 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -21,6 +21,8 @@
 
 * 标准spring boot工程
 * **注意** 本分支依赖Dubbo2.7-SNAPSHOT版本,该Dubbo版本还未正式发布,因此如果发现依赖方面的错误,请清空本地库中的dubbo2.7相关文件
+* [application.properties配置说明](https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E)  
+* **注意** 本分支依赖Dubbo2.7-SNAPSHOT版本,该Dubbo版本还未正式发布,因此如果发现依赖方面的错误,请清空本地库中的dubbo2.7相关文件
 * 在项目根目录(incubator-dubbo-ops)第一次构建需要强制更新: `mvn -Dmaven.test.skip=true clean -U package`
 
 
@@ -31,7 +33,10 @@
 3. 构建
 
     > - `mvn clean package`
-4. 启动 `mvn --projects dubbo-admin-backend spring-boot:run`
+4. 启动 
+   * `mvn --projects dubbo-admin-backend spring-boot:run`   
+   或者   
+   * `cd dubbo-admin-backend/target; java -jar dubbo-admin-backend-0.0.1-SNAPSHOT.jar`
 5. 访问 `http://localhost:8080`
 ---
 
diff --git a/dubbo-admin-backend/README.md b/dubbo-admin-backend/README.md
index 49d5c21..a67748f 100644
--- a/dubbo-admin-backend/README.md
+++ b/dubbo-admin-backend/README.md
@@ -1,5 +1,5 @@
 ## Dubbo Admin后端配置
-当前版本的的Dubbo Aadmin支持Dubbo2.7的新特性(元数据展示,应用级别的配置),同时也兼容Dubbo2.6的用法,两个版本的配置不同,具体介绍如下:  
+当前版本的的Dubbo Admin支持Dubbo2.7的新特性(元数据展示,应用级别的配置),同时也兼容Dubbo2.6的用法,两个版本的配置不同,具体介绍如下:  
 * application.properties配置
   * dubbo.config.center: 2.7的配置,推荐用法,填写配置中心的地址,并且在配置中心的相应目录下配置注册中心和元数据中心的地址,Dubbo Admin会根据相应的协议,初始化对应的客户端,实现对配置中心,元数据中心的访问
   * dubbo.registry.address: 2.6的配置,只配置注册中心的地址。采用此配置,Dubbo Admin会把配置,元数据相关的内容也写入注册中心的不同目录下
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
index 9f5c282..86d9d2b 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/Constants.java
@@ -24,7 +24,7 @@
 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 METADATA_ADDRESS = "dubbo.metadata-report.address";
     public static final String DEFAULT_ROOT = "dubbo";
     public static final String PATH_SEPARATOR = "/";
     public static final String GROUP_KEY = "group";
@@ -41,6 +41,17 @@
     public static final String BALANCING = "balancing";
     public static final String SERVICE = "service";
     public static final String APPLICATION = "application";
+    public static final String PUNCTUATION_POINT = ".";
+    public static final String PUNCTUATION_SEPARATOR_POINT = "\\.";
+    public static final String INTERROGATION_POINT = "?";
+    public static final String ANY_VALUE = "*";
+    public static final String PLUS_SIGNS = "+";
+    public static final String IP = "ip";
+    public static final String INTERFACE_KEY = "interface";
+    public static final String VERSION_KEY = "version";
+    public static final String PROVIDERS_CATEGORY = "providers";
+    public static final String CONSUMERS_CATEGORY = "consumers";
+    public static final String SPECIFICATION_VERSION_KEY = "specVersion";
     public static final Set<String> CONFIGS = new HashSet<>();
 
     static {
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
index a44a849..ad01650 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/MD5Util.java
@@ -17,11 +17,15 @@
 
 package org.apache.dubbo.admin.common.util;
 
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 
 public class MD5Util {
 
+    private static final Logger logger = LoggerFactory.getLogger(MD5Util.class);
     private static MessageDigest md;
     private static final char[] hexCode = "0123456789ABCDEF".toCharArray();
 
@@ -29,7 +33,7 @@
         try {
             md = MessageDigest.getInstance("MD5");
         } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
     }
 
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteUtils.java
similarity index 86%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteUtils.java
index 7c48e14..cb2c759 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteRule.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/common/util/RouteUtils.java
@@ -37,7 +37,7 @@
  * The meaning of Rule: If a request matches When Condition, then use Then Condition to filter providers (only providers match Then Condition will be returned). <br>
  * The process of using Conditions to match consumers and providers is called `Filter`.
  * When Condition are used to filter ConsumersController, while Then Condition are used to filter ProvidersController.
- * RouteRule performs like this: If a Consumer matches When Condition, then only return the ProvidersController matches Then Condition. This means RouteRule should be applied to current Consumer and the providers returned are filtered by RouteRule.<br>
+ * RouteUtils performs like this: If a Consumer matches When Condition, then only return the ProvidersController matches Then Condition. This means RouteUtils should be applied to current Consumer and the providers returned are filtered by RouteUtils.<br>
  *
  * An example of ConditionRoute Rule:<code>
  * key1 = value11,value12 & key2 = value21 & key2 != value22 => key3 = value3 & key4 = value41,vlaue42 & key5 !=value51
@@ -47,9 +47,9 @@
  * Value object, thread safe.
  *
  */
-public class RouteRule {
+public class RouteUtils {
     @SuppressWarnings("unchecked")
-    static RouteRule EMPTY = new RouteRule(Collections.EMPTY_MAP, Collections.EMPTY_MAP);
+    static RouteUtils EMPTY = new RouteUtils(Collections.EMPTY_MAP, Collections.EMPTY_MAP);
     private static Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
     private static Pattern CONDITION_SEPERATOR = Pattern.compile("(.*)=>(.*)");
     private static Pattern VALUE_LIST_SEPARATOR = Pattern.compile("\\s*,\\s*");
@@ -58,7 +58,7 @@
     private volatile String tostring = null;
 
     // FIXME
-    private RouteRule(Map<String, MatchPair> when, Map<String, MatchPair> then) {
+    private RouteUtils(Map<String, MatchPair> when, Map<String, MatchPair> then) {
         for (Map.Entry<String, MatchPair> entry : when.entrySet()) {
             entry.getValue().freeze();
         }
@@ -140,16 +140,16 @@
     }
 
     /**
-     * Parse the RouteRule as a string into an object.
+     * Parse the RouteUtils as a string into an object.
      *
-     * @throws ParseException RouteRule string format is wrong. The following input conditions, RouteRule are illegal.
+     * @throws ParseException RouteUtils string format is wrong. The following input conditions, RouteUtils are illegal.
      * <ul> <li> input is <code>null</code>。
      * <li> input is "" or " "。
      * <li> input Rule doesn't have a When Condition
      * <li> input Rule doesn't have a Then Condition
      * </ul>
      */
-    public static RouteRule parse(Route conditionRoute) throws ParseException {
+    public static RouteUtils parse(Route conditionRoute) throws ParseException {
         if (conditionRoute == null)
             throw new ParseException("null conditionRoute!", 0);
 
@@ -160,7 +160,7 @@
         return parse(conditionRoute == null ? null : conditionRoute.getMatchRule(), conditionRoute == null ? null : conditionRoute.getFilterRule());
     }
 
-    public static RouteRule parse(String whenRule, String thenRule) throws ParseException {
+    public static RouteUtils parse(String whenRule, String thenRule) throws ParseException {
         /*if (whenRule == null || whenRule.trim().length() == 0) {
             throw new ParseException("Illegal route rule without when express", 0);
     	}*/
@@ -169,10 +169,10 @@
         }
         Map<String, MatchPair> when = parseRule(whenRule.trim());
         Map<String, MatchPair> then = parseRule(thenRule.trim());
-        return new RouteRule(when, then);
+        return new RouteUtils(when, then);
     }
 
-    public static RouteRule parse(String rule) throws ParseException {
+    public static RouteUtils parse(String rule) throws ParseException {
         if (StringUtils.isBlank(rule)) {
             throw new ParseException("Illegal blank route rule", 0);
         }
@@ -187,7 +187,7 @@
      * @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 conditionRoute) {
+    public static RouteUtils parseQuitely(Route conditionRoute) {
         try {
             return parse(conditionRoute);
         } catch (ParseException e) {
@@ -235,15 +235,10 @@
         existRule.setPriority(conditionRoute.getPriority());
         return existRule;
     }
-    public static BlackWhiteList convertToBlackWhiteList(AccessDTO accessDTO) {
+    public static List<String> 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();
@@ -268,11 +263,38 @@
             sb.append(" =>");
             conditions.add(sb.toString());
         }
-        blackWhiteList.setConditions(conditions);
-        return blackWhiteList;
+        return conditions;
     }
 
-    public static AccessDTO convertToAccessDTO(BlackWhiteList blackWhiteList, String scope, String key) {
+    public static List<String> filterBlackWhiteListFromConditions(List<String> conditions) {
+        List<String> result = new ArrayList<>();
+        if (conditions == null || conditions.isEmpty()) {
+            return result;
+        }
+        for (String condition : conditions) {
+            if (isBlackList(condition)) {
+                result.add(condition);
+            } else if (isWhiteList(condition)) {
+                result.add(condition);
+            }
+        }
+        return result;
+    }
+
+    public static List<String> filterConditionRuleFromConditions(List<String> conditions) {
+        List<String> result = new ArrayList<>();
+        if (conditions == null || conditions.isEmpty()) {
+            return result;
+        }
+        for (String condition : conditions) {
+            if (!isBlackList(condition) && !isWhiteList(condition)) {
+                result.add(condition);
+            }
+        }
+        return result;
+    }
+
+    public static AccessDTO convertToAccessDTO(List<String> blackWhiteList, String scope, String key) {
         if (blackWhiteList == null) {
             return null;
         }
@@ -282,8 +304,8 @@
         } else {
             accessDTO.setService(key);
         }
-        if (blackWhiteList.getConditions() != null) {
-            for (String condition : blackWhiteList.getConditions()) {
+        if (blackWhiteList != null) {
+            for (String condition : blackWhiteList) {
                 if (condition.contains("host != ")) {
                     //white list
                     condition = org.apache.commons.lang3.StringUtils.substringBetween(condition, "host !=", " =>").trim();
@@ -306,8 +328,8 @@
         route.setFilterRule("false");
         route.setEnabled(true);
 
-        Map<String, RouteRule.MatchPair> when = new HashMap<>();
-        RouteRule.MatchPair matchPair = new RouteRule.MatchPair(new HashSet<>(), new HashSet<>());
+        Map<String, RouteUtils.MatchPair> when = new HashMap<>();
+        RouteUtils.MatchPair matchPair = new RouteUtils.MatchPair(new HashSet<>(), new HashSet<>());
         when.put(Route.KEY_CONSUMER_HOST, matchPair);
 
         if (accessDTO.getWhitelist() != null) {
@@ -318,7 +340,7 @@
         }
 
         StringBuilder sb = new StringBuilder();
-        RouteRule.contidionToString(sb, when);
+        RouteUtils.contidionToString(sb, when);
         route.setMatchRule(sb.toString());
         return route;
     }
@@ -330,7 +352,7 @@
         } else {
             conditionRouteDTO.setApplication(routingRule.getKey());
         }
-        conditionRouteDTO.setConditions(routingRule.getConditions());
+        conditionRouteDTO.setConditions(RouteUtils.filterConditionRuleFromConditions(routingRule.getConditions()));
         conditionRouteDTO.setPriority(routingRule.getPriority());
         conditionRouteDTO.setEnabled(routingRule.isEnabled());
         conditionRouteDTO.setForce(routingRule.isForce());
@@ -338,7 +360,7 @@
         return conditionRouteDTO;
     }
 
-    public static Route convertBlackWhiteListtoRoute(BlackWhiteList blackWhiteList, String scope, String key) {
+    public static Route convertBlackWhiteListtoRoute(List<String> blackWhiteList, String scope, String key) {
         AccessDTO accessDTO = convertToAccessDTO(blackWhiteList, scope, key);
         return convertAccessDTOtoRoute(accessDTO);
     }
@@ -402,19 +424,19 @@
         return condition;
     }
 
-    public static RouteRule createFromNameAndValueListString(Map<String, String> whenParams, Map<String, String> notWhenParams,
-                                                             Map<String, String> thenParams, Map<String, String> notThenParams) {
+    public static RouteUtils createFromNameAndValueListString(Map<String, String> whenParams, Map<String, String> notWhenParams,
+                                                              Map<String, String> thenParams, Map<String, String> notThenParams) {
         Map<String, MatchPair> when = parseNameAndValueListString2Condition(whenParams, notWhenParams);
         Map<String, MatchPair> then = parseNameAndValueListString2Condition(thenParams, notThenParams);
 
-        return new RouteRule(when, then);
+        return new RouteUtils(when, then);
     }
 
-    public static RouteRule createFromCondition(Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
-        return new RouteRule(whenCondition, thenCondition);
+    public static RouteUtils createFromCondition(Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
+        return new RouteUtils(whenCondition, thenCondition);
     }
 
-    public static RouteRule copyWithRemove(RouteRule copy, Set<String> whenParams, Set<String> thenParams) {
+    public static RouteUtils copyWithRemove(RouteUtils copy, Set<String> whenParams, Set<String> thenParams) {
         Map<String, MatchPair> when = new HashMap<String, MatchPair>();
         for (Entry<String, MatchPair> entry : copy.getWhenCondition().entrySet()) {
             if (whenParams == null || !whenParams.contains(entry.getKey())) {
@@ -429,7 +451,7 @@
             }
         }
 
-        return new RouteRule(when, then);
+        return new RouteUtils(when, then);
     }
 
     /**
@@ -438,9 +460,9 @@
      * @param copy Replace Base
      * @param whenCondition WhenCondition to replace, if Base does not have an item, insert it directly.
      * @param thenCondition ThenCondition to replace, if Base has no items, then insert directly.
-     * @return RouteRule after replacement
+     * @return RouteUtils after replacement
      */
-    public static RouteRule copyWithReplace(RouteRule copy, Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
+    public static RouteUtils copyWithReplace(RouteUtils copy, Map<String, MatchPair> whenCondition, Map<String, MatchPair> thenCondition) {
         if (null == copy) {
             throw new NullPointerException("Argument copy is null!");
         }
@@ -457,7 +479,7 @@
             then.putAll(thenCondition);
         }
 
-        return new RouteRule(when, then);
+        return new RouteUtils(when, then);
     }
 
     // TODO ToString out of the current list is out of order, should we sort?
@@ -573,6 +595,14 @@
         return sb.toString();
     }
 
+    private static boolean isBlackList(String address) {
+        return (address.startsWith("host = ") && address.endsWith(" =>"));
+    }
+
+    private static boolean isWhiteList(String address) {
+        return (address.startsWith("host != ") && address.endsWith(" =>"));
+    }
+
     @Override
     public String toString() {
         if (tostring != null)
@@ -603,7 +633,7 @@
             return false;
         if (getClass() != obj.getClass())
             return false;
-        RouteRule other = (RouteRule) obj;
+        RouteUtils other = (RouteUtils) obj;
         if (thenCondition == null) {
             if (other.thenCondition != null)
                 return false;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
index 0aa0442..a3c6405 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java
@@ -19,13 +19,14 @@
 
 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.admin.registry.config.GovernanceConfiguration;
+import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
+import org.apache.dubbo.admin.registry.metadata.impl.NoOpMetadataCollector;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.registry.RegistryFactory;
 import org.springframework.beans.factory.annotation.Value;
@@ -40,17 +41,21 @@
 public class ConfigCenter {
 
 
-    @Value("${dubbo.configcenter:}")
+    @Value("${dubbo.config-center:}")
     private String configCenter;
+    @Value("${dubbo.config-center.username:}")
+    private String username;
+    @Value("${dubbo.config-center.password:}")
+    private String password;
 
     @Value("${dubbo.registry.address:}")
     private String registryAddress;
-
-    private static String globalConfigPath = "config/dubbo/dubbo.properties";
-
     @Value("${dubbo.registry.group:}")
     private String group;
 
+    private static String globalConfigPath = "config/dubbo/dubbo.properties";
+
+    private static final Logger logger = LoggerFactory.getLogger(ConfigCenter.class);
 
     private URL configCenterUrl;
     private URL registryUrl;
@@ -65,7 +70,7 @@
         GovernanceConfiguration dynamicConfiguration = null;
 
         if (StringUtils.isNotEmpty(configCenter)) {
-            configCenterUrl = formUrl(configCenter, group);
+            configCenterUrl = formUrl(configCenter, group, username, password);
             dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(configCenterUrl.getProtocol());
             dynamicConfiguration.setUrl(configCenterUrl);
             dynamicConfiguration.init();
@@ -74,21 +79,22 @@
             if (StringUtils.isNotEmpty(config)) {
                 Arrays.stream(config.split("\n")).forEach( s -> {
                     if(s.startsWith(Constants.REGISTRY_ADDRESS)) {
-                        registryUrl = formUrl(s.split("=")[1].trim(), group);
+                        registryUrl = formUrl(s.split("=")[1].trim(), group, username, password);
                     } else if (s.startsWith(Constants.METADATA_ADDRESS)) {
-                        metadataUrl = formUrl(s.split("=")[1].trim(), group);
+                        metadataUrl = formUrl(s.split("=")[1].trim(), group, username, password);
                     }
                 });
             }
         }
         if (dynamicConfiguration == null) {
             if (StringUtils.isNotEmpty(registryAddress)) {
-                registryUrl = formUrl(registryAddress, group);
+                registryUrl = formUrl(registryAddress, group, username, password);
                 dynamicConfiguration = ExtensionLoader.getExtensionLoader(GovernanceConfiguration.class).getExtension(registryUrl.getProtocol());
                 dynamicConfiguration.setUrl(registryUrl);
                 dynamicConfiguration.init();
+                logger.warn("you are using dubbo.registry.address, which is not recommend, please refer to: https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin-configuration");
             } else {
-                throw new ConfigurationException("Either configcenter or registry address is needed");
+                throw new ConfigurationException("Either config center or registry address is needed, please refer to https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin-configuration");
                 //throw exception
             }
         }
@@ -104,9 +110,9 @@
         Registry registry = null;
         if (registryUrl == null) {
             if (StringUtils.isBlank(registryAddress)) {
-                throw new ConfigurationException("Either configcenter or registry address is needed");
+                throw new ConfigurationException("Either config center or registry address is needed, please refer to https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin-configuration");
             }
-            registryUrl = formUrl(registryAddress, group);
+            registryUrl = formUrl(registryAddress, group, username, password);
         }
         RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
         registry = registryFactory.getRegistry(registryUrl);
@@ -124,14 +130,22 @@
             metaDataCollector = ExtensionLoader.getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol());
             metaDataCollector.setUrl(metadataUrl);
             metaDataCollector.init();
+        } else {
+            logger.warn("you are using dubbo.registry.address, which is not recommend, please refer to: https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin-configuration");
         }
         return metaDataCollector;
     }
 
-    private URL formUrl(String config, String group) {
+    private URL formUrl(String config, String group, String username, String password) {
         URL url = URL.valueOf(config);
         if (StringUtils.isNotEmpty(group)) {
-            url.addParameter(org.apache.dubbo.common.Constants.GROUP_KEY, group);
+            url = url.addParameter(org.apache.dubbo.common.Constants.GROUP_KEY, group);
+        }
+        if (StringUtils.isNotEmpty(username)) {
+            url = url.setUsername(username);
+        }
+        if (StringUtils.isNotEmpty(password)) {
+            url = url.setPassword(password);
         }
         return url;
     }
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 e815669..ac350c5 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,8 +16,10 @@
  */
 package org.apache.dubbo.admin.controller;
 
-import org.apache.dubbo.admin.common.util.RouteRule;
+import org.apache.dubbo.admin.common.exception.VersionValidationException;
+import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
+import org.apache.dubbo.admin.service.ProviderService;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.commons.lang3.StringUtils;
@@ -38,10 +40,12 @@
     private static final Logger logger = LoggerFactory.getLogger(AccessesController.class);
 
     private final RouteService routeService;
+    private final ProviderService providerService;
 
     @Autowired
-    public AccessesController(RouteService routeService) {
+    public AccessesController(RouteService routeService, ProviderService providerService) {
         this.routeService = routeService;
+        this.providerService = providerService;
     }
 
     @RequestMapping(method = RequestMethod.GET)
@@ -67,14 +71,14 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public AccessDTO detailAccess(@PathVariable String id, @PathVariable String env) throws ParseException {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         AccessDTO accessDTO = routeService.findAccess(id);
         return accessDTO;
     }
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public void deleteAccess(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         routeService.deleteAccess(id);
     }
 
@@ -84,6 +88,10 @@
         if (StringUtils.isBlank(accessDTO.getService()) && StringUtils.isBlank(accessDTO.getApplication())) {
             throw new ParamValidationException("Either Service or application is required.");
         }
+        String application = accessDTO.getApplication();
+        if (StringUtils.isNotEmpty(application) && this.providerService.findVersionInApplication(application).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support application scope blackwhite list config");
+        }
         if (accessDTO.getBlacklist() == null && accessDTO.getWhitelist() == null) {
             throw new ParamValidationException("One of Blacklist/Whitelist is required.");
         }
@@ -93,25 +101,11 @@
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
     public void updateAccess(@PathVariable String id, @RequestBody AccessDTO accessDTO, @PathVariable String env) {
 
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         ConditionRouteDTO route = routeService.findConditionRoute(id);
         if (Objects.isNull(route)) {
             throw new ResourceNotFoundException("Unknown ID!");
         }
         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
index a5849e0..f764801 100644
--- 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
@@ -21,6 +21,7 @@
 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.common.util.Constants;
 import org.apache.dubbo.admin.model.dto.ConditionRouteDTO;
 import org.apache.dubbo.admin.service.ProviderService;
 import org.apache.dubbo.admin.service.RouteService;
@@ -61,7 +62,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
     public boolean updateRule(@PathVariable String id, @RequestBody ConditionRouteDTO newConditionRoute, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         ConditionRouteDTO oldConditionRoute = routeService.findConditionRoute(id);
         if (oldConditionRoute == null) {
             throw new ResourceNotFoundException("can not find route rule for: " + id);
@@ -89,7 +90,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public ConditionRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         ConditionRouteDTO conditionRoute = routeService.findConditionRoute(id);
         if (conditionRoute == null || conditionRoute.getConditions() == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -99,21 +100,21 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         routeService.deleteConditionRoute(id);
         return true;
     }
 
     @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
     public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         routeService.enableConditionRoute(id);
         return true;
     }
 
     @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
     public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         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 3d1221e..a803527 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,8 +20,11 @@
 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.common.util.Constants;
 import org.apache.dubbo.admin.model.dto.BalancingDTO;
 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.*;
@@ -35,10 +38,12 @@
 public class LoadBalanceController {
 
     private final OverrideService overrideService;
+    private final ProviderService providerService;
 
     @Autowired
-    public LoadBalanceController(OverrideService overrideService) {
+    public LoadBalanceController(OverrideService overrideService, ProviderService providerService) {
         this.overrideService = overrideService;
+        this.providerService = providerService;
     }
 
     @RequestMapping(method = RequestMethod.POST)
@@ -47,16 +52,11 @@
         if (StringUtils.isBlank(balancingDTO.getService()) && StringUtils.isBlank(balancingDTO.getApplication())) {
             throw new ParamValidationException("Either Service or application is required.");
         }
+        String application = balancingDTO.getApplication();
+        if (StringUtils.isNotEmpty(application) && this.providerService.findVersionInApplication(application).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support application scope load balancing config");
+        }
         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;
     }
 
@@ -65,7 +65,7 @@
         if (id == null) {
             throw new ParamValidationException("Unknown ID!");
         }
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         BalancingDTO balancing = overrideService.findBalance(id);
         if (balancing == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -98,7 +98,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public BalancingDTO detailLoadBalance(@PathVariable String id, @PathVariable String env) throws ParamValidationException {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         BalancingDTO balancingDTO = overrideService.findBalance(id);
         if (balancingDTO == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -114,7 +114,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteLoadBalance(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         if (id == null) {
             throw new IllegalArgumentException("Argument of id is null!");
         }
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 96cb8dd..fb19178 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
@@ -21,6 +21,7 @@
 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.common.util.Constants;
 import org.apache.dubbo.admin.model.dto.DynamicConfigDTO;
 import org.apache.dubbo.admin.service.OverrideService;
 import org.apache.dubbo.admin.service.ProviderService;
@@ -61,7 +62,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
     public boolean updateOverride(@PathVariable String id, @RequestBody DynamicConfigDTO overrideDTO, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         DynamicConfigDTO old = overrideService.findOverride(id);
         if (old == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -89,7 +90,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public DynamicConfigDTO detailOverride(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         DynamicConfigDTO override = overrideService.findOverride(id);
         if (override == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -100,7 +101,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteOverride(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         overrideService.deleteOverride(id);
         return true;
     }
@@ -108,14 +109,14 @@
     @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
     public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
 
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         overrideService.enableOverride(id);
         return true;
     }
 
     @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
     public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
 
         overrideService.disableOverride(id);
         return true;
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 9233f2a..87856ef 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
@@ -25,7 +25,7 @@
 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.admin.common.util.Constants;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
@@ -53,60 +53,14 @@
     @RequestMapping(method = RequestMethod.GET)
     public Set<ServiceDTO> searchService(@RequestParam String pattern,
                                          @RequestParam String filter,@PathVariable String env) {
-
-        List<Provider> providers = new ArrayList<>();
-        if (!filter.contains("*") && !filter.contains("?")) {
-            if (pattern.equals("ip")) {
-                providers = providerService.findByAddress(filter);
-            } 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("service")) {
-               candidates = providerService.findServices();
-            } else if (pattern.equals("application")) {
-                candidates = providerService.findApplications();
-            }
-            filter = filter.toLowerCase().replace(".", "\\.");
-            if (filter.startsWith("*")) {
-                filter = "." + filter;
-            }
-            Pattern regex = Pattern.compile(filter);
-            for (String candidate : candidates) {
-                Matcher matcher = regex.matcher(candidate);
-                if (matcher.matches() || matcher.lookingAt()) {
-                    if (pattern.equals("service")) {
-                        providers.addAll(providerService.findByService(candidate));
-                    } else {
-                        providers.addAll(providerService.findByApplication(candidate));
-                    }
-                }
-            }
-        }
-
-        Set<ServiceDTO> result = new TreeSet<>();
-        for (Provider provider : providers) {
-            Map<String, String> map = StringUtils.parseQueryString(provider.getParameters());
-            String app = provider.getApplication();
-            String service = map.get(Constants.INTERFACE_KEY);
-            String group = map.get(Constants.GROUP_KEY);
-            String version = map.get(Constants.VERSION_KEY);
-            ServiceDTO s = new ServiceDTO();
-            s.setAppName(app);
-            s.setService(service);
-            s.setGroup(group);
-            s.setVersion(version);
-            result.add(s);
-        }
-        return result;
+        return providerService.getServiceDTOS(pattern, filter, env);
     }
 
+
+
     @RequestMapping(value = "/{service}", method = RequestMethod.GET)
     public ServiceDetailDTO serviceDetail(@PathVariable String service, @PathVariable String env) {
-        service = service.replace("*", "/");
+        service = service.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         List<Provider> providers = providerService.findByService(service);
 
         List<Consumer> consumers = consumerService.findByService(service);
@@ -121,6 +75,8 @@
                                                                       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);
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
index 40b81bf..54bfffe 100644
--- 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
@@ -21,6 +21,7 @@
 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.common.util.Constants;
 import org.apache.dubbo.admin.model.dto.TagRouteDTO;
 import org.apache.dubbo.admin.service.ProviderService;
 import org.apache.dubbo.admin.service.RouteService;
@@ -62,7 +63,7 @@
     @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
     public boolean updateRule(@PathVariable String id, @RequestBody TagRouteDTO routeDTO, @PathVariable String env) {
 
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         String app = routeDTO.getApplication();
         if (providerService.findVersionInApplication(app).equals("2.6")) {
             throw new VersionValidationException("dubbo 2.6 does not support tag route");
@@ -100,7 +101,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.GET)
     public TagRouteDTO detailRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         TagRouteDTO tagRoute = routeService.findTagRoute(id);
         if (tagRoute == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -110,21 +111,21 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         routeService.deleteTagRoute(id);
         return true;
     }
 
     @RequestMapping(value = "/enable/{id}", method = RequestMethod.PUT)
     public boolean enableRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         routeService.enableTagRoute(id);
         return true;
     }
 
     @RequestMapping(value = "/disable/{id}", method = RequestMethod.PUT)
     public boolean disableRoute(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         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 11ce807..2146a01 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,6 +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.common.exception.VersionValidationException;
+import org.apache.dubbo.admin.common.util.Constants;
 import org.apache.dubbo.admin.common.util.ConvertUtil;
 import org.apache.dubbo.admin.model.dto.AccessDTO;
 import org.apache.dubbo.admin.model.dto.WeightDTO;
@@ -27,6 +29,7 @@
 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.apache.dubbo.admin.service.ProviderService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.*;
@@ -39,10 +42,12 @@
 public class WeightController {
 
     private final OverrideService overrideService;
+    private final ProviderService providerService;
 
     @Autowired
-    public WeightController(OverrideService overrideService) {
+    public WeightController(OverrideService overrideService, ProviderService providerService) {
         this.overrideService = overrideService;
+        this.providerService = providerService;
     }
 
     @RequestMapping(method = RequestMethod.POST)
@@ -51,15 +56,11 @@
         if (StringUtils.isBlank(weightDTO.getService()) && StringUtils.isBlank(weightDTO.getApplication())) {
             throw new ParamValidationException("Either Service or application is required.");
         }
+        String application = weightDTO.getApplication();
+        if (StringUtils.isNotEmpty(application) && this.providerService.findVersionInApplication(application).equals("2.6")) {
+            throw new VersionValidationException("dubbo 2.6 does not support application scope blackwhite list config");
+        }
         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;
     }
 
@@ -68,17 +69,11 @@
         if (id == null) {
             throw new ParamValidationException("Unknown ID!");
         }
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         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));
         overrideService.updateWeight(weightDTO);
         return true;
     }
@@ -101,29 +96,12 @@
             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) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         WeightDTO weightDTO = overrideService.findWeight(id);
         if (weightDTO == null) {
             throw new ResourceNotFoundException("Unknown ID!");
@@ -133,7 +111,7 @@
 
     @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
     public boolean deleteWeight(@PathVariable String id, @PathVariable String env) {
-        id = id.replace("*", "/");
+        id = id.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
         overrideService.deleteWeight(id);
         return true;
     }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
index 6e3fa50..3822291 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/dto/ServiceDTO.java
@@ -17,6 +17,7 @@
 
 package org.apache.dubbo.admin.model.dto;
 
+import java.util.Objects;
 import org.apache.commons.lang3.StringUtils;
 
 public class ServiceDTO implements Comparable<ServiceDTO>{
@@ -71,4 +72,22 @@
         }
         return result;
     }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        ServiceDTO that = (ServiceDTO) o;
+        return Objects.equals(service, that.service) && Objects.equals(appName, that.appName) && Objects
+            .equals(group, that.group) && Objects.equals(version, that.version);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(service, appName, group, version);
+    }
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java
index 46b012f..7707e94 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/model/store/RoutingRule.java
@@ -28,7 +28,7 @@
     private boolean force;
     private boolean runtime;
     private List<String> conditions;
-    private BlackWhiteList blackWhiteList;
+//    private BlackWhiteList blackWhiteList;
 
 
     public String getKey() {
@@ -87,11 +87,11 @@
         this.conditions = conditions;
     }
 
-    public BlackWhiteList getBlackWhiteList() {
-        return blackWhiteList;
-    }
-
-    public void setBlackWhiteList(BlackWhiteList blackWhiteList) {
-        this.blackWhiteList = blackWhiteList;
-    }
+//    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/data/config/GovernanceConfiguration.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
similarity index 96%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
index 8fb75ab..c6ed397 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/GovernanceConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/GovernanceConfiguration.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.config;
+package org.apache.dubbo.admin.registry.config;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
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/registry/config/impl/ApolloConfiguration.java
similarity index 95%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
index 2bc0f90..13d4b2e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ApolloConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ApolloConfiguration.java
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.config.impl;
+package org.apache.dubbo.admin.registry.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.admin.registry.config.GovernanceConfiguration;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
 import org.springframework.beans.factory.annotation.Value;
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/registry/config/impl/NoOpConfiguration.java
similarity index 92%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/NoOpConfiguration.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/NoOpConfiguration.java
index 08cb489..85dca2f 100644
--- 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/registry/config/impl/NoOpConfiguration.java
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.config.impl;
+package org.apache.dubbo.admin.registry.config.impl;
 
-import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
+import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
 import org.apache.dubbo.common.URL;
 
 public class NoOpConfiguration implements GovernanceConfiguration {
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/registry/config/impl/ZookeeperConfiguration.java
similarity index 77%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
index 95e7988..0ba847a 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/config/impl/ZookeeperConfiguration.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/config/impl/ZookeeperConfiguration.java
@@ -15,25 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.config.impl;
+package org.apache.dubbo.admin.registry.config.impl;
 
+import org.apache.commons.lang3.StringUtils;
 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.admin.registry.config.GovernanceConfiguration;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.URL;
 
-import javax.swing.*;
 
 public class ZookeeperConfiguration implements GovernanceConfiguration {
+    private static final Logger logger = LoggerFactory.getLogger(ZookeeperConfiguration.class);
     private CuratorFramework zkClient;
     private URL url;
     private String root;
 
     @Override
     public void setUrl(URL url) {
-       this.url = url;
+        this.url = url;
     }
 
     @Override
@@ -43,7 +46,15 @@
 
     @Override
     public void init() {
-        zkClient = CuratorFrameworkFactory.newClient(url.getAddress(), new ExponentialBackoffRetry(1000, 3));
+        CuratorFrameworkFactory.Builder zkClientBuilder = CuratorFrameworkFactory.builder().
+                connectString(url.getAddress()).
+                retryPolicy(new ExponentialBackoffRetry(1000, 3));
+        if(StringUtils.isNotEmpty(url.getUsername()) && StringUtils.isNotEmpty(url.getPassword())){
+            // add authorization
+            String auth = url.getUsername() + ":" + url.getPassword();
+            zkClientBuilder.authorization("digest", auth.getBytes());
+        }
+        zkClient = zkClientBuilder.build();
         String group = url.getParameter(Constants.GROUP_KEY, Constants.DEFAULT_ROOT);
         if (!group.startsWith(Constants.PATH_SEPARATOR)) {
             group = Constants.PATH_SEPARATOR + group;
@@ -77,7 +88,7 @@
             zkClient.setData().forPath(path, value.getBytes());
             return value;
         } catch (Exception e) {
-
+            logger.error(e.getMessage(), e);
         }
         return null;
     }
@@ -92,7 +103,7 @@
             }
             return new String(zkClient.getData().forPath(path));
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
         return null;
     }
@@ -103,7 +114,7 @@
         try {
             zkClient.delete().forPath(path);
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
         return true;
     }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java
similarity index 95%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java
index 5b5e802..b5974a7 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.metadata;
+package org.apache.dubbo.admin.registry.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
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/registry/metadata/impl/NoOpMetadataCollector.java
similarity index 91%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/NoOpMetadataCollector.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NoOpMetadataCollector.java
index 8e561a6..3638570 100644
--- 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/registry/metadata/impl/NoOpMetadataCollector.java
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.metadata.impl;
+package org.apache.dubbo.admin.registry.metadata.impl;
 
-import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 
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/registry/metadata/impl/RedisMetaDataCollector.java
similarity index 94%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/RedisMetaDataCollector.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/RedisMetaDataCollector.java
index b00238a..2431b8e 100644
--- 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/registry/metadata/impl/RedisMetaDataCollector.java
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.metadata.impl;
+package org.apache.dubbo.admin.registry.metadata.impl;
 
 
-import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import redis.clients.jedis.Jedis;
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/registry/metadata/impl/ZookeeperMetaDataCollector.java
similarity index 88%
rename from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
rename to dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java
index 0ecab02..48c3cf3 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/impl/ZookeeperMetaDataCollector.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java
@@ -15,18 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.dubbo.admin.data.metadata.impl;
+package org.apache.dubbo.admin.registry.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.admin.registry.metadata.MetaDataCollector;
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 
 public class ZookeeperMetaDataCollector implements MetaDataCollector {
 
+    private static final Logger logger = LoggerFactory.getLogger(ZookeeperMetaDataCollector.class);
     private CuratorFramework client;
     private URL url;
     private String root;
@@ -86,7 +89,7 @@
             }
             return new String(client.getData().forPath(path));
         } catch (Exception e) {
-            e.printStackTrace();
+            logger.error(e.getMessage(), e);
         }
         return null;
     }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
index eafb6d0..01a79e4 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/ProviderService.java
@@ -17,9 +17,11 @@
 package org.apache.dubbo.admin.service;
 
 import org.apache.dubbo.admin.model.domain.Provider;
+import org.apache.dubbo.admin.model.dto.ServiceDTO;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * ProviderService
@@ -45,6 +47,11 @@
 
     String getProviderMetaData(MetadataIdentifier providerIdentifier);
 
+    /**
+     * Get all provider's service name
+     *
+     * @return list of all provider's service name
+     */
     List<String> findServices();
 
     String findServiceVersion(String serviceName, String application);
@@ -59,18 +66,36 @@
 
     List<String> findApplicationsByServiceName(String serviceName);
 
+    /**
+     * Get provider list with specific service name.
+     *
+     * @param serviceName specific service name, cannot be fuzzy string
+     * @return list of provider object
+     */
     List<Provider> findByService(String serviceName);
 
     List<Provider> findByAppandService(String app, String serviceName);
 
     List<Provider> findAll();
 
+    /**
+     * Get provider list with specific ip address.
+     *
+     * @param providerAddress provider's ip address
+     * @return list of provider object
+     */
     List<Provider> findByAddress(String providerAddress);
 
     List<String> findServicesByAddress(String providerAddress);
 
     List<String> findApplications();
 
+    /**
+     * Get provider list with specific application name.
+     *
+     * @param application specific application name
+     * @return list of provider object
+     */
     List<Provider> findByApplication(String application);
 
     List<String> findServicesByApplication(String application);
@@ -79,4 +104,17 @@
 
     Provider findByServiceAndAddress(String service, String address);
 
-}
+    /**
+     * Get a set of service data object.
+     *
+     * ServiceDTO object contains base information include
+     * service name , application, group and version.
+     *
+     * @param pattern {@code String} type of search
+     * @param filter  {@code String} input filter string
+     * @param env     {@code String}the environment of front end
+     * @return a set of services for fore-end page
+     */
+    Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env);
+
+}
\ No newline at end of file
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
index 7a9b1fa..7a4a676 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/RegistryServerSync.java
@@ -60,9 +60,11 @@
      */
     private final ConcurrentHashMap<String, String> URL_IDS_MAPPER = new ConcurrentHashMap<>();
 
-    // ConcurrentMap<category, ConcurrentMap<servicename, Map<MD5, URL>>>
-    private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>>
-        registryCache = new ConcurrentHashMap<>();
+    /**
+     * ConcurrentMap<category, ConcurrentMap<servicename, Map<MD5, URL>>>
+     * registryCache
+     */
+    private final ConcurrentMap<String, ConcurrentMap<String, Map<String, URL>>> registryCache = new ConcurrentHashMap<>();
     @Autowired
     private Registry registry;
 
@@ -70,16 +72,19 @@
         return registryCache;
     }
 
+    @Override
     public void afterPropertiesSet() throws Exception {
         logger.info("Init Dubbo Admin Sync Cache...");
         registry.subscribe(SUBSCRIBE, this);
     }
 
+    @Override
     public void destroy() throws Exception {
         registry.unsubscribe(SUBSCRIBE, this);
     }
 
     // Notification of of any service with any type (override、subcribe、route、provider) is full.
+    @Override
     public void notify(List<URL> urls) {
         if (urls == null || urls.isEmpty()) {
             return;
@@ -89,7 +94,8 @@
         String interfaceName = null;
         for (URL url : urls) {
             String category = url.getParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY);
-            if (Constants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { // NOTE: group and version in empty protocol is *
+            // NOTE: group and version in empty protocol is *
+            if (Constants.EMPTY_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
                 ConcurrentMap<String, Map<String, URL>> services = registryCache.get(category);
                 if (services != null) {
                     String group = url.getParameter(Constants.GROUP_KEY);
@@ -155,4 +161,4 @@
         }
     }
 }
-    
+
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
index 914943d..d9e63d5 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/AbstractService.java
@@ -16,8 +16,8 @@
  */
 package org.apache.dubbo.admin.service.impl;
 
-import org.apache.dubbo.admin.data.config.GovernanceConfiguration;
-import org.apache.dubbo.admin.data.metadata.MetaDataCollector;
+import org.apache.dubbo.admin.registry.config.GovernanceConfiguration;
+import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
 import org.apache.dubbo.admin.service.RegistryServerSync;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
index 09670c8..0786b8c 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java
@@ -16,33 +16,27 @@
  */
 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.model.dto.ServiceDTO;
 import org.apache.dubbo.admin.service.OverrideService;
 import org.apache.dubbo.admin.service.ProviderService;
-import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.admin.common.util.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.*;
 import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
-import static org.apache.dubbo.common.Constants.SPECIFICATION_VERSION_KEY;
 
 /**
  * IbatisProviderService
@@ -54,6 +48,7 @@
     @Autowired
     OverrideService overrideService;
 
+    @Override
     public void create(Provider provider) {
         URL url = provider.toUrl();
         registry.register(url);
@@ -96,7 +91,7 @@
 //        }
 //    }
 
-    @java.lang.Override
+    @Override
     public String getProviderMetaData(MetadataIdentifier providerIdentifier) {
         return metaDataCollector.getProviderMetaData(providerIdentifier);
     }
@@ -209,12 +204,20 @@
             weight = Integer.parseInt(value);
         }
         weight = (int) (weight * factor);
-        if (weight < 1) weight = 1;
-        if (weight == 2) weight = 3;
-        if (weight == 24) weight = 25;
+        if (weight < 1){
+            weight = 1;
+        }
+        if (weight == 2){
+            weight = 3;
+        }
+
+        if (weight == 24){
+            weight = 25;
+        }
         return weight;
     }
 
+    @Override
     public void deleteStaticProvider(String id) {
         URL oldProvider = findProviderUrl(id);
         if (oldProvider == null) {
@@ -223,6 +226,7 @@
         registry.unregister(oldProvider);
     }
 
+    @Override
     public void updateProvider(Provider provider) {
         String hash = provider.getHash();
         if (hash == null) {
@@ -239,6 +243,7 @@
         registry.register(newProvider);
     }
 
+    @Override
     public Provider findProvider(String id) {
         return SyncUtils.url2Provider(findProviderUrlPair(id));
     }
@@ -247,41 +252,32 @@
         return SyncUtils.filterFromCategory(getRegistryCache(), Constants.PROVIDERS_CATEGORY, id);
     }
 
+    @Override
     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());
+        if (providerUrls != null){
+            ret.addAll(providerUrls.keySet());
+        }
         return ret;
     }
 
+    @Override
     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;
+        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);
+                if (app != null) {
+                    ret.add(app);
                 }
             }
         }
@@ -289,24 +285,52 @@
         return ret;
     }
 
-    public List<String> findAddressesByService(String service) {
+    @Override
+    public List<String> findAddressesByApplication(String application) {
         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);
+        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))) {
+                    String addr = u.getAddress();
+                    if (addr != null) {
+                        ret.add(addr);
+                    }
+                }
+            }
         }
 
         return ret;
     }
 
+    @Override
+    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;
+    }
+
+    @Override
     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;
+        if (null == providerUrls) {
+            return ret;
+        }
 
         Map<String, URL> value = providerUrls.get(service);
         if (value == null) {
@@ -314,17 +338,21 @@
         }
         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);
+            String app = u.getParameter(Constants.APPLICATION);
+            if (app != null){
+                ret.add(app);
+            }
         }
 
         return ret;
     }
 
+    @Override
     public List<Provider> findByService(String serviceName) {
         return SyncUtils.url2ProviderList(findProviderUrlByService(serviceName));
     }
 
+    @Override
     public List<Provider> findByAppandService(String app, String serviceName) {
         return SyncUtils.url2ProviderList(findProviderUrlByAppandService(app, serviceName));
     }
@@ -337,6 +365,7 @@
         return SyncUtils.filterFromCategory(getRegistryCache(), filter);
     }
 
+    @Override
     public List<Provider> findAll() {
         return SyncUtils.url2ProviderList(findAllProviderUrl());
     }
@@ -347,6 +376,7 @@
         return SyncUtils.filterFromCategory(getRegistryCache(), filter);
     }
 
+    @Override
     public List<Provider> findByAddress(String providerAddress) {
         return SyncUtils.url2ProviderList(findProviderUrlByAddress(providerAddress));
     }
@@ -359,11 +389,14 @@
         return SyncUtils.filterFromCategory(getRegistryCache(), filter);
     }
 
+    @Override
     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;
+        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();
@@ -379,23 +412,29 @@
         return ret;
     }
 
+    @Override
     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;
+        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);
+                String app = u.getParameter(Constants.APPLICATION);
+                if (app != null) {
+                    ret.add(app);
+                }
             }
         }
 
         return ret;
     }
 
+    @Override
     public List<Provider> findByApplication(String application) {
         return SyncUtils.url2ProviderList(findProviderUrlByApplication(application));
     }
@@ -425,7 +464,7 @@
     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(Constants.APPLICATION, app);
         filter.put(SyncUtils.SERVICE_FILTER_KEY, service);
         return SyncUtils.filterFromCategory(getRegistryCache(), filter);
     }
@@ -435,21 +474,24 @@
     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);
+        filter.put(Constants.APPLICATION, application);
         return SyncUtils.filterFromCategory(getRegistryCache(), filter);
     }
 
+    @Override
     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;
+        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))) {
+                if (application.equals(u.getParameter(Constants.APPLICATION))) {
                     ret.add(e1.getKey());
                     break;
                 }
@@ -459,14 +501,19 @@
         return ret;
     }
 
+    @Override
     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;
+        if (providerUrls == null || service == null || service.length() == 0){
+            return ret;
+        }
 
         Map<String, URL> providers = providerUrls.get(service);
-        if (null == providers || providers.isEmpty()) return ret;
+        if (null == providers || providers.isEmpty()) {
+            return ret;
+        }
 
         Entry<String, URL> p = providers.entrySet().iterator().next();
         String value = p.getValue().getParameter("methods");
@@ -488,6 +535,7 @@
         return findProvider(id).toUrl();
     }
 
+    @Override
     public Provider findByServiceAndAddress(String service, String address) {
         return SyncUtils.url2Provider(findProviderUrl(service, address));
     }
@@ -506,4 +554,73 @@
         }
     }
 
+    @Override
+    public Set<ServiceDTO> getServiceDTOS(String pattern, String filter, String env) {
+        List<Provider> providers = new ArrayList<>();
+        if (!filter.contains(Constants.ANY_VALUE) && !filter.contains(Constants.INTERROGATION_POINT)) {
+            // filter with specific string
+            if (Constants.IP.equals(pattern)) {
+                providers = findByAddress(filter);
+            } else if (Constants.SERVICE.equals(pattern)) {
+                providers = findByService(filter);
+            } else if (Constants.APPLICATION.equals(pattern)) {
+                providers = findByApplication(filter);
+            }
+        } else {
+            // filter with fuzzy search
+            List<String> candidates = Collections.emptyList();
+            if (Constants.SERVICE.equals(pattern)) {
+                candidates = findServices();
+            } else if (Constants.APPLICATION.equals(pattern)) {
+                candidates = findApplications();
+            }
+            // replace dot symbol and asterisk symbol to java-based regex pattern
+            filter = filter.toLowerCase().replace(Constants.PUNCTUATION_POINT, Constants.PUNCTUATION_SEPARATOR_POINT);
+            // filter start with [* 、? 、+] will triggering PatternSyntaxException
+            if (filter.startsWith(Constants.ANY_VALUE)
+                || filter.startsWith(Constants.INTERROGATION_POINT) || filter.startsWith(Constants.PLUS_SIGNS)) {
+                filter = Constants.PUNCTUATION_POINT + filter;
+            }
+            // search with no case insensitive
+            Pattern regex = Pattern.compile(filter, Pattern.CASE_INSENSITIVE);
+            for (String candidate : candidates) {
+                Matcher matcher = regex.matcher(candidate);
+                if (matcher.matches() || matcher.lookingAt()) {
+                    if (Constants.SERVICE.equals(pattern)) {
+                        providers.addAll(findByService(candidate));
+                    } else {
+                        providers.addAll(findByApplication(candidate));
+                    }
+                }
+            }
+        }
+
+        Set<ServiceDTO> result = convertProviders2DTO(providers);
+        return result;
+    }
+
+    /**
+     * Convert provider list to ServiceDTO list
+     *
+     * @param providers list of providers
+     * @return ServiceDTO list of front page
+     */
+    public Set<ServiceDTO> convertProviders2DTO(List<Provider> providers) {
+        Set<ServiceDTO> result = new TreeSet<>();
+        for (Provider provider : providers) {
+            Map<String, String> map = StringUtils.parseQueryString(provider.getParameters());
+            String app = provider.getApplication();
+            String service = map.get(Constants.INTERFACE_KEY);
+            String group = map.get(Constants.GROUP_KEY);
+            String version = map.get(Constants.VERSION_KEY);
+            ServiceDTO s = new ServiceDTO();
+            s.setAppName(app);
+            s.setService(service);
+            s.setGroup(group);
+            s.setVersion(version);
+            result.add(s);
+        }
+        return result;
+    }
+
 }
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
index b7e7def..bd1272e 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
+++ b/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/service/impl/RouteServiceImpl.java
@@ -19,13 +19,12 @@
 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.RouteUtils;
 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;
@@ -53,7 +52,7 @@
         if (existConfig != null) {
             existRule = YamlParser.loadObject(existConfig, RoutingRule.class);
         }
-        existRule = RouteRule.insertConditionRule(existRule, conditionRoute);
+        existRule = RouteUtils.insertConditionRule(existRule, conditionRoute);
         //register2.7
         dynamicConfiguration.setConfig(path, YamlParser.dumpObject(existRule));
 
@@ -74,8 +73,8 @@
             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);
+        ConditionRouteDTO oldConditionRoute = RouteUtils.createConditionRouteFromRule(routingRule);
+        routingRule = RouteUtils.insertConditionRule(routingRule, newConditionRoute);
         dynamicConfiguration.setConfig(path, YamlParser.dumpObject(routingRule));
 
         //for 2.6
@@ -98,8 +97,9 @@
             //throw exception
         }
         RoutingRule route = YamlParser.loadObject(config, RoutingRule.class);
-        if (route.getBlackWhiteList() != null) {
-           route.setConditions(null);
+        List<String> blackWhiteList = RouteUtils.filterBlackWhiteListFromConditions(route.getConditions());
+        if (blackWhiteList.size() != 0) {
+           route.setConditions(blackWhiteList);
             dynamicConfiguration.setConfig(path, YamlParser.dumpObject(route));
         } else {
             dynamicConfiguration.deleteConfig(path);
@@ -108,7 +108,7 @@
         //for 2.6
         if (route.getScope().equals(Constants.SERVICE)) {
             RoutingRule originRule = YamlParser.loadObject(config, RoutingRule.class);
-            ConditionRouteDTO conditionRouteDTO = RouteRule.createConditionRouteFromRule(originRule);
+            ConditionRouteDTO conditionRouteDTO = RouteUtils.createConditionRouteFromRule(originRule);
             Route old = convertRouteToOldRoute(conditionRouteDTO);
             registry.unregister(old.toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true));
         }
@@ -120,16 +120,17 @@
         String config = dynamicConfiguration.getConfig(path);
         if (config != null) {
             RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
-            BlackWhiteList old = ruleDTO.getBlackWhiteList();
-            if (ruleDTO.getConditions() == null) {
+            List<String> blackWhiteList = RouteUtils.filterBlackWhiteListFromConditions(ruleDTO.getConditions());
+            List<String> conditions = RouteUtils.filterConditionRuleFromConditions(ruleDTO.getConditions());
+            if (conditions.size() == 0) {
                 dynamicConfiguration.deleteConfig(path);
             } else {
-                ruleDTO.setBlackWhiteList(null);
+                ruleDTO.setConditions(conditions);
                 dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
             }
             //2.6
-            if (ruleDTO.getScope().equals(Constants.SERVICE) && old != null) {
-                Route route = RouteRule.convertBlackWhiteListtoRoute(old, Constants.SERVICE, id);
+            if (ruleDTO.getScope().equals(Constants.SERVICE) && blackWhiteList.size() > 0) {
+                Route route = RouteUtils.convertBlackWhiteListtoRoute(blackWhiteList, Constants.SERVICE, id);
                 registry.unregister(route.toUrl());
             }
         }
@@ -140,7 +141,7 @@
         String id = ConvertUtil.getIdFromDTO(accessDTO);
         String path = getPath(id, Constants.CONDITION_ROUTE);
         String config = dynamicConfiguration.getConfig(path);
-        BlackWhiteList blackWhiteList = RouteRule.convertToBlackWhiteList(accessDTO);
+        List<String> blackWhiteList = RouteUtils.convertToBlackWhiteList(accessDTO);
         RoutingRule ruleDTO;
         if (config == null) {
             ruleDTO = new RoutingRule();
@@ -151,19 +152,20 @@
                 ruleDTO.setScope(Constants.SERVICE);
             }
             ruleDTO.setKey(id);
-            ruleDTO.setBlackWhiteList(blackWhiteList);
+            ruleDTO.setConditions(blackWhiteList);
         } else {
             ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
-            if (ruleDTO.getBlackWhiteList() != null) {
-                //todo throw exception
+            if (ruleDTO.getConditions() == null) {
+                ruleDTO.setConditions(blackWhiteList);
+            } else {
+                ruleDTO.getConditions().addAll(blackWhiteList);
             }
-            ruleDTO.setBlackWhiteList(blackWhiteList);
         }
         dynamicConfiguration.setConfig(path, YamlParser.dumpObject(ruleDTO));
 
         //for 2.6
         if (ruleDTO.getScope().equals("service")) {
-            Route route = RouteRule.convertAccessDTOtoRoute(accessDTO);
+            Route route = RouteUtils.convertAccessDTOtoRoute(accessDTO);
             registry.register(route.toUrl());
         }
 
@@ -175,8 +177,8 @@
         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());
+            List<String> blackWhiteList = RouteUtils.filterBlackWhiteListFromConditions(ruleDTO.getConditions());
+            return RouteUtils.convertToAccessDTO(blackWhiteList, ruleDTO.getScope(), ruleDTO.getKey());
         }
         return null;
     }
@@ -185,20 +187,22 @@
     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;
+        List<String> blackWhiteList = RouteUtils.convertToBlackWhiteList(accessDTO);
         String config = dynamicConfiguration.getConfig(path);
+        List<String> oldList = null;
         if (config != null) {
             RoutingRule ruleDTO = YamlParser.loadObject(config, RoutingRule.class);
-            old = ruleDTO.getBlackWhiteList();
-            ruleDTO.setBlackWhiteList(blackWhiteList);
+            oldList = RouteUtils.filterBlackWhiteListFromConditions(ruleDTO.getConditions());
+            List<String> conditions = RouteUtils.filterConditionRuleFromConditions(ruleDTO.getConditions());
+            conditions.addAll(blackWhiteList);
+            ruleDTO.setConditions(conditions);
             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);
+            Route oldRoute = RouteUtils.convertBlackWhiteListtoRoute(oldList, Constants.SERVICE, key);
+            Route newRoute = RouteUtils.convertAccessDTOtoRoute(accessDTO);
             registry.unregister(oldRoute.toUrl());
             registry.register(newRoute.toUrl());
         }
@@ -213,7 +217,7 @@
 
             if (ruleDTO.getScope().equals(Constants.SERVICE)) {
                 //for2.6
-                URL oldURL = convertRouteToOldRoute(RouteRule.createConditionRouteFromRule(ruleDTO)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true);
+                URL oldURL = convertRouteToOldRoute(RouteUtils.createConditionRouteFromRule(ruleDTO)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG, true);
                 registry.unregister(oldURL);
                 oldURL = oldURL.addParameter("enabled", true);
                 registry.register(oldURL);
@@ -235,7 +239,7 @@
 
             if (routeRule.getScope().equals(Constants.SERVICE)) {
                 //for 2.6
-                URL oldURL = convertRouteToOldRoute(RouteRule.createConditionRouteFromRule(routeRule)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG,true);
+                URL oldURL = convertRouteToOldRoute(RouteUtils.createConditionRouteFromRule(routeRule)).toUrl().addParameter(Constants.COMPATIBLE_CONFIG,true);
                 registry.unregister(oldURL);
                 oldURL = oldURL.addParameter("enabled", false);
                 registry.register(oldURL);
@@ -254,7 +258,7 @@
         String config = dynamicConfiguration.getConfig(path);
         if (config != null) {
             RoutingRule routingRule = YamlParser.loadObject(config, RoutingRule.class);
-            ConditionRouteDTO conditionRouteDTO = RouteRule.createConditionRouteFromRule(routingRule);
+            ConditionRouteDTO conditionRouteDTO = RouteUtils.createConditionRouteFromRule(routingRule);
             return conditionRouteDTO;
         }
         return null;
@@ -264,7 +268,7 @@
     public void createTagRoute(TagRouteDTO tagRoute) {
         String id = ConvertUtil.getIdFromDTO(tagRoute);
         String path = getPath(id,Constants.TAG_ROUTE);
-        TagRoute store = RouteRule.convertTagroutetoStore(tagRoute);
+        TagRoute store = RouteUtils.convertTagroutetoStore(tagRoute);
         dynamicConfiguration.setConfig(path, YamlParser.dumpObject(store));
     }
 
@@ -276,7 +280,7 @@
             throw new ResourceNotFoundException("can not find tagroute: " + id);
             //throw exception
         }
-        TagRoute store = RouteRule.convertTagroutetoStore(tagRoute);
+        TagRoute store = RouteUtils.convertTagroutetoStore(tagRoute);
         dynamicConfiguration.setConfig(path, YamlParser.dumpObject(store));
 
     }
@@ -317,16 +321,16 @@
         String config = dynamicConfiguration.getConfig(path);
         if (config != null) {
             TagRoute tagRoute = YamlParser.loadObject(config, TagRoute.class);
-            return RouteRule.convertTagroutetoDisplay(tagRoute);
+            return RouteUtils.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";
+            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "condition-route";
         } else {
-            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "tagrouters";
+            return prefix + Constants.PATH_SEPARATOR + key + Constants.PATH_SEPARATOR + "tag-route";
         }
     }
 
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
deleted file mode 100644
index 12783c4..0000000
--- a/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.config.GovernanceConfiguration
+++ /dev/null
@@ -1,2 +0,0 @@
-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
deleted file mode 100644
index 0009f5d..0000000
--- a/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.data.metadata.MetaDataCollector
+++ /dev/null
@@ -1,2 +0,0 @@
-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/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration
new file mode 100644
index 0000000..11b2d39
--- /dev/null
+++ b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.config.GovernanceConfiguration
@@ -0,0 +1,2 @@
+zookeeper=org.apache.dubbo.admin.registry.config.impl.ZookeeperConfiguration
+apollo=org.apache.dubbo.admin.registry.config.impl.ApolloConfiguration
diff --git a/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.metadata.MetaDataCollector b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.metadata.MetaDataCollector
new file mode 100644
index 0000000..cd1a521
--- /dev/null
+++ b/dubbo-admin-backend/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.metadata.MetaDataCollector
@@ -0,0 +1,2 @@
+zookeeper=org.apache.dubbo.admin.registry.metadata.impl.ZookeeperMetaDataCollector
+redis=org.apache.dubbo.admin.registry.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 892d167..28fa8d0 100644
--- a/dubbo-admin-backend/src/main/resources/application.properties
+++ b/dubbo-admin-backend/src/main/resources/application.properties
@@ -15,8 +15,11 @@
 # limitations under the License.
 #
 
+dubbo.config-center.username=username
+dubbo.config-center.password=password
+dubbo.config-center=zookeeper://127.0.0.1:2181
 dubbo.registry.group=dubbo
-dubbo.configcenter=zookeeper://127.0.0.1:2181
+dubbo.registry.address=zookeeper://127.0.0.1:2181
 dubbo.apollo.token=e16e5cd903fd0c97a116c873b448544b9d086de9
 dubbo.apollo.appId=test
 dubbo.apollo.env=dev
diff --git a/dubbo-admin-backend/src/main/resources/log4j.properties b/dubbo-admin-backend/src/main/resources/log4j.properties
index 5be84a2..e269697 100644
--- a/dubbo-admin-backend/src/main/resources/log4j.properties
+++ b/dubbo-admin-backend/src/main/resources/log4j.properties
@@ -15,7 +15,7 @@
 # limitations under the License.
 #
 log4j.rootCategory=INFO, stdout, file
-log4j.logger.org.apache=ERROR
+log4j.logger.org.apache=WARN
 
 
 # 控制台输出
@@ -34,4 +34,4 @@
 log4j.appender.file.maxFileSize=10MB
 log4j.appender.file.maxBackupIndex=100
 log4j.appender.file.layout=org.apache.log4j.PatternLayout
-log4j.appender.file.layout.ConversionPattern=%d [%t] %-5p %C{6} (%F:%L) - %m%n
\ No newline at end of file
+log4j.appender.file.layout.ConversionPattern=%d [%t] %-5p %C{6} (%F:%L) - %m%n
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/common/util/UrlUtilsTest.java
similarity index 96%
rename from dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/governance/util/UrlUtilsTest.java
rename to dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/common/util/UrlUtilsTest.java
index faf4bd7..5250c17 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/common/util/UrlUtilsTest.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 org.apache.dubbo.admin.common.util.UrlUtils;
 import org.junit.Assert;
diff --git a/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
new file mode 100644
index 0000000..9e36350
--- /dev/null
+++ b/dubbo-admin-backend/src/test/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.apache.dubbo.admin.model.store.OverrideConfig;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class YamlParserTest {
+
+    private String streamToString(InputStream stream) throws IOException {
+        byte[] bytes = new byte[stream.available()];
+        stream.read(bytes);
+        return new String(bytes);
+    }
+
+    @Test
+    public void parseLoadBalanceTest() throws IOException {
+        try (InputStream yamlStream = this.getClass().getResourceAsStream("/LoadBalance.yml")) {
+            DynamicConfigDTO overrideDTO = YamlParser.loadObject(streamToString(yamlStream), DynamicConfigDTO.class);
+            assertEquals("v2.7", overrideDTO.getConfigVersion());
+            assertEquals(false, overrideDTO.isEnabled());
+            List<OverrideConfig> configs = overrideDTO.getConfigs();
+            assertEquals(2, configs.size());
+
+            OverrideConfig first = configs.get(0);
+            assertEquals("0.0.0.0:20880", first.getAddresses().get(0));
+            assertEquals("provider", first.getSide());
+            Map<String, Object> parameters = first.getParameters();
+            assertEquals(1, parameters.size());
+            assertEquals(2000, parameters.get("timeout"));
+
+            OverrideConfig second = configs.get(1);
+            assertEquals("balancing", second.getType());
+            assertEquals(true, second.isEnabled());
+            parameters = second.getParameters();
+            assertEquals(2, parameters.size());
+            assertEquals("*", parameters.get("method"));
+            assertEquals("random", parameters.get("strategy"));
+        }
+    }
+
+
+}
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
deleted file mode 100644
index 80604d7..0000000
--- a/dubbo-admin-backend/src/test/main/java/org/apache/dubbo/admin/common/util/YamlParserTest.java
+++ /dev/null
@@ -1,50 +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.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/resources/LoadBalance.yml
similarity index 77%
rename from dubbo-admin-backend/src/test/main/resources/LoadBalance.yml
rename to dubbo-admin-backend/src/test/resources/LoadBalance.yml
index bbf1742..2220097 100644
--- a/dubbo-admin-backend/src/test/main/resources/LoadBalance.yml
+++ b/dubbo-admin-backend/src/test/resources/LoadBalance.yml
@@ -1,7 +1,5 @@
 ---
-apiVersion: v2.7
-scope: application
-key: governance-consumer
+configVersion: v2.7
 enabled: false
 configs:
   - addresses: ["0.0.0.0:20880"]
diff --git a/dubbo-admin-frontend/package.json b/dubbo-admin-frontend/package.json
index 26e89c6..6a0a9ce 100644
--- a/dubbo-admin-frontend/package.json
+++ b/dubbo-admin-frontend/package.json
@@ -17,6 +17,7 @@
     "js-yaml": "^3.12.0",
     "jsoneditor": "^5.26.2",
     "vue": "^2.5.2",
+    "vue-i18n": "^8.6.0",
     "vue-router": "^3.0.1",
     "vuetify": "^1.2.2",
     "vuex": "^3.0.1"
diff --git a/dubbo-admin-frontend/src/api/menu.js b/dubbo-admin-frontend/src/api/menu.js
index 05f1660..6f5ccac 100644
--- a/dubbo-admin-frontend/src/api/menu.js
+++ b/dubbo-admin-frontend/src/api/menu.js
@@ -16,23 +16,23 @@
  */
 
 const Menu = [
-  { title: 'Service Search', path: '/service', icon: 'search' },
+  { title: 'serviceSearch', path: '/service', icon: 'search' },
   {
-    title: 'Service Governance',
+    title: 'serviceGovernance',
     icon: 'edit',
     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' },
-      { title: 'Load Balance', path: '/governance/loadbalance' }
+      { title: 'routingRule', path: '/governance/routingRule' },
+      {title: 'tagRule', path: '/governance/tagRule', badge: 'new'},
+      { title: 'accessControl', path: '/governance/access' },
+      { title: 'dynamicConfig', path: '/governance/config' },
+      { title: 'weightAdjust', path: '/governance/weight' },
+      { title: 'loadBalance', path: '/governance/loadbalance' }
     ]
   },
-  { title: 'Service Test', path: '/test', icon: 'code', badge: 'feature' },
-  { title: 'Service Mock', path: '/mock', icon: 'build', badge: 'feature' },
-  { title: 'Metrics', path: '/metrics', icon: 'show_chart', badge: 'feature' }
+  { title: 'serviceTest', path: '/test', icon: 'code', badge: 'feature' },
+  { title: 'serviceMock', path: '/mock', icon: 'build', badge: 'feature' },
+  { title: 'metrics', path: '/metrics', icon: 'show_chart', badge: 'feature' }
 
 ]
 
diff --git a/dubbo-admin-frontend/src/components/ServiceDetail.vue b/dubbo-admin-frontend/src/components/ServiceDetail.vue
index 74130ec..3618c0c 100644
--- a/dubbo-admin-frontend/src/components/ServiceDetail.vue
+++ b/dubbo-admin-frontend/src/components/ServiceDetail.vue
@@ -19,7 +19,7 @@
   <v-container grid-list-xl fluid >
     <v-layout row wrap >
       <v-flex sm12>
-        <h3>Basic Info</h3>
+        <h3>{{$t('basicInfo')}}</h3>
       </v-flex>
       <v-flex lg12>
         <v-data-table
@@ -34,16 +34,16 @@
         </v-data-table>
       </v-flex>
       <v-flex sm12>
-        <h3>Service Info</h3>
+        <h3>{{$t('serviceInfo')}}</h3>
       </v-flex>
       <v-flex lg12 >
         <v-tabs
           class="elevation-1">
           <v-tab>
-            providers
+            {{$t('providers')}}
           </v-tab>
           <v-tab>
-            consumers
+            {{$t('consumers')}}
           </v-tab>
           <v-tab-item>
             <v-data-table
@@ -85,7 +85,7 @@
         </v-tabs>
       </v-flex>
       <v-flex sm12>
-        <h3>Metadata</h3>
+        <h3>{{$t('metaData')}}</h3>
       </v-flex>
       <v-flex lg12>
         <v-data-table
@@ -101,6 +101,12 @@
               <v-chip label>{{props.item.returnType}}</v-chip>
             </td>
           </template>
+          <template slot="no-data">
+            <v-alert :value="true" color="warning" icon="warning">
+              {{$t('noMetadataHint')}}
+              <a :href="$t('configAddress')" target="_blank">{{$t('here')}}</a>
+            </v-alert>
+          </template>
         </v-data-table>
       </v-flex>
     </v-layout>
@@ -109,68 +115,74 @@
 <script>
   export default {
     data: () => ({
-      metaHeaders: [
-        {
-          text: 'Method Name',
-          value: 'method',
-          sortable: false
-        },
-        {
-          text: 'Parameter List',
-          value: 'parameter',
-          sortable: false
-        },
-        {
-          text: 'Return Type',
-          value: 'returnType',
-          sortable: false
-        }
-      ],
-      detailHeaders: {
-        providers: [
-          {
-            text: 'IP',
-            value: 'ip'
-          },
-          {
-            text: 'Port',
-            value: 'port'
-          },
-          {
-            text: 'Timeout(ms)',
-            value: 'timeout'
-          },
-          {
-            text: 'Serialization',
-            value: 'serial'
-          },
-          {
-            text: 'Operation',
-            value: 'operate'
-          }
-
-        ],
-        consumers: [
-          {
-            text: 'IP',
-            value: 'ip'
-          },
-          {
-            text: 'Port',
-            value: 'port'
-          },
-          {
-            text: 'Application Name',
-            value: 'appName'
-          }
-        ]
-      },
+      metaHeaders: [],
+      detailHeaders: {},
       providerDetails: [],
       consumerDetails: [],
       methodMetaData: [],
       basic: []
     }),
     methods: {
+      setmetaHeaders: function () {
+        this.metaHeaders = [
+          {
+            text: this.$t('methodName'),
+            value: 'method',
+            sortable: false
+          },
+          {
+            text: this.$t('parameterList'),
+            value: 'parameter',
+            sortable: false
+          },
+          {
+            text: this.$t('returnType'),
+            value: 'returnType',
+            sortable: false
+          }
+        ]
+      },
+      setdetailHeaders: function () {
+        this.detailHeaders = {
+          providers: [
+            {
+              text: this.$t('ip'),
+              value: 'ip'
+            },
+            {
+              text: this.$t('port'),
+              value: 'port'
+            },
+            {
+              text: this.$t('timeout'),
+              value: 'timeout'
+            },
+            {
+              text: this.$t('serialization'),
+              value: 'serial'
+            },
+            {
+              text: this.$t('operation'),
+              value: 'operate'
+            }
+
+          ],
+          consumers: [
+            {
+              text: this.$t('ip'),
+              value: 'ip'
+            },
+            {
+              text: this.$t('port'),
+              value: 'port'
+            },
+            {
+              text: this.$t('appName'),
+              value: 'appName'
+            }
+          ]
+        }
+      },
       detail: function (service) {
         this.$axios.get('/service/' + service)
             .then(response => {
@@ -196,6 +208,8 @@
       }
     },
     mounted: function () {
+      this.setmetaHeaders()
+      this.setdetailHeaders()
       let query = this.$route.query
       let meta = {
         'service': '',
diff --git a/dubbo-admin-frontend/src/components/ServiceSearch.vue b/dubbo-admin-frontend/src/components/ServiceSearch.vue
index 3725115..71c1156 100644
--- a/dubbo-admin-frontend/src/components/ServiceSearch.vue
+++ b/dubbo-admin-frontend/src/components/ServiceSearch.vue
@@ -34,7 +34,7 @@
                   hide-no-data
                   :suffix="queryBy"
                   :hint="hint"
-                  label="Search Dubbo Services"
+                  :label="$t('searchDubboService')"
                   @keyup.enter="submit"
                 ></v-combobox>
                 <v-menu class="hidden-xs-only">
@@ -47,11 +47,11 @@
                       v-for="(item, i) in items"
                       :key="i"
                       @click="selected = i">
-                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
                     </v-list-tile>
                   </v-list>
                 </v-menu>
-                <v-btn @click="submit" color="primary" large>Search</v-btn>
+                <v-btn @click="submit" color="primary" large>{{ $t('search') }}</v-btn>
               </v-layout>
             </v-form>
           </v-card-text>
@@ -62,7 +62,7 @@
     <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-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
           <v-spacer></v-spacer>
         </v-toolbar>
 
@@ -122,9 +122,9 @@
   export default {
     data: () => ({
       items: [
-        {id: 0, title: 'service name', value: 'service'},
-        {id: 1, title: 'IP', value: 'ip'},
-        {id: 2, title: 'application', value: 'application'}
+        {id: 0, title: 'serviceName', value: 'service'},
+        {id: 1, title: 'ip', value: 'ip'},
+        {id: 2, title: 'app', value: 'application'}
       ],
       options: [
         { title: 'Routing Rule',
@@ -155,55 +155,61 @@
       typeAhead: [],
       services: [],
       filter: '',
-      headers: [
-        {
-          text: 'Service Name',
-          value: 'service',
-          align: 'left'
-        },
-        {
-          text: 'Group',
-          value: 'group',
-          align: 'left'
-        },
-        {
-          text: 'Version',
-          value: 'version',
-          align: 'left'
-        },
-        {
-          text: 'Application',
-          value: 'application',
-          align: 'left'
-        },
-        {
-          text: 'Operation',
-          value: 'operation',
-          sortable: false,
-          width: '110px'
-        }
-      ]
+      headers: []
     }),
     computed: {
       queryBy () {
-        return 'by ' + this.items[this.selected].title
+        return 'by ' + this.$t(this.items[this.selected].title)
       },
       hint () {
         if (this.selected === 0) {
-          return 'Service ID, org.apache.dubbo.demo.api.DemoService, * for all services'
+          return this.$t('serviceSearchHint')
         } else if (this.selected === 1) {
-          return 'Find all services provided by the target server on the specified IP address'
+          return this.$t('ipSearchHint')
         } else if (this.selected === 2) {
-          return 'Input an application name to find all services provided by one particular application, * for all'
+          return this.$t('appSearchHint')
         }
       }
     },
     watch: {
       input (val) {
         this.querySelections(val)
+      },
+      area () {
+        this.setHeaders()
       }
     },
     methods: {
+      setHeaders: function () {
+        this.headers = [
+          {
+            text: this.$t('serviceName'),
+            value: 'service',
+            align: 'left'
+          },
+          {
+            text: this.$t('group'),
+            value: 'group',
+            align: 'left'
+          },
+          {
+            text: this.$t('version'),
+            value: 'version',
+            align: 'left'
+          },
+          {
+            text: this.$t('app'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '110px'
+          }
+        ]
+      },
       querySelections (v) {
         if (this.timerID) {
           clearTimeout(this.timerID)
@@ -236,7 +242,7 @@
         if (version != null) {
           query = query + '&version=' + version
         }
-        return '/#/serviceDetail?' + query
+        return '#/serviceDetail?' + query
       },
       governanceHref: function (type, service, group, version) {
         let base = '/#/governance/' + type
@@ -276,6 +282,7 @@
       }
     },
     mounted: function () {
+      this.setHeaders()
       let query = this.$route.query
       let filter = null
       let pattern = null
diff --git a/dubbo-admin-frontend/src/components/governance/AccessControl.vue b/dubbo-admin-frontend/src/components/governance/AccessControl.vue
index bfbb274..0b5f3c2 100644
--- a/dubbo-admin-frontend/src/components/governance/AccessControl.vue
+++ b/dubbo-admin-frontend/src/components/governance/AccessControl.vue
@@ -32,7 +32,7 @@
                   append-icon=""
                   hide-no-data
                   :suffix="queryBy"
-                  label="Search Routing Rule"
+                  :label="$t('searchRoutingRule')"
                 ></v-combobox>
                 <v-menu class="hidden-xs-only">
                   <v-btn slot="activator" large icon>
@@ -44,11 +44,11 @@
                       v-for="(item, i) in items"
                       :key="i"
                       @click="selected = i">
-                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
                     </v-list-tile>
                   </v-list>
                 </v-menu>
-                <v-btn @click="search" color="primary" large>Search</v-btn>
+                <v-btn @click="search" color="primary" large>{{$t('search')}}</v-btn>
 
               </v-layout>
             </v-form>
@@ -63,13 +63,13 @@
                    color="transparent"
                    class="elevation-0">
           <v-toolbar-title>
-            <span class="headline">Search Result</span>
+            <span class="headline">{{$t('searchResult')}}</span>
           </v-toolbar-title>
           <v-spacer></v-spacer>
           <v-btn outline
                  color="primary"
                  @click.stop="toCreate"
-                 class="mb-2">CREATE</v-btn>
+                 class="mb-2">{{$t('create')}}</v-btn>
         </v-toolbar>
 
         <v-card-text class="pa-0" v-if="selected == 0">
@@ -87,8 +87,16 @@
                           class="mr-2"
                           color="blue"
                           slot="activator"
-                          @click="toEdit(props.item)">edit</v-icon>
-                  <span>Edit</span>
+                          @click="toEdit(props.item, true)">visibility</v-icon>
+                  <span>{{$t('view')}}</span>
+                </v-tooltip>
+                <v-tooltip bottom>
+                  <v-icon small
+                          class="mr-2"
+                          color="blue"
+                          slot="activator"
+                          @click="toEdit(props.item, false)">edit</v-icon>
+                  <span>{{$t('edit')}}</span>
                 </v-tooltip>
                 <v-tooltip bottom>
                   <v-icon small
@@ -96,7 +104,7 @@
                           slot="activator"
                           color="red"
                           @click="toDelete(props.item)">delete</v-icon>
-                  <span>Delete</span>
+                  <span>{{$t('delete')}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -117,7 +125,15 @@
                           class="mr-2"
                           color="blue"
                           slot="activator"
-                          @click="toEdit(props.item)">edit</v-icon>
+                          @click="toEdit(props.item, true)">visibility</v-icon>
+                  <span>{{$t('view')}}</span>
+                </v-tooltip>
+                <v-tooltip bottom>
+                  <v-icon small
+                          class="mr-2"
+                          color="blue"
+                          slot="activator"
+                          @click="toEdit(props.item, false)">edit</v-icon>
                   <span>Edit</span>
                 </v-tooltip>
                 <v-tooltip bottom>
@@ -144,25 +160,44 @@
         </v-card-title>
         <v-card-text>
           <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"
-                          :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"
+              label="Service Unique ID"
+              :hint="$t('dataIdHint')"
+              :readonly="modal.readonly"
+              v-model="modal.service"
+            ></v-text-field>
+            <v-text-field
+              :label="$t('appName')"
+              :hint="$t('appNameHint')"
+              :readonly="modal.readonly"
               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-layout row justify-space-between>
+              <v-flex >
+                <v-text-field
+                  :readonly="modal.readonly"
+                  :label="$t('whiteList')"
+                  v-model="modal.whiteList"
+                  :hint="$t('whiteListHint')">
+                </v-text-field>
+              </v-flex>
+              <v-spacer></v-spacer>
+              <v-flex>
+                <v-text-field
+                  :label="$t('blackList')"
+                  :hint="$t('blackListHint')"
+                  v-model="modal.blackList"
+                  :readonly="modal.id != null">
+                </v-text-field>
+              </v-flex>
+            </v-layout>
           </v-form>
         </v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
           <v-btn color="darken-1"
                  flat
-                 @click="closeModal()">Close</v-btn>
+                 @click="closeModal()">{{$t('close')}}</v-btn>
           <v-btn color="primary"
                  depressed
                  @click="modal.click">{{ modal.saveBtn }}</v-btn>
@@ -180,10 +215,10 @@
           <v-spacer></v-spacer>
           <v-btn color="darken-1"
                  flat
-                 @click="confirm.enable = false">Disagree</v-btn>
+                 @click="confirm.enable = false">{{$t('disagree')}}</v-btn>
           <v-btn color="primary"
                  depressed
-                 @click="deleteItem(confirm.id)">Agree</v-btn>
+                 @click="deleteItem(confirm.id)">{{$t('agree')}}</v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -191,7 +226,6 @@
 </template>
 
 <script>
-import yaml from 'js-yaml'
 import AceEditor from '@/components/public/AceEditor'
 import Search from '@/components/public/Search'
 
@@ -199,41 +233,18 @@
   name: 'AccessControl',
   data: () => ({
     items: [
-      {id: 0, title: 'service name', value: 'service'},
-      {id: 1, title: 'application', value: 'application'}
+      {id: 0, title: 'serviceName', value: 'service'},
+      {id: 1, title: 'app', value: 'application'}
     ],
     selected: 0,
     filter: null,
     loading: false,
-    serviceHeaders: [
-      {
-        text: 'Service Name',
-        value: 'service',
-        align: 'left'
-      },
-      {
-        text: 'Operation',
-        value: 'operation',
-        sortable: false,
-        width: '115px'
-      }
-    ],
-    appHeaders: [
-      {
-        text: 'Application Name',
-        value: 'application',
-        align: 'left'
-      },
-      {
-        text: 'Operation',
-        value: 'operation',
-        sortable: false,
-        width: '115px'
-      }
-    ],
+    serviceHeaders: [],
+    appHeaders: [],
     accesses: [],
     modal: {
       enable: false,
+      readonly: false,
       title: 'Create New',
       saveBtn: 'Create',
       click: () => {},
@@ -241,6 +252,8 @@
       service: null,
       application: null,
       content: '',
+      blackList: '',
+      whiteList: '',
       template:
         'blacklist:\n' +
         '  - 1.1.1.1\n' +
@@ -262,10 +275,42 @@
     }
   }),
   methods: {
+    setAppHeaders () {
+      this.appHeaders = [
+        {
+          text: this.$t('appName'),
+          value: 'application',
+          align: 'left'
+        },
+        {
+          text: this.$t('operation'),
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
+      ]
+    },
+    setServiceHeaders () {
+      this.serviceHeaders = [
+        {
+          text: this.$t('serviceName'),
+          value: 'service',
+          align: 'left'
+        },
+        {
+          text: this.$t('operation'),
+          value: 'operation',
+          sortable: false,
+          width: '115px'
+        }
+      ]
+    },
     search () {
-      this.filter = document.querySelector('#serviceSearch').value.trim()
       if (!this.filter) {
-        return
+        this.filter = document.querySelector('#serviceSearch').value.trim()
+        if (!this.filter) {
+          return
+        }
       }
       let type = this.items[this.selected].value
       this.loading = true
@@ -305,18 +350,26 @@
       })
     },
     createItem () {
-      let doc = yaml.load(this.modal.content)
+      // let doc = yaml.load(this.modal.content)
       this.filter = ''
       if (!this.modal.service && !this.modal.application) {
         this.$notify.error('Either service or application is needed')
         return
       }
       let vm = this
+      let blackList = []
+      let whiteList = []
+      if (this.modal.blackList) {
+        blackList = this.modal.blackList.split(',')
+      }
+      if (this.modal.whiteList) {
+        whiteList = this.modal.whiteList.split(',')
+      }
       this.$axios.post('/rules/access', {
         service: this.modal.service,
         application: this.modal.application,
-        whitelist: doc.whitelist,
-        blacklist: doc.blacklist
+        whitelist: whiteList,
+        blacklist: blackList
       }).then(response => {
         if (response.status === 201) {
           if (vm.modal.service) {
@@ -332,7 +385,7 @@
         this.showSnackbar('success', 'Create success')
       }).catch(error => this.showSnackbar('error', error.response.data.message))
     },
-    toEdit (item) {
+    toEdit (item, readonly) {
       let itemId = null
       if (this.selected === 0) {
         itemId = item.service
@@ -344,21 +397,26 @@
       }
       Object.assign(this.modal, {
         enable: true,
+        readonly: readonly,
         title: 'Edit',
         saveBtn: 'Update',
         click: this.editItem,
         id: itemId,
         service: item.service,
         application: item.application,
-        content: yaml.safeDump({blacklist: item.blacklist, whitelist: item.whitelist})
+        whiteList: item.whitelist,
+        blackList: item.blacklist
+        // content: yaml.safeDump({blacklist: item.blacklist, whitelist: item.whitelist})
       })
     },
     editItem () {
-      let doc = yaml.load(this.modal.content)
+      // let doc = yaml.load(this.modal.content)
+      let blackList = this.modal.blackList.split(',')
+      let whiteList = this.modal.whiteList.split(',')
       let vm = this
       this.$axios.put('/rules/access/' + this.modal.id, {
-        whitelist: doc.whitelist,
-        blacklist: doc.blacklist,
+        whitelist: whiteList,
+        blacklist: blackList,
         application: this.modal.application,
         service: this.modal.service
 
@@ -405,10 +463,18 @@
   },
   computed: {
     queryBy () {
-      return 'by ' + this.items[this.selected].title
+      return 'by ' + this.$t(this.items[this.selected].title)
+    }
+  },
+  watch: {
+    area () {
+      this.setAppHeaders()
+      this.setServiceHeaders()
     }
   },
   mounted () {
+    this.setAppHeaders()
+    this.setServiceHeaders()
     let query = this.$route.query
     if ('service' in query) {
       this.filter = query['service']
diff --git a/dubbo-admin-frontend/src/components/governance/LoadBalance.vue b/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
index 650cc8f..6a1eb56 100644
--- a/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
+++ b/dubbo-admin-frontend/src/components/governance/LoadBalance.vue
@@ -30,7 +30,7 @@
                   append-icon=""
                   hide-no-data
                   :suffix="queryBy"
-                  label="Search Balancing Rule"
+                  :label="$t('searchBalanceRule')"
                 ></v-combobox>
                 <v-menu class="hidden-xs-only">
                   <v-btn slot="activator" large icon>
@@ -42,11 +42,11 @@
                       v-for="(item, i) in items"
                       :key="i"
                       @click="selected = i">
-                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
                     </v-list-tile>
                   </v-list>
                 </v-menu>
-                <v-btn @click="submit" color="primary" large>Search</v-btn>
+                <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
 
               </v-layout>
             </v-form>
@@ -58,9 +58,9 @@
     <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-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
           <v-spacer></v-spacer>
-          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
         </v-toolbar>
 
         <v-card-text class="pa-0" v-if="selected == 0">
@@ -78,7 +78,7 @@
                   <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon, props.item)">
                     {{op.icon}}
                   </v-icon>
-                  <span>{{op.tooltip}}</span>
+                  <span>{{$t(op.tooltip)}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -100,7 +100,7 @@
                   <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon, props.item)">
                     {{op.icon}}
                   </v-icon>
-                  <span>{{op.tooltip}}</span>
+                  <span>{{$t(op.tooltip)}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -117,34 +117,53 @@
         <v-card-text >
           <v-text-field
             label="Service Unique ID"
-            hint="A service ID in form of group/service:version, group and version are optional"
+            :hint="$t('dataIdHint')"
             v-model="service"
+            :readonly="readonly"
           ></v-text-field>
           <v-text-field
-            label="Application Name"
-            hint="Application name the service belongs to"
+            :label="$t('appName')"
+            :hint="$t('appNameHint')"
             v-model="application"
+            :readonly="readonly"
           ></v-text-field>
-          <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
-          <ace-editor v-model="ruleText" :readonly="readonly"/>
+          <v-layout row justify-space-between>
+            <v-flex >
+              <v-text-field
+                :label="$t('method')"
+                :hint="$t('methodHint')"
+                v-model="rule.method"
+                :readonly="readonly"
+              ></v-text-field>
+            </v-flex>
+            <v-spacer></v-spacer>
+            <v-flex>
+              <v-select
+                :items="rule.strategyKey"
+                :label="$t('strategy')"
+                v-model="rule.strategy"
+                :readonly="readonly"
+              ></v-select>
+            </v-flex>
+          </v-layout>
 
         </v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
-          <v-btn color="darken-1" flat @click.native="closeDialog">Close</v-btn>
-          <v-btn color="primary darken-1" depressed @click.native="saveItem">Save</v-btn>
+          <v-btn color="darken-1" flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+          <v-btn color="primary darken-1" depressed @click.native="saveItem">{{$t('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-title class="headline">{{$t(this.warnTitle)}}</v-card-title>
         <v-card-text >{{this.warnText}}</v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
-          <v-btn color="darken-1" flat @click.native="closeWarn">CANCLE</v-btn>
-          <v-btn color="primary darken-1" depressed @click.native="deleteItem(warnStatus.id)">CONFIRM</v-btn>
+          <v-btn color="darken-1" flat @click.native="closeWarn">{{$t('cancel')}}</v-btn>
+          <v-btn color="primary darken-1" depressed @click.native="deleteItem(warnStatus.id)">{{$t('confirm')}}</v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -153,7 +172,6 @@
 
 </template>
 <script>
-  import yaml from 'js-yaml'
   import AceEditor from '@/components/public/AceEditor'
   import Search from '@/components/public/Search'
   export default {
@@ -163,8 +181,8 @@
     },
     data: () => ({
       items: [
-        {id: 0, title: 'service name', value: 'service'},
-        {id: 1, title: 'application', value: 'application'}
+        {id: 0, title: 'serviceName', value: 'service'},
+        {id: 1, title: 'app', value: 'application'}
       ],
       selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
@@ -181,57 +199,81 @@
       warnStatus: {},
       height: 0,
       operations: [
-        {id: 0, icon: 'visibility', tooltip: 'View'},
-        {id: 1, icon: 'edit', tooltip: 'Edit'},
-        {id: 3, icon: 'delete', tooltip: 'Delete'}
+        {id: 0, icon: 'visibility', tooltip: 'view'},
+        {id: 1, icon: 'edit', tooltip: 'edit'},
+        {id: 3, icon: 'delete', tooltip: 'delete'}
       ],
-      loadBalances: [
-      ],
+      loadBalances: [],
       template:
         'methodName: *  # * for all methods\n' +
         'strategy:  # leastactive, random, roundrobin',
+      rule: {
+        method: '',
+        strategy: '',
+        strategyKey: [
+          {
+            text: 'Least Active',
+            value: 'leastactive'
+          },
+          {
+            text: 'Random',
+            value: 'random'
+          },
+          {
+            text: 'Round Robin',
+            value: 'roundrobin'
+          }
+
+        ]
+      },
       ruleText: '',
       readonly: false,
-      serviceHeaders: [
-        {
-          text: 'Service Name',
-          value: 'service',
-          align: 'left'
-        },
-        {
-          text: 'Method',
-          value: 'method',
-          align: 'left'
-
-        },
-        {
-          text: 'Operation',
-          value: 'operation',
-          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'
-        }
-      ]
+      serviceHeaders: [],
+      appHeaders: []
     }),
     methods: {
+      setServiceHeaders: function () {
+        this.serviceHeaders = [
+          {
+            text: this.$t('serviceName'),
+            value: 'service',
+            align: 'left'
+          },
+          {
+            text: this.$t('method'),
+            value: 'method',
+            align: 'left'
+
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
+      setAppHeaders: function () {
+        this.appHeaders = [
+          {
+            text: this.$t('appName'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('method'),
+            value: 'method',
+            align: 'left'
+
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
       submit: function () {
         this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
@@ -273,7 +315,8 @@
       },
       saveItem: function () {
         this.ruleText = this.verifyRuleText(this.ruleText)
-        let balancing = yaml.safeLoad(this.ruleText)
+        // let balancing = yaml.safeLoad(this.ruleText)
+        let balancing = {}
         if (!this.service && !this.application) {
           this.$notify.error('Either service or application is needed')
           return
@@ -281,6 +324,8 @@
         let vm = this
         balancing.service = this.service
         balancing.application = this.application
+        balancing.methodName = this.rule.method
+        balancing.strategy = this.rule.strategy
         if (this.updateId) {
           if (this.updateId === 'close') {
             this.closeDialog()
@@ -358,10 +403,12 @@
       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)
+        // delete balancing.service
+        // delete balancing.application
+        // delete balancing.id
+        // this.ruleText = yaml.safeDump(balancing)
+        this.rule.method = balancing.methodName
+        this.rule.strategy = balancing.strategy
         this.readonly = readonly
         this.dialog = true
       },
@@ -394,10 +441,18 @@
     },
     computed: {
       queryBy () {
-        return 'by ' + this.items[this.selected].title
+        return 'by ' + this.$t(this.items[this.selected].title)
+      }
+    },
+    watch: {
+      area () {
+        this.setServiceHeaders()
+        this.setAppHeaders()
       }
     },
     mounted: function () {
+      this.setServiceHeaders()
+      this.setAppHeaders()
       this.ruleText = this.template
       let query = this.$route.query
       let filter = null
diff --git a/dubbo-admin-frontend/src/components/governance/Overrides.vue b/dubbo-admin-frontend/src/components/governance/Overrides.vue
index 89c9aa4..9b51345 100644
--- a/dubbo-admin-frontend/src/components/governance/Overrides.vue
+++ b/dubbo-admin-frontend/src/components/governance/Overrides.vue
@@ -30,7 +30,7 @@
                   append-icon=""
                   hide-no-data
                   :suffix="queryBy"
-                  label="Search Dynamic Config"
+                  :label="$t('searchDynamicConfig')"
                 ></v-combobox>
                 <v-menu class="hidden-xs-only">
                   <v-btn slot="activator" large icon>
@@ -42,11 +42,11 @@
                       v-for="(item, i) in items"
                       :key="i"
                       @click="selected = i">
-                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
                     </v-list-tile>
                   </v-list>
                 </v-menu>
-                <v-btn @click="submit" color="primary" large>Search</v-btn>
+                <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
 
               </v-layout>
             </v-form>
@@ -58,9 +58,9 @@
     <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-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
           <v-spacer></v-spacer>
-          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
         </v-toolbar>
 
         <v-card-text class="pa-0" v-if="selected == 0">
@@ -77,7 +77,7 @@
                   <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>
+                  <span>{{$t(op.tooltip(props.item))}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -98,7 +98,7 @@
                   <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>
+                  <span>{{$t(op.tooltip(props.item))}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -110,7 +110,7 @@
     <v-dialog   v-model="dialog" width="800px" persistent >
       <v-card>
         <v-card-title class="justify-center">
-          <span class="headline">Create New Dynamic Config Rule</span>
+          <span class="headline">{{$t('createNewDynamicConfigRule')}}</span>
         </v-card-title>
         <v-card-text >
           <v-text-field
@@ -124,26 +124,26 @@
             v-model="application"
           ></v-text-field>
 
-          <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
+          <v-subheader class="pa-0 mt-3">{{$t('ruleContent')}}</v-subheader>
           <ace-editor v-model="ruleText" :readonly="readonly"/>
 
         </v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
-          <v-btn color="darken-1" flat @click.native="closeDialog">Close</v-btn>
-          <v-btn color="primary darken-1" depressed @click.native="saveItem">Save</v-btn>
+          <v-btn color="darken-1" flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+          <v-btn color="primary darken-1" depressed @click.native="saveItem">{{$t('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-title class="headline">{{$t(this.warnTitle)}}</v-card-title>
         <v-card-text >{{this.warnText}}</v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
-          <v-btn color="darken-1" flat @click.native="closeWarn">CANCLE</v-btn>
-          <v-btn color="primary darken-1" depressed @click.native="deleteItem(warnStatus)">CONFIRM</v-btn>
+          <v-btn color="darken-1" flat @click.native="closeWarn">{{$t('cancel')}}</v-btn>
+          <v-btn color="primary darken-1" depressed @click.native="deleteItem(warnStatus)">{{$t('confirm')}}</v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -163,8 +163,8 @@
     },
     data: () => ({
       items: [
-        {id: 0, title: 'service name', value: 'service'},
-        {id: 1, title: 'application', value: 'application'}
+        {id: 0, title: 'serviceName', value: 'service'},
+        {id: 1, title: 'app', value: 'application'}
       ],
       selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
@@ -195,34 +195,40 @@
         '      timeout: 6000       # dynamic config parameter\n',
       ruleText: '',
       readonly: false,
-      serviceHeaders: [
-        {
-          text: 'Service Name',
-          value: 'service',
-          align: 'left'
-        },
-        {
-          text: 'Operation',
-          value: 'operation',
-          sortable: false,
-          width: '115px'
-        }
-      ],
-      appHeaders: [
-        {
-          text: 'Application Name',
-          value: 'application',
-          align: 'left'
-        },
-        {
-          text: 'Operation',
-          value: 'operation',
-          sortable: false,
-          width: '115px'
-        }
-      ]
+      serviceHeaders: [],
+      appHeaders: []
     }),
     methods: {
+      setAppHeaders: function () {
+        this.appHeaders = [
+          {
+            text: this.$t('appName'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
+      setServiceHeaders: function () {
+        this.serviceHeaders = [
+          {
+            text: this.$t('serviceName'),
+            value: 'service',
+            align: 'left'
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
       submit: function () {
         this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
@@ -422,10 +428,18 @@
     },
     computed: {
       queryBy () {
-        return 'by ' + this.items[this.selected].title
+        return 'by ' + this.$t(this.items[this.selected].title)
+      }
+    },
+    watch: {
+      area () {
+        this.setAppHeaders()
+        this.setServiceHeaders()
       }
     },
     mounted: function () {
+      this.setAppHeaders()
+      this.setServiceHeaders()
       this.ruleText = this.template
       let query = this.$route.query
       let filter = null
diff --git a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue b/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
index d87ae45..97ef8cc 100644
--- a/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
+++ b/dubbo-admin-frontend/src/components/governance/RoutingRule.vue
@@ -30,7 +30,7 @@
                   append-icon=""
                   hide-no-data
                   :suffix="queryBy"
-                  label="Search Routing Rule"
+                  :label="$t('searchRoutingRule')"
                 ></v-combobox>
                 <v-menu class="hidden-xs-only">
                   <v-btn slot="activator" large icon>
@@ -42,11 +42,11 @@
                       v-for="(item, i) in items"
                       :key="i"
                       @click="selected = i">
-                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
                     </v-list-tile>
                   </v-list>
                 </v-menu>
-                <v-btn @click="submit" color="primary" large>Search</v-btn>
+                <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
 
               </v-layout>
             </v-form>
@@ -57,9 +57,9 @@
     <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-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
           <v-spacer></v-spacer>
-          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
         </v-toolbar>
 
         <v-card-text class="pa-0" v-if="selected == 0">
@@ -78,7 +78,7 @@
                   <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>
+                  <span>{{$t(op.tooltip(props.item))}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -99,7 +99,7 @@
                   <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>
+                  <span>{{$t(op.tooltip(props.item))}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -111,12 +111,12 @@
     <v-dialog   v-model="dialog" width="800px" persistent >
       <v-card>
         <v-card-title class="justify-center">
-          <span class="headline">Create New Routing Rule</span>
+          <span class="headline">{{$t('createNewRoutingRule')}}</span>
         </v-card-title>
         <v-card-text >
           <v-text-field
             label="Service Unique ID"
-            hint="A service ID in form of group/service:version, group and version are optional"
+            :hint="$t('dataIdHint')"
             v-model="service"
           ></v-text-field>
           <v-text-field
@@ -125,26 +125,26 @@
             v-model="application"
           ></v-text-field>
 
-          <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
+          <v-subheader class="pa-0 mt-3">{{$t('ruleContent')}}</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-btn flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+          <v-btn depressed color="primary" @click.native="saveItem">{{$t('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-title class="headline">{{$t(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-btn flat @click.native="closeWarn">{{$t('cancel')}}</v-btn>
+          <v-btn depressed color="primary" @click.native="deleteItem(warnStatus)">{{$t('confirm')}}</v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -162,8 +162,8 @@
     },
     data: () => ({
       items: [
-        {id: 0, title: 'service name', value: 'service'},
-        {id: 1, title: 'application', value: 'application'}
+        {id: 0, title: 'serviceName', value: 'service'},
+        {id: 1, title: 'app', value: 'application'}
       ],
       selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
@@ -192,50 +192,56 @@
         ' - \'=> host != 172.22.3.91\'\n',
       ruleText: '',
       readonly: false,
-      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',
-          align: 'left'
-        },
-        {
-          text: 'Group',
-          value: 'group',
-          align: 'left'
-
-        },
-        {
-          text: 'Enabled',
-          value: 'enabled',
-          sortable: false
-        },
-        {
-          text: 'Operation',
-          value: 'operation',
-          sortable: false,
-          width: '115px'
-        }
-      ]
+      appHeaders: [],
+      serviceHeaders: []
     }),
     methods: {
+      setAppHeaders: function () {
+        this.appHeaders = [
+          {
+            text: this.$t('appName'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('enabled'),
+            value: 'enabled',
+            sortable: false
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
+      setServiceHeaders: function () {
+        this.serviceHeaders = [
+          {
+            text: this.$t('serviceName'),
+            value: 'service',
+            align: 'left'
+          },
+          {
+            text: this.$t('group'),
+            value: 'group',
+            align: 'left'
+
+          },
+          {
+            text: this.$t('enabled'),
+            value: 'enabled',
+            sortable: false
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
       submit: function () {
         this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
@@ -430,10 +436,18 @@
     },
     computed: {
       queryBy () {
-        return 'by ' + this.items[this.selected].title
+        return 'by ' + this.$t(this.items[this.selected].title)
+      }
+    },
+    watch: {
+      area () {
+        this.setAppHeaders()
+        this.setServiceHeaders()
       }
     },
     mounted: function () {
+      this.setAppHeaders()
+      this.setServiceHeaders()
       this.ruleText = this.template
       let query = this.$route.query
       let filter = null
diff --git a/dubbo-admin-frontend/src/components/governance/TagRule.vue b/dubbo-admin-frontend/src/components/governance/TagRule.vue
index 17b3bb2..19242fe 100644
--- a/dubbo-admin-frontend/src/components/governance/TagRule.vue
+++ b/dubbo-admin-frontend/src/components/governance/TagRule.vue
@@ -19,15 +19,15 @@
   <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>
+        <search id="serviceSearch" v-model="filter" :submit="submit" :label="$t('searchTagRule')"></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-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
           <v-spacer></v-spacer>
-          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
         </v-toolbar>
 
         <v-card-text class="pa-0" >
@@ -45,7 +45,7 @@
                   <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>
+                  <span>{{$t(op.tooltip(props.item))}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -57,30 +57,30 @@
     <v-dialog   v-model="dialog" width="800px" persistent >
       <v-card>
         <v-card-title class="justify-center">
-          <span class="headline">Create New Routing Rule</span>
+          <span class="headline">{{$t('createNewTagRule')}}</span>
         </v-card-title>
         <v-card-text >
           <v-text-field
-            label="Application Name"
-            hint="Application name the service belongs to"
+            :label="$t('appName')"
+            :hint="$t('appNameHint')"
             v-model="application"
           ></v-text-field>
 
-          <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
+          <v-subheader class="pa-0 mt-3">{{$t('ruleContent')}}</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-btn flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+          <v-btn depressed color="primary" @click.native="saveItem">{{$t('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-title class="headline">{{$t(this.warnTitle)}}</v-card-title>
         <v-card-text >{{this.warnText}}</v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
@@ -131,26 +131,29 @@
         '   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'
-        }
-      ]
+      headers: []
     }),
     methods: {
+      setHeaders: function () {
+        this.headers = [
+          {
+            text: this.$t('appName'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('enabled'),
+            value: 'enabled',
+            sortable: false
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
       submit: function () {
         this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
@@ -244,17 +247,17 @@
               })
             break
           case 'block':
-            this.openWarn(' Are you sure to block Routing Rule', 'application: ' + item.application)
+            this.openWarn(' Are you sure to block Tag 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.openWarn(' Are you sure to enable Tag 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.openWarn(' Are you sure to Delete Tag Rule', 'application: ' + item.application)
             this.warnStatus.operation = 'delete'
             this.warnStatus.id = itemId
         }
@@ -310,7 +313,13 @@
     created () {
       this.setHeight()
     },
+    watch: {
+      area () {
+        this.setHeaders()
+      }
+    },
     mounted: function () {
+      this.setHeaders()
       this.ruleText = this.template
       let query = this.$route.query
       let filter = null
diff --git a/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue b/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
index f21b34e..60515cd 100644
--- a/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
+++ b/dubbo-admin-frontend/src/components/governance/WeightAdjust.vue
@@ -30,7 +30,7 @@
                   append-icon=""
                   hide-no-data
                   :suffix="queryBy"
-                  label="Search Routing Rule"
+                  :label="$t('searchWeightRule')"
                 ></v-combobox>
                 <v-menu class="hidden-xs-only">
                   <v-btn slot="activator" large icon>
@@ -42,11 +42,11 @@
                       v-for="(item, i) in items"
                       :key="i"
                       @click="selected = i">
-                      <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+                      <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
                     </v-list-tile>
                   </v-list>
                 </v-menu>
-                <v-btn @click="submit" color="primary" large>Search</v-btn>
+                <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
 
               </v-layout>
             </v-form>
@@ -58,9 +58,9 @@
     <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-toolbar-title><span class="headline">{{$t('searchResult')}}</span></v-toolbar-title>
           <v-spacer></v-spacer>
-          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">CREATE</v-btn>
+          <v-btn outline color="primary" @click.stop="openDialog" class="mb-2">{{$t('create')}}</v-btn>
         </v-toolbar>
 
         <v-card-text class="pa-0" v-if="selected == 0">
@@ -78,7 +78,7 @@
                   <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon, props.item)">
                     {{op.icon}}
                   </v-icon>
-                  <span>{{op.tooltip}}</span>
+                  <span>{{$t(op.tooltip)}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -99,7 +99,7 @@
                   <v-icon small class="mr-2" slot="activator" @click="itemOperation(op.icon, props.item)">
                     {{op.icon}}
                   </v-icon>
-                  <span>{{op.tooltip}}</span>
+                  <span>{{$t(op.tooltip)}}</span>
                 </v-tooltip>
               </td>
             </template>
@@ -111,28 +111,45 @@
     <v-dialog   v-model="dialog" width="800px" persistent >
       <v-card>
         <v-card-title class="justify-center">
-          <span class="headline">Create New Weight Rule</span>
+          <span class="headline">{{$t('createNewWeightRule')}}</span>
         </v-card-title>
         <v-card-text >
           <v-text-field
             label="Service Unique ID"
-            hint="A service ID in form of group/service:version, group and version are optional"
+            :hint="$t('serviceIdHint')"
             v-model="service"
+            :readonly="readonly"
           ></v-text-field>
           <v-text-field
-            label="Application Name"
-            hint="Application name the service belongs to"
+            :label="$t('appName')"
+            :hint="$t('appNameHint')"
             v-model="application"
+            :readonly="readonly"
           ></v-text-field>
-          <v-subheader class="pa-0 mt-3">RULE CONTENT</v-subheader>
-
-          <ace-editor v-model="ruleText" :readonly="readonly"></ace-editor>
-
+          <v-layout row justify-space-between>
+            <v-flex >
+              <v-text-field
+                :label="$t('weight')"
+                :hint="$t('weightHint')"
+                v-model="rule.weight"
+                :readonly="readonly"
+              ></v-text-field>
+            </v-flex>
+            <v-spacer></v-spacer>
+            <v-flex>
+              <v-text-field
+                :label="$t('address')"
+                :hint="$t('weightAddressHint')"
+                v-model="rule.address"
+                :readonly="readonly"
+              ></v-text-field>
+            </v-flex>
+          </v-layout>
         </v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
-          <v-btn color="darken-1" flat @click.native="closeDialog">Close</v-btn>
-          <v-btn color="primary darken-1" depressed @click.native="saveItem">Save</v-btn>
+          <v-btn color="darken-1" flat @click.native="closeDialog">{{$t('close')}}</v-btn>
+          <v-btn color="primary darken-1" depressed @click.native="saveItem">{{$t('save')}}</v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -143,8 +160,8 @@
         <v-card-text >{{this.warnText}}</v-card-text>
         <v-card-actions>
           <v-spacer></v-spacer>
-          <v-btn color="darken-1" flat @click.native="closeWarn">CANCLE</v-btn>
-          <v-btn color="primary darken-1" depressed @click.native="deleteItem(warnStatus)">CONFIRM</v-btn>
+          <v-btn color="darken-1" flat @click.native="closeWarn">{{$t('cancel')}}</v-btn>
+          <v-btn color="primary darken-1" depressed @click.native="deleteItem(warnStatus)">{{$t('confirm')}}</v-btn>
         </v-card-actions>
       </v-card>
     </v-dialog>
@@ -154,7 +171,6 @@
 
 <script>
   import AceEditor from '@/components/public/AceEditor'
-  import yaml from 'js-yaml'
   import Search from '@/components/public/Search'
   export default {
     components: {
@@ -163,8 +179,8 @@
     },
     data: () => ({
       items: [
-        {id: 0, title: 'service name', value: 'service'},
-        {id: 1, title: 'application', value: 'application'}
+        {id: 0, title: 'serviceName', value: 'service'},
+        {id: 1, title: 'app', value: 'application'}
       ],
       selected: 0,
       dropdown_font: [ 'Service', 'App', 'IP' ],
@@ -181,9 +197,9 @@
       warnStatus: {},
       height: 0,
       operations: [
-        {id: 0, icon: 'visibility', tooltip: 'View'},
-        {id: 1, icon: 'edit', tooltip: 'Edit'},
-        {id: 3, icon: 'delete', tooltip: 'Delete'}
+        {id: 0, icon: 'visibility', tooltip: 'view'},
+        {id: 1, icon: 'edit', tooltip: 'edit'},
+        {id: 3, icon: 'delete', tooltip: 'delete'}
       ],
       weights: [
       ],
@@ -193,47 +209,57 @@
         '  - 192.168.0.1\n' +
         '  - 192.168.0.2',
       ruleText: '',
+      rule: {
+        weight: 100,
+        address: ''
+      },
       readonly: false,
-      serviceHeaders: [
-        {
-          text: 'Service Name',
-          value: 'service',
-          align: 'left'
-        },
-        {
-          text: 'Weight',
-          value: 'weight',
-          align: 'left'
-
-        },
-        {
-          text: 'Operation',
-          value: 'operation',
-          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'
-        }
-      ]
+      serviceHeaders: [],
+      appHeaders: []
     }),
     methods: {
+      setServiceHeaders: function () {
+        this.serviceHeaders = [
+          {
+            text: this.$t('serviceName'),
+            value: 'service',
+            align: 'left'
+          },
+          {
+            text: this.$t('weight'),
+            value: 'weight',
+            align: 'left'
+
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
+      setAppHeaders: function () {
+        this.appHeaders = [
+          {
+            text: this.$t('appName'),
+            value: 'application',
+            align: 'left'
+          },
+          {
+            text: this.$t('weight'),
+            value: 'weight',
+            align: 'left'
+
+          },
+          {
+            text: this.$t('operation'),
+            value: 'operation',
+            sortable: false,
+            width: '115px'
+          }
+        ]
+      },
       submit: function () {
         this.filter = document.querySelector('#serviceSearch').value.trim()
         this.search(this.filter, true)
@@ -255,6 +281,8 @@
       },
       closeDialog: function () {
         this.ruleText = this.template
+        this.rule.address = ''
+        this.rule.weight = 100
         this.service = ''
         this.dialog = false
         this.readonly = false
@@ -274,13 +302,16 @@
         this.warn = false
       },
       saveItem: function () {
-        let weight = yaml.safeLoad(this.ruleText)
+        let weight = {}
+        // let weight = yaml.safeLoad(this.ruleText)
         if (!this.service && !this.application) {
           this.$notify.error('Either service or application is needed')
           return
         }
         weight.service = this.service
         weight.application = this.application
+        weight.weight = this.rule.weight
+        weight.addresses = this.rule.address.split(',')
         let vm = this
         if (this.updateId) {
           if (this.updateId === 'close') {
@@ -359,9 +390,11 @@
       handleWeight: function (weight, readonly) {
         this.service = weight.service
         this.application = weight.application
-        delete weight.service
-        delete weight.application
-        this.ruleText = yaml.safeDump(weight)
+        // delete weight.service
+        // delete weight.application
+        // this.ruleText = yaml.safeDump(weight)
+        this.rule.weight = weight.weight
+        this.rule.address = weight.addresses.join(',')
         this.readonly = readonly
         this.dialog = true
       },
@@ -384,10 +417,18 @@
     },
     computed: {
       queryBy () {
-        return 'by ' + this.items[this.selected].title
+        return 'by ' + this.$t(this.items[this.selected].title)
+      }
+    },
+    watch: {
+      area () {
+        this.setAppHeaders()
+        this.setServiceHeaders()
       }
     },
     mounted: function () {
+      this.setAppHeaders()
+      this.setServiceHeaders()
       this.ruleText = this.template
       let query = this.$route.query
       let filter = null
diff --git a/dubbo-admin-frontend/src/components/metrics/ServiceMetrics.vue b/dubbo-admin-frontend/src/components/metrics/ServiceMetrics.vue
index 373d1cf..204083a 100644
--- a/dubbo-admin-frontend/src/components/metrics/ServiceMetrics.vue
+++ b/dubbo-admin-frontend/src/components/metrics/ServiceMetrics.vue
@@ -16,14 +16,19 @@
   -->
 
 <template>
-  <v-container grid-list-xl fluid>
-    <v-layout row wrap>
-      <v-flex lg12>
-        <v-card>
-          <v-card-title>
-            <h1>Service Metrics will release in the future</h1>
-          </v-card-title>
-        </v-card>
+  <v-container
+    fill-height
+  >
+    <v-layout align-center>
+      <v-flex text-xs-center>
+        <h1 class="display-2 primary--text">{{$t('later.metrics')}}</h1>
+        <v-btn
+          href="#/service"
+          color="primary"
+          outline
+        >
+          {{$t('goIndex')}}
+        </v-btn>
       </v-flex>
     </v-layout>
   </v-container>
diff --git a/dubbo-admin-frontend/src/components/public/Drawer.vue b/dubbo-admin-frontend/src/components/public/Drawer.vue
index 9f9cb8e..7f92ed8 100644
--- a/dubbo-admin-frontend/src/components/public/Drawer.vue
+++ b/dubbo-admin-frontend/src/components/public/Drawer.vue
@@ -36,14 +36,14 @@
         <v-list-group v-if="item.items" :group="item.group" :prepend-icon="item.icon" no-action>
           <v-list-tile slot="activator" ripple>
             <v-list-tile-content>
-              <v-list-tile-title>{{ item.title }}</v-list-tile-title>
+              <v-list-tile-title>{{ $t(item.title) }}</v-list-tile-title>
             </v-list-tile-content>
           </v-list-tile>
 
           <template v-for="(subItem, i) in item.items">
             <v-list-tile :to="subItem.path" ripple>
               <v-list-tile-content>
-                <v-list-tile-title>{{ subItem.title }}</v-list-tile-title>
+                <v-list-tile-title>{{ $t(subItem.title) }}</v-list-tile-title>
               </v-list-tile-content>
               <v-chip v-if="subItem.badge" color="primary" class="v-chip--x-small" disabled text-color="white">
                 {{subItem.badge}}
@@ -56,7 +56,7 @@
           <v-list-tile-action>
             <v-icon>{{ item.icon }}</v-icon>
           </v-list-tile-action>
-          <v-list-tile-content>{{ item.title }}</v-list-tile-content>
+          <v-list-tile-content>{{ $t(item.title) }}</v-list-tile-content>
           <v-chip v-if="item.badge" color="primary" class="v-chip--x-small" disabled text-color="white">
             {{item.badge}}
           </v-chip>
diff --git a/dubbo-admin-frontend/src/components/public/Search.vue b/dubbo-admin-frontend/src/components/public/Search.vue
index db03c8c..6ace1e9 100644
--- a/dubbo-admin-frontend/src/components/public/Search.vue
+++ b/dubbo-admin-frontend/src/components/public/Search.vue
@@ -23,7 +23,7 @@
           :label="label" clearable
           v-bind:value="value"
           v-on:input="$emit('input', $event)"></v-text-field>
-        <v-btn @click="submit" color="primary" large>Search</v-btn>
+        <v-btn @click="submit" color="primary" large>{{$t('search')}}</v-btn>
       </v-layout>
     </v-card-text>
   </v-card>
diff --git a/dubbo-admin-frontend/src/components/public/Toolbar.vue b/dubbo-admin-frontend/src/components/public/Toolbar.vue
index b32c37a..edb9143 100644
--- a/dubbo-admin-frontend/src/components/public/Toolbar.vue
+++ b/dubbo-admin-frontend/src/components/public/Toolbar.vue
@@ -28,18 +28,38 @@
       hide-details
       solo-inverted
       prepend-inner-icon="search"
-      label="Search"
+      :label="$t('search')"
       class="hidden-sm-and-down"
     >
     </v-text-field>
 
     <v-spacer></v-spacer>
+
+    <!--settings button-->
     <v-btn icon v-if="false">
       <v-icon>settings</v-icon>
     </v-btn>
+
+    <!--full screen button-->
     <v-btn icon @click="handleFullScreen()">
       <v-icon>fullscreen</v-icon>
     </v-btn>
+
+    <!--language select button-->
+    <v-menu  attach bottom left offset-y max-height="500">
+      <v-btn flat slot="activator" style="mini-width: 48px">
+        {{selectedLang}}
+      </v-btn>
+      <v-list class="pa-0">
+        <v-list-tile v-for="(item, index) in lang" @click="change(index)" :key="index">
+          <v-list-tile-content>
+            <v-list-tile-title>{{item}}</v-list-tile-title>
+          </v-list-tile-content>
+        </v-list-tile>
+      </v-list>
+    </v-menu>
+
+    <!--notifictation button-->
     <v-menu offset-y origin="center center" class="elelvation-1" :nudge-bottom="14" transition="scale-transition" v-if="false">
       <v-btn icon flat slot="activator">
         <v-badge color="red" overlap>
@@ -49,6 +69,8 @@
       </v-btn>
       <!--<notification-list></notification-list>-->
     </v-menu>
+
+    <!--login user info-->
     <v-menu offset-y origin="center center" :nudge-bottom="10" transition="scale-transition" v-if="false">
       <v-btn icon large flat slot="activator">
         <v-avatar size="30px">
@@ -73,6 +95,11 @@
   export default {
     name: 'toolbar',
     data: () => ({
+      selectedLang: '',
+      lang: [
+        '简体中文',
+        'English'
+      ],
       items: [
         {
           icon: 'account_circle',
@@ -104,12 +131,30 @@
       handleDrawerToggle () {
         window.getApp.$emit('DRAWER_TOGGLED')
       },
+      change (index) {
+        this.selectedLang = this.lang[index]
+        if (index === 0) {
+          this.$i18n.locale = 'zh'
+        } else {
+          this.$i18n.locale = 'en'
+        }
+        this.$store.dispatch('changeArea', {area: this.$i18n.locale})
+        window.localStorage.setItem('locale', this.$i18n.locale)
+        window.localStorage.setItem('selectedLang', this.selectedLang)
+      },
       handleTheme () {
         window.getApp.$emit('CHANGE_THEME')
       },
       handleFullScreen () {
         Util.toggleFullScreen()
       }
+    },
+    mounted: function () {
+      if (this.$i18n.locale === 'zh') {
+        this.selectedLang = '简体中文'
+      } else {
+        this.selectedLang = 'English'
+      }
     }
   }
 </script>
diff --git a/dubbo-admin-frontend/src/components/test/ServiceMock.vue b/dubbo-admin-frontend/src/components/test/ServiceMock.vue
index 7fd9a76..cf3c2fd 100644
--- a/dubbo-admin-frontend/src/components/test/ServiceMock.vue
+++ b/dubbo-admin-frontend/src/components/test/ServiceMock.vue
@@ -16,14 +16,19 @@
   -->
 
 <template>
-  <v-container grid-list-xl fluid>
-    <v-layout row wrap>
-      <v-flex lg12>
-        <v-card>
-          <v-card-title>
-            <h1>Service Mock will release in the future</h1>
-          </v-card-title>
-        </v-card>
+  <v-container
+    fill-height
+  >
+    <v-layout align-center>
+      <v-flex text-xs-center>
+        <h1 class="display-2 primary--text">{{$t('later.serviceMock')}}</h1>
+        <v-btn
+          href="#/service"
+          color="primary"
+          outline
+        >
+          {{$t('goIndex')}}
+        </v-btn>
       </v-flex>
     </v-layout>
   </v-container>
diff --git a/dubbo-admin-frontend/src/lang/en.js b/dubbo-admin-frontend/src/lang/en.js
new file mode 100644
index 0000000..0dd6d94
--- /dev/null
+++ b/dubbo-admin-frontend/src/lang/en.js
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+export default {
+  serviceSearch: 'Service Search',
+  serviceGovernance: 'Service Governance',
+  routingRule: 'Condition Rule',
+  tagRule: 'Tag Rule',
+  dynamicConfig: 'Dynamic Config',
+  accessControl: 'Black White List',
+  weightAdjust: 'Weight Adjust',
+  loadBalance: 'Load Balance',
+  serviceTest: 'Service Test',
+  serviceMock: 'Service Mock',
+  metrics: 'Metrics',
+  group: 'Group',
+  serviceInfo: 'Service Info',
+  providers: 'Providers',
+  consumers: 'Consumers',
+  version: 'Version',
+  app: 'Application',
+  ip: 'IP',
+  port: 'PORT',
+  timeout: 'timeout(ms)',
+  serialization: 'serialization',
+  appName: 'Application Name',
+  serviceName: 'Service Name',
+  operation: 'Operation',
+  searchResult: 'Search Result',
+  search: 'Search',
+  methodName: 'Method Name',
+  enabled: 'Enabled',
+  disabled: 'Disabled',
+  method: 'Method',
+  weight: 'Weight',
+  create: 'CREATE',
+  save: 'SAVE',
+  cancel: 'CANCEL',
+  close: 'CLOSE',
+  confirm: 'CONFIRM',
+  ruleContent: 'RULE CONTENT',
+  createNewRoutingRule: 'Create New Routing Rule',
+  createNewTagRule: 'Create New Tag Rule',
+  createNewDynamicConfigRule: 'Create New Dynamic Config Rule',
+  createNewWeightRule: 'Create New Weight Rule',
+  serviceIdHint: 'Service ID',
+  view: 'View',
+  edit: 'Edit',
+  delete: 'Delete',
+  searchRoutingRule: 'Search Routing Rule',
+  searchWeightRule: 'Search Weight Adjust Rule',
+  dataIdHint: 'A service ID in form of group/service:version, group and version are optional',
+  agree: 'Agree',
+  disagree: 'Disagree',
+  searchDynamicConfig: 'Search Dynamic Config',
+  appNameHint: 'Application name the service belongs to',
+  basicInfo: 'BasicInfo',
+  metaData: 'MetaData',
+  searchDubboService: 'Search Dubbo Services',
+  serviceSearchHint: 'Service ID, org.apache.dubbo.demo.api.DemoService, * for all services',
+  ipSearchHint: 'Find all services provided by the target server on the specified IP address',
+  appSearchHint: 'Input an application name to find all services provided by one particular application, * for all',
+  searchTagRule: 'Search Tag Rule by application name',
+  searchBalanceRule: 'Search Balancing Rule',
+  noMetadataHint: 'There is no metadata available, please update to Dubbo2.7, or check your config center configuration in application.properties, please check ',
+  parameterList: 'parameterList',
+  returnType: 'returnType',
+  here: 'here',
+  configAddress: 'https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin-configuration',
+  whiteList: 'White List',
+  whiteListHint: 'White list IP address, divided by comma: 1.1.1.1,2.2.2.2',
+  blackList: 'Black List',
+  blackListHint: 'Black list IP address, divided by comma: 3.3.3.3,4.4.4.4',
+  address: 'Address',
+  weightAddressHint: 'IP addresses to set this weight, divided by comma: 1.1.1.1,2.2.2.2',
+  weightHint: 'weight value, default is 100',
+  methodHint: 'choose method of load balancing, * for all methods',
+  strategy: 'Strategy',
+  balanceStrategyHint: 'load balancing strategy',
+  goIndex: 'Go To Index',
+  releaseLater: 'will release later',
+  later: {
+    metrics: 'Metrics will release later',
+    serviceTest: 'Service Test will release later',
+    serviceMock: 'Service Mock will release later'
+  }
+}
diff --git a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java b/dubbo-admin-frontend/src/lang/index.js
similarity index 62%
copy from dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
copy to dubbo-admin-frontend/src/lang/index.js
index 5b5e802..f043c56 100644
--- a/dubbo-admin-backend/src/main/java/org/apache/dubbo/admin/data/metadata/MetaDataCollector.java
+++ b/dubbo-admin-frontend/src/lang/index.js
@@ -14,23 +14,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+import Vue from 'vue'
+import VueI18n from 'vue-i18n'
+import enLocale from './en'
+import zhLocale from './zh'
 
-package org.apache.dubbo.admin.data.metadata;
+Vue.use(VueI18n)
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.SPI;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-
-@SPI("zookeeper")
-public interface MetaDataCollector {
-
-    void setUrl(URL url);
-
-    URL getUrl();
-
-    void init();
-
-    String getProviderMetaData(MetadataIdentifier key);
-
-    String getConsumerMetaData(MetadataIdentifier key);
+const messages = {
+  en: {
+    ...enLocale
+  },
+  zh: {
+    ...zhLocale
+  }
 }
+
+let locale = window.localStorage.getItem('locale')
+let selectedLang = window.localStorage.getItem('selectedLang')
+
+export default new VueI18n({
+  locale: locale === null ? 'zh' : locale,
+  selectedLang: selectedLang === null ? '简体中文' : selectedLang,
+  messages
+})
diff --git a/dubbo-admin-frontend/src/lang/zh.js b/dubbo-admin-frontend/src/lang/zh.js
new file mode 100644
index 0000000..85186ee
--- /dev/null
+++ b/dubbo-admin-frontend/src/lang/zh.js
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+export default {
+  serviceSearch: '服务查询',
+  serviceGovernance: '服务治理',
+  routingRule: '条件路由',
+  tagRule: '标签路由',
+  dynamicConfig: '动态配置',
+  accessControl: '黑白名单',
+  weightAdjust: '权重调整',
+  loadBalance: '负载均衡',
+  serviceTest: '服务测试',
+  serviceMock: '服务Mock',
+  providers: '提供者',
+  consumers: '消费者',
+  metrics: '统计',
+  group: '组',
+  version: '版本',
+  app: '应用',
+  ip: 'IP地址',
+  serviceInfo: '服务信息',
+  port: '端口',
+  timeout: '超时(毫秒)',
+  serialization: '序列化',
+  appName: '应用名',
+  serviceName: '服务名',
+  operation: '操作',
+  searchResult: '查询结果',
+  search: '搜索',
+  methodName: '方法名',
+  enabled: '开启',
+  disabled: '禁用',
+  method: '方法',
+  weight: '权重',
+  create: '创建',
+  save: '保存',
+  cancel: '取消',
+  close: '关闭',
+  confirm: '确认',
+  ruleContent: '规则内容',
+  createNewRoutingRule: '创建新路由规则',
+  createNewTagRule: '创建新标签规则',
+  createNewDynamicConfigRule: '创建新动态配置规则',
+  createNewWeightRule: '新建权重规则',
+  serviceIdHint: '服务名',
+  view: '查看',
+  edit: '编辑',
+  delete: '删除',
+  searchRoutingRule: '搜索路由规则',
+  searchWeightRule: '搜索权重调整规则',
+  dataIdHint: '组/服务:版本形式的服务ID,组和版本可选',
+  agree: '同意',
+  disagree: '不同意',
+  searchDynamicConfig: '搜索动态配置',
+  appNameHint: '服务所属的应用名称',
+  basicInfo: '基础信息',
+  metaData: '元数据',
+  searchDubboService: '搜索Dubbo服务',
+  serviceSearchHint: '服务ID, org.apache.dubbo.demo.api.DemoService, * 代表所有服务',
+  ipSearchHint: '在指定的IP地址上查找目标服务器提供的所有服务',
+  appSearchHint: '输入应用名称以查找由一个特定应用提供的所有服务, * 代表所有',
+  searchTagRule: '根据应用名搜索标签规则',
+  searchBalanceRule: '搜索负载均衡规则',
+  parameterList: '参数列表',
+  returnType: '返回值',
+  noMetadataHint: '无元数据信息,请升级至Dubbo2.7及以上版本,或者查看application.properties中关于config center的配置,详见',
+  here: '这里',
+  configAddress: 'https://github.com/apache/incubator-dubbo-ops/wiki/Dubbo-Admin%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E',
+  whiteList: '白名单',
+  whiteListHint: '白名单IP列表, 多个地址用逗号分隔: 1.1.1.1,2.2.2.2',
+  blackList: '黑名单',
+  blackListHint: '黑名单IP列表, 多个地址用逗号分隔: 3.3.3.3,4.4.4.4',
+  address: '地址列表',
+  weightAddressHint: '此权重设置的IP地址,用逗号分隔: 1.1.1.1,2.2.2.2',
+  weightHint: '权重值,默认100',
+  methodHint: '负载均衡生效的方法,*代表所有方法',
+  strategy: '策略',
+  balanceStrategyHint: '负载均衡策略',
+  goIndex: '返回首页',
+  releaseLater: '在后续版本中发布,敬请期待',
+  later: {
+    metrics: 'Metrics会在后续版本中发布,敬请期待',
+    serviceTest: '服务测试会在后续版本中发布,敬请期待',
+    serviceMock: '服务Mock会在后续版本中发布,敬请期待'
+  }
+}
diff --git a/dubbo-admin-frontend/src/main.js b/dubbo-admin-frontend/src/main.js
index 4eeb96d..f323034 100644
--- a/dubbo-admin-frontend/src/main.js
+++ b/dubbo-admin-frontend/src/main.js
@@ -25,9 +25,11 @@
 import { store } from './store'
 import Notify from './components/public/notify'
 import { AXIOS } from './components/http-common'
+import i18n from './lang'
 
 Vue.use(Vuetify)
 Vue.use(Notify)
+
 Vue.prototype.$axios = AXIOS
 
 Vue.config.productionTip = false
@@ -37,6 +39,7 @@
   el: '#app',
   router,
   store,
+  i18n,
   components: { App },
   template: '<App/>'
 })
diff --git a/dubbo-admin-frontend/src/store/index.js b/dubbo-admin-frontend/src/store/index.js
index ffbd5fd..a631f4d 100644
--- a/dubbo-admin-frontend/src/store/index.js
+++ b/dubbo-admin-frontend/src/store/index.js
@@ -22,9 +22,18 @@
 
 export const store = new Vuex.Store({
   state: {
-    appTitle: 'Dubbo OPS'
+    appTitle: 'Dubbo OPS',
+    area: null
   },
-  mutations: {},
-  actions: {},
+  mutations: {
+    setArea (state, area) {
+      state.area = area
+    }
+  },
+  actions: {
+    changeArea ({commit}, area) {
+      commit('setArea', area)
+    }
+  },
   getters: {}
 })