最近由于电脑死机,导致项目重启时一直失败,后来发现是从Xxl配置中心读取配置文件时出错了。顺便看了看项目启动时如何读取配置文件的,话不多说,直接上图。
1.首先在客户端要引入 XxlConfFactory 进行信息配置
一.初始化XxlConfFactory的init()方法
当 XxlConfFactory 被实例化时,会执行到 afterPropertiesSet 方法
Let me see see init() 方法里面有什么
又有三个 init() 方法和一个监听
① XxlConfRemoteConf.init(adminAddress, env, accessToken);
可以看到,仅仅是组装了下数据。
② XxlConfMirrorConf.init(mirrorfile);
可以看到给静态参数赋上了值,没有会抛异常
③ XxlConfLocalCacheConf.init();
public class XxlConfLocalCacheConf {
private static Logger logger = LoggerFactory.getLogger(XxlConfClient.class);
private static ConcurrentHashMap<String, XxlConfLocalCacheConf.CacheNode>
localCacheRepository = null;
private static Thread refreshThread;
private static boolean refreshThreadStop = false;
public XxlConfLocalCacheConf() {
}
public static void init() {
localCacheRepository = new ConcurrentHashMap();
Map<String, String> preConfData = new HashMap();
Map<String, String> mirrorConfData = XxlConfMirrorConf.readConfMirror();
Map<String, String> remoteConfData = null;
if (mirrorConfData != null && mirrorConfData.size() > 0) {
remoteConfData = XxlConfRemoteConf.find(mirrorConfData.keySet());
}
if (mirrorConfData != null && mirrorConfData.size() > 0) {
preConfData.putAll(mirrorConfData);
}
if (remoteConfData != null && remoteConfData.size() > 0) {
preConfData.putAll(remoteConfData);
}
if (preConfData != null && preConfData.size() > 0) {
Iterator var3 = preConfData.keySet().iterator();
while(var3.hasNext()) {
String preKey = (String)var3.next();
set(preKey, (String)preConfData.get(preKey), XxlConfLocalCacheConf.SET_TYPE.PRELOAD);
}
}
// 定时刷新从远程拉取配置文件
refreshThread = new Thread(new Runnable() {
public void run() {
while(!XxlConfLocalCacheConf.refreshThreadStop) {
try {
XxlConfLocalCacheConf.refreshCacheAndMirror();
} catch (Exception var2) {
if (!XxlConfLocalCacheConf.refreshThreadStop && !(var2 instanceof InterruptedException)) {
XxlConfLocalCacheConf.logger.error(">>>>>>>>>> xxl-conf, refresh thread error.");
XxlConfLocalCacheConf.logger.error(var2.getMessage(), var2);
}
}
}
XxlConfLocalCacheConf.logger.info(">>>>>>>>>> xxl-conf, refresh thread stoped.");
}
});
refreshThread.setDaemon(true);
refreshThread.start();
logger.info(">>>>>>>>>> xxl-conf, XxlConfLocalCacheConf init success.");
}
public static void destroy() {
...
}
private static void refreshCacheAndMirror() throws InterruptedException {
if (localCacheRepository.size() == 0) {
TimeUnit.SECONDS.sleep(3L);
} else {
boolean monitorRet = XxlConfRemoteConf.monitor(localCacheRepository.keySet());
if (!monitorRet) {
TimeUnit.SECONDS.sleep(10L);
}
Set<String> keySet = localCacheRepository.keySet();
Iterator var3;
String remoteKey;
if (keySet.size() > 0) {
Map<String, String> remoteDataMap = XxlConfRemoteConf.find(keySet);
if (remoteDataMap != null && remoteDataMap.size() > 0) {
var3 = remoteDataMap.keySet().iterator();
label43:
while(true) {
while(true) {
if (!var3.hasNext()) {
break label43;
}
remoteKey = (String)var3.next();
String remoteData = (String)remoteDataMap.get(remoteKey);
XxlConfLocalCacheConf.CacheNode existNode = (XxlConfLocalCacheConf.CacheNode)localCacheRepository.get(remoteKey);
if (existNode != null && existNode.getValue() != null && existNode.getValue().equals(remoteData)) {
logger.debug(">>>>>>>>>> xxl-conf: RELOAD unchange-pass [{}].", remoteKey);
} else {
set(remoteKey, remoteData, XxlConfLocalCacheConf.SET_TYPE.RELOAD);
}
}
}
}
}
Map<String, String> mirrorConfData = new HashMap();
var3 = keySet.iterator();
while(var3.hasNext()) {
remoteKey = (String)var3.next();
XxlConfLocalCacheConf.CacheNode existNode = (XxlConfLocalCacheConf.CacheNode)localCacheRepository.get(remoteKey);
mirrorConfData.put(remoteKey, existNode.getValue() != null ? existNode.getValue() : "");
}
XxlConfMirrorConf.writeConfMirror(mirrorConfData);
logger.debug(">>>>>>>>>> xxl-conf, refreshCacheAndMirror success.");
}
}
private static void set(String key, String value, XxlConfLocalCacheConf.SET_TYPE optType) {
...
}
private static XxlConfLocalCacheConf.CacheNode get(String key) {
...
}
public static String get(String key, String defaultVal) {
...
}
public static enum SET_TYPE {
SET,
RELOAD,
PRELOAD;
private SET_TYPE() {
}
}
public static class CacheNode implements Serializable {
private static final long serialVersionUID = 42L;
private String value;
public CacheNode() {
}
public CacheNode(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
public void setValue(String value) {
this.value = value;
}
}
}
可以看到里面有个获取镜像配置数据的方法 XxlConfMirrorConf.readConfMirror();用来获取配置信息,之后将获取的数据放到静态参数。而去还有个线程 refreshThread 该线程的目的就是获取远程仓库的配置文件。
public static boolean monitor(Set<String> keys) {
Iterator var1 = adminAddressArr.iterator();
if (var1.hasNext()) {
String adminAddressUrl = (String)var1.next();
String url = adminAddressUrl + "/conf/monitor";
XxlConfParamVO paramVO = new XxlConfParamVO();
paramVO.setAccessToken(accessToken);
paramVO.setEnv(env);
paramVO.setKeys(new ArrayList(keys));
String paramsJson = BasicJson.toJson(paramVO);
Map<String, Object> respObj = getAndValid(url, paramsJson, 60);
return respObj != null;
} else {
return false;
}
}
我们再看XxlConfMirrorConf.readConfMirror()方法
public static Map<String, String> readConfMirror() {
// 加载配置文件
Properties mirrorProp = PropUtil.loadFileProp(mirrorfile);
if (mirrorProp != null && mirrorProp.stringPropertyNames() != null && mirrorProp.stringPropertyNames().size() > 0) {
Map<String, String> mirrorConfData = new HashMap();
Iterator var2 = mirrorProp.stringPropertyNames().iterator();
while(var2.hasNext()) {
String key = (String)var2.next();
mirrorConfData.put(key, mirrorProp.getProperty(key));
}
return mirrorConfData;
} else {
return null;
}
}
// loadFileProp 方法
public static Properties loadFileProp(String propertyFileName) {
FileInputStream in = null;
Properties prop;
try {
File file = new File(propertyFileName);
URL url;
if (!file.exists()) {
url = null;
return url;
}
url = (new File(propertyFileName)).toURI().toURL();
in = new FileInputStream(url.getPath());
if (in != null) {
prop = new Properties();
prop.load(new InputStreamReader(in, "utf-8"));
Properties var5 = prop;
return var5;
}
prop = null;
} catch (IOException var17) {
logger.error(var17.getMessage(), var17);
return null;
} finally {
if (in != null) {
try {
in.close();
} catch (IOException var16) {
logger.error(var16.getMessage(), var16);
}
}
}
return prop;
}
mirrorfile 参数时实例化 XxlConfFactory 时所给的配置信息。读取文件存入Map中并返回。
④ XxlConfListenerFactory.addListener();
public static boolean addListener(String key, XxlConfListener xxlConfListener) {
if (xxlConfListener == null) {
return false;
} else if (key != null && key.trim().length() != 0) {
try {
String value = XxlConfClient.get(key);
xxlConfListener.onChange(key, value);
} catch (Exception var3) {
logger.error(var3.getMessage(), var3);
}
List<XxlConfListener> listeners = (List)keyListenerRepository.get(key);
if (listeners == null) {
listeners = new ArrayList();
keyListenerRepository.put(key, listeners);
}
((List)listeners).add(xxlConfListener);
return true;
} else {
noKeyConfListener.add(xxlConfListener);
return true;
}
}