package org.xforth.config.manager; import org.apache.curator.RetryPolicy; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFrameworkFactory; import org.apache.curator.retry.ExponentialBackoffRetry; import org.apache.zookeeper.CreateMode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.io.*; import java.util.*; @Component public class RemoteConfigManager implements IRemoteConfigManager{ private static final Logger logger = LoggerFactory.getLogger(RemoteConfigManager.class); private static final String DEFAULT_NAMESPACE = "/config-center"; private static final String DEFAULT_DECODE = "utf-8"; private CuratorFramework zkClient; private String zkConnectString; public RemoteConfigManager(){ } @PostConstruct public void init(){ RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3); zkClient = CuratorFrameworkFactory.newClient(zkConnectString, retryPolicy); zkClient.start(); } /** * init by properties file * @param schema * @param file * @throws Exception :if schema exists,throw RuntimeException */ @Override public void initByProperties(String schema,File file) throws Exception { String servicePath = generateServicePath(schema); checkServiceConfigExists(servicePath); initServicePath(servicePath); Properties prop = new Properties(); InputStream input = null; try { input = new FileInputStream(file); prop.load(input); } catch (IOException e) { logger.error("importProperties load properties exception:{}",e); } Enumeration enums = prop.keys(); while (enums.hasMoreElements()) { Object key = enums.nextElement(); prop.get(key); importRemoteConfig(servicePath, key.toString(), prop.get(key).toString()); } } private void checkServiceConfigExists(String servicePath){ try { if(zkClient.checkExists().forPath(servicePath)!=null){ throw new RuntimeException("this service config have been inited for servicePath:"+servicePath); } } catch (Exception e) { logger.error("checkServiceConfigExists exception:{}",e); } } private void initServicePath(String servicePath){ try { if(zkClient.checkExists().forPath(DEFAULT_NAMESPACE)==null){ zkClient.create().withMode(CreateMode.PERSISTENT).forPath(DEFAULT_NAMESPACE); } if(zkClient.checkExists().forPath(servicePath)==null){ zkClient.create().withMode(CreateMode.PERSISTENT).forPath(servicePath); } } catch (Exception e) { logger.error("checkServiceConfigExists exception:{}",e); } } private void importRemoteConfig(String servicePath,String key,String value) throws Exception { final String keyPath = servicePath.concat("/").concat(key); if(zkClient.checkExists().forPath(keyPath)==null){ zkClient.create().withMode(CreateMode.PERSISTENT).forPath(servicePath+"/"+key,value.getBytes(DEFAULT_DECODE)); }else{ throw new RuntimeException("this service config have been inited for keyPath:"+keyPath); } } private String generateServicePath(String schema){ return DEFAULT_NAMESPACE.concat("/").concat(schema); } private String generateKeyPath(String schema,String key){ return generateServicePath(schema).concat("/").concat(key); } @Override public void update(String schema, String key, String value) throws Exception { final String keyPath = generateKeyPath(schema,key); zkClient.setData().forPath(keyPath, value.getBytes(DEFAULT_DECODE)); } @Override public void delete(String schema, String key, String value) throws Exception { final String keyPath = generateKeyPath(schema,key); zkClient.delete().forPath(keyPath); } @Override public Map<String,String> exportProperties(String schema) throws Exception { final String servicePath = generateServicePath(schema); HashMap<String,String> propertyMap = new HashMap<String, String>(); if(zkClient.checkExists().forPath(servicePath)==null) { List<String> keyPathList = zkClient.getChildren().forPath(servicePath); if(keyPathList!=null){ for(String keyPath:keyPathList){ byte[] data = zkClient.getData().forPath(keyPath); String key = keyPath.replaceAll(".*//", ""); propertyMap.put(key,new String(data,DEFAULT_DECODE)); } } } return propertyMap; } public String getZkConnectString() { return zkConnectString; } @Value("${zookeeper.host:}") public void setZkConnectString(String zkConnectString) { this.zkConnectString = zkConnectString; } }