經過consul的官網查看consul對外提供的RESTAPI,找到獲取consul中全部配置文件的名稱接口;找到根據配置文件名稱獲取配置文件內容的接口;html
經過mongoTemplate操做MongoDB數據庫;每次配置文件修改後保存的時候在mongo表裏新增一條數據;spring
mongo數據庫裏存儲當前版本的hash值,若是新版本的hash值和當前版本的hash值一致就放棄本次保存操做,視爲配置沒有改動,保留原來版本;數據庫
新版本插入以前獲取當前版本編號,若是當前沒有版本則插入到第一個版本;若是當前有版本和當前版本號小於20則插入到當前最大版本+1的版本;若是當前版本=20在則刪除第1個版本,以後每一個版本遞減1,新版本插入到第20版本;app
5consul
配置:
consul可視化界面修改配置後點擊保存時調用本身的rest接口ide
{
"watches":[
{
"type":"keyprefix",
"prefix":"config/",
"token":"p2BE1AtpwPbrxZdC6k+eXA",
"handler_type":"http",
"http_handler_config":{
"path":" http://127.0.0.1/consul/config/"
}
}
]
}
廢話很少說,先上代碼url
2. @Autowired
private RestTemplate restTemplate;
@Override
public String readConsul(String url, String ymlName, String token) {
try {
String reqJsonStr;
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("text/html; charset=UTF-8");
headers.setContentType(type);
headers.set("X-Consul-Token", token);
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<String> exchange = restTemplate.exchange(new URI(url + ymlName), HttpMethod.GET, entity, String.class);
String result = exchange.getBody();
List<RestGetResultDo> conList = JSON.parseArray(result, RestGetResultDo.class);
return conList.get(0).getValue();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
4. @Override
public List<String> getConsulConfigYmlNameList(String url, String token) {
RestTemplate restTemplate2 = new RestTemplate();
try {
String reqJsonStr;
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("text/html; charset=UTF-8");
headers.setContentType(type);
headers.set("X-Consul-Token", token);
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<String> exchange = restTemplate.exchange(new URI(url), HttpMethod.GET, entity, String.class);
String result = exchange.getBody();
result = result.replaceAll("\r|\n| |\\[|\\]|\\\"", "");
String[] split = result.split(",");
return Arrays.asList(split);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static final String VERSION_NUMBER = "versionNumber";
public static final int MAX_VERSION = 20;
@Autowired
private ConsulConfigManage consulConfigManage;
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private ConsulProperties consulProperties;
@Value("${spring.cloud.consul.token}")
private String consulToken;
/**
* consul配置持久化到MongoDB的實現類
*
* @return
*/
@Override
public Boolean consulToMongoDB() {
int versionNumber = 1;
int oldFirstDocumentHash = 1;
int newDocumentHash = 1;
boolean isSync = false;
try {
ConsulConfigDo configDo = new ConsulConfigDo();
//獲取到全部配置文件的名稱
List<String> consulConfigYmlNameList = consulConfigManage.getConsulConfigYmlNameList("http://" + consulProperties.getHost() + ":" + consulProperties.getPort() + "/v1/kv/" + "?keys", consulToken);
//把每一個配置文件的name和content放到map中
Map map = new HashMap();
for (String ymlName : consulConfigYmlNameList) {
String ymlContent = consulConfigManage.readConsul("http://" + consulProperties.getHost() + ":" + consulProperties.getPort() + "/v1/kv/", ymlName, consulToken);
ymlName = ymlName.contains(".") ? ymlName = ymlName.substring(0, ymlName.indexOf(".")) : ymlName;
map.put(ymlName, ymlContent);
}
//查詢MongoDB中最近添加的一個版本
List<ConsulConfigDo> consulConfigDos = mongoTemplate.find(new Query().with(new Sort(new Sort.Order(Sort.Direction.DESC, "_id"))), ConsulConfigDo.class);
ConsulConfigDo first = null;
//初始版本
if (consulConfigDos.size() == 0) {
configDo.set_id(System.currentTimeMillis());
configDo.setConsul_content(map);
configDo.setVersionNumber(String.format("%02d", versionNumber));
configDo.setHash(hash(configDo.getConsul_content()));
mongoTemplate.insert(configDo);
isSync = true;
} else {
first = consulConfigDos.get(0);
//最近添加的一個版本hash
oldFirstDocumentHash = first.getHash();
configDo.setConsul_content(map);
newDocumentHash = hash(configDo.getConsul_content());
if (newDocumentHash == oldFirstDocumentHash) {
//不一樣步
return isSync;
} else {
//同步
String versionNumber1 = first.getVersionNumber();
Integer integer = Integer.valueOf(versionNumber1);
//若是數據小於20
if (integer < MAX_VERSION) {
versionNumber = integer + 1;
} else {
//刪掉第一條數據
mongoTemplate.remove(new Query(Criteria.where(VERSION_NUMBER).is("01")), ConsulConfigDo.class);
//每條數據的versionNumber遞減1
List<ConsulConfigDo> documents = mongoTemplate.find(new Query().with(new Sort(new Sort.Order(Sort.Direction.ASC, "_id"))), ConsulConfigDo.class);
for (ConsulConfigDo document : documents) {
Integer versionNum = Integer.valueOf(document.getVersionNumber());
String format = String.format("%02d", versionNum -= 1);
mongoTemplate.updateFirst(new Query(Criteria.where(VERSION_NUMBER).is(document.getVersionNumber())), Update.update(VERSION_NUMBER, format), ConsulConfigDo.class);
}
versionNumber = 20;
}
//插入到第20個版本
configDo.setVersionNumber(String.format("%02d", versionNumber));
configDo.setHash(hash(configDo.getConsul_content()));
configDo.set_id(System.currentTimeMillis());
mongoTemplate.insert(configDo);
isSync = true;
}
}
return isSync;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 計算hash值
*
* @param key
* @return
*/
private int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
@Data
public class RestGetResultDo implements Serializable {
private int LockIndex;
private String Key;
private int Flags;
private String Value;
private int CreateIndex;
private int ModifyIndex;
}
@Validated
@Data
@ToString
@Document(collection = "app_yml_config")
public class ConsulConfigDo {
private Long _id;
private Map consul_content;
private String versionNumber;
private int hash; }