Application.xml废弃<resources>节点

This commit is contained in:
Redkale
2022-12-09 21:54:51 +08:00
parent 8a630ff007
commit 8c20ba96f6
10 changed files with 833 additions and 478 deletions

View File

@@ -3,49 +3,48 @@ redkale.nodeid = 1000
redkale.port = 6560 redkale.port = 6560
redkale.lib = ./ redkale.lib = ./
#\u3010resources\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011
#\u3010executor\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011 #\u3010executor\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011
redkale.resources.executor.threads = 4 redkale.executor.threads = 4
redkale.resources.executor.hash = false redkale.executor.hash = false
#\u3010transport\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011 #\u3010transport\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011
redkale.resources.transport.bufferCapacity = 32k redkale.transport.bufferCapacity = 32k
redkale.resources.transport.bufferPoolSize = 32 redkale.transport.bufferPoolSize = 32
#\u3010excludelibs\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011 #\u3010excludelibs\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011
redkale.resources.excludelibs.value = ^.*mysql.*$;^.*kafka.*$ redkale.excludelibs.value = ^.*mysql.*$;^.*kafka.*$
#\u3010cluster\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011 #\u3010cluster\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011
redkale.resources.cluster.type = org.redkalex.cluster.consul.ConsulClusterAgent redkale.cluster.type = org.redkalex.cluster.consul.ConsulClusterAgent
redkale.resources.cluster.waits= = false redkale.cluster.waits= = false
redkale.resources.cluster.protocols = SNCP redkale.cluster.protocols = SNCP
redkale.resources.cluster.ports = 7070;7071 redkale.cluster.ports = 7070;7071
redkale.resources.mq[0].name = redkale.mq[0].name =
redkale.resources.mq[0].type = org.redkalex.mq.kafka.KafkaMessageAgent redkale.mq[0].type = org.redkalex.mq.kafka.KafkaMessageAgent
redkale.resources.mq[0].servers.value = 127.0.0.1:9101 redkale.mq[0].servers.value = 127.0.0.1:9101
redkale.resources.group[0].name = redkale.group[0].name =
redkale.resources.group[0].protocol = TCP redkale.group[0].protocol = TCP
redkale.resources.group[0].node[0].addr = 127.0.0.1 redkale.group[0].node[0].addr = 127.0.0.1
redkale.resources.group[0].node[0].port = 7070 redkale.group[0].node[0].port = 7070
#\u3010listener\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011 redkale.listener[0].value = org.redkalex.xxx.XXXApplicationListener
redkale.resources.listener.value = org.redkalex.xxx.XXXApplicationListener
#\u3010properties\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011 #\u3010properties\u8282\u70b9\u5168\u5c40\u552f\u4e00\u3011
redkale.resources.properties.load = config.properties redkale.properties.load = config.properties
redkale.resources.properties.property[0].name = system.property.yyyy redkale.properties.property[0].name = system.property.yyyy
redkale.resources.properties.property[0].value = YYYYYY redkale.properties.property[0].value = YYYYYY
redkale.resources.properties.property[1].name = xxxxxxx redkale.properties.property[1].name = xxxxxxx
redkale.resources.properties.property[1].value = YYYYYY redkale.properties.property[1].value = YYYYYY
redkale.server[0].protocol = HTTP redkale.server[0].protocol = HTTP
redkale.server[0].host = 127.0.0.1 redkale.server[0].host = 127.0.0.1
redkale.server[0].port = 6060 redkale.server[0].port = 6060
redkale.server[0].root = root redkale.server[0].root = root
redkale.server[0].lib = redkale.server[0].lib =
#\u3010\u8282\u70b9\u5728<server>\u4e2d\u552f\u4e00\u3011
#\u3010ssl\u8282\u70b9\u5728<server>\u4e2d\u552f\u4e00\u3011
redkale.server[0].ssl.build = org.redkale.net.SSLBuilder\u5b50\u7c7b redkale.server[0].ssl.build = org.redkale.net.SSLBuilder\u5b50\u7c7b
redkale.server[0].services[0].autoload = true redkale.server[0].services[0].autoload = true

View File

@@ -28,10 +28,11 @@
<application nodeid="1000" port="6560" lib=""> <application nodeid="1000" port="6560" lib="">
<!-- <!--
【节点全局唯一 已废弃,不再需要此节点】
所有服务所需的资源 所有服务所需的资源
--> -->
<resources> <resources>
</resources>
<!-- <!--
【节点全局唯一】 @since 2.3.0 【节点全局唯一】 @since 2.3.0
@@ -145,7 +146,6 @@
<property name="xxxxxx" value="XXXXXXXX"/> <property name="xxxxxx" value="XXXXXXXX"/>
</properties> </properties>
</resources>
<!-- <!--
protocol: required server所启动的协议Redkale内置的有HTTP、SNCP、WATCH。协议均使用TCP实现; WATCH服务只能存在一个。 protocol: required server所启动的协议Redkale内置的有HTTP、SNCP、WATCH。协议均使用TCP实现; WATCH服务只能存在一个。
name: 服务的名称用于监控识别一个配置文件中的server.name不能重复,命名规则: 字母、数字、下划线 name: 服务的名称用于监控识别一个配置文件中的server.name不能重复,命名规则: 字母、数字、下划线
@@ -366,4 +366,5 @@
<!-- 参数完全同上 --> <!-- 参数完全同上 -->
<services autoload="true" includes="" excludes="" /> <services autoload="true" includes="" excludes="" />
</server> </server>
</application> </application>

View File

@@ -82,11 +82,6 @@ public final class Application {
*/ */
public static final String RESNAME_APP_CONF_FILE = "APP_CONF_FILE"; public static final String RESNAME_APP_CONF_FILE = "APP_CONF_FILE";
/**
* application.xml 文件中resources节点的内容 类型: AnyValue
*/
public static final String RESNAME_APP_GRES = "APP_GRES";
/** /**
* 当前进程节点的nodeid 类型int * 当前进程节点的nodeid 类型int
*/ */
@@ -152,9 +147,6 @@ public final class Application {
//Source 原始的配置资源, 只会存在redkale.datasource(.|[) redkale.cachesource(.|[)开头的配置项 //Source 原始的配置资源, 只会存在redkale.datasource(.|[) redkale.cachesource(.|[)开头的配置项
final Properties sourceProperties = new Properties(); final Properties sourceProperties = new Properties();
//sourceProperties对应的AnyValue类型对象
AnyValue sourceConfig;
//CacheSource 资源 //CacheSource 资源
final List<CacheSource> cacheSources = new CopyOnWriteArrayList<>(); final List<CacheSource> cacheSources = new CopyOnWriteArrayList<>();
@@ -261,7 +253,7 @@ public final class Application {
this.resourceFactory.register(RESNAME_APP_HOME, File.class, root); this.resourceFactory.register(RESNAME_APP_HOME, File.class, root);
this.resourceFactory.register(RESNAME_APP_HOME, URI.class, root.toURI()); this.resourceFactory.register(RESNAME_APP_HOME, URI.class, root.toURI());
File confFile = null; File confFile = null;
try { try { //设置APP_HOME
this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath()); this.resourceFactory.register(RESNAME_APP_HOME, root.getCanonicalPath());
if (System.getProperty(RESNAME_APP_HOME) == null) { if (System.getProperty(RESNAME_APP_HOME) == null) {
System.setProperty(RESNAME_APP_HOME, root.getCanonicalPath()); System.setProperty(RESNAME_APP_HOME, root.getCanonicalPath());
@@ -415,7 +407,6 @@ public final class Application {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
//------------------------------------ 配置 <transport> 节点 ------------------------------------ //------------------------------------ 配置 <transport> 节点 ------------------------------------
final AnyValue resources = config.getAnyValue("resources");
TransportStrategy strategy = null; TransportStrategy strategy = null;
String excludelib0 = null; String excludelib0 = null;
ClusterAgent cluster = null; ClusterAgent cluster = null;
@@ -425,12 +416,11 @@ public final class Application {
int readTimeoutSeconds = TransportFactory.DEFAULT_READTIMEOUTSECONDS; int readTimeoutSeconds = TransportFactory.DEFAULT_READTIMEOUTSECONDS;
int writeTimeoutSeconds = TransportFactory.DEFAULT_WRITETIMEOUTSECONDS; int writeTimeoutSeconds = TransportFactory.DEFAULT_WRITETIMEOUTSECONDS;
AnyValue executorConf = null; AnyValue executorConf = null;
if (resources != null) { executorConf = config.getAnyValue("executor");
executorConf = resources.getAnyValue("executor"); AnyValue excludelibConf = config.getAnyValue("excludelibs");
AnyValue excludelibConf = resources.getAnyValue("excludelibs");
if (excludelibConf != null) excludelib0 = excludelibConf.getValue("value"); if (excludelibConf != null) excludelib0 = excludelibConf.getValue("value");
AnyValue transportConf = resources.getAnyValue("transport"); AnyValue transportConf = config.getAnyValue("transport");
int groupsize = resources.getAnyValues("group").length; int groupsize = config.getAnyValues("group").length;
if (groupsize > 0 && transportConf == null) transportConf = new DefaultAnyValue(); if (groupsize > 0 && transportConf == null) transportConf = new DefaultAnyValue();
if (transportConf != null) { if (transportConf != null) {
//--------------transportBufferPool----------- //--------------transportBufferPool-----------
@@ -441,7 +431,7 @@ public final class Application {
bufferPoolSize = parseLenth(transportConf.getValue("bufferPoolSize"), threads * 4); bufferPoolSize = parseLenth(transportConf.getValue("bufferPoolSize"), threads * 4);
} }
AnyValue clusterConf = resources.getAnyValue("cluster"); AnyValue clusterConf = config.getAnyValue("cluster");
if (clusterConf != null) { if (clusterConf != null) {
try { try {
String classVal = clusterConf.getValue("type", clusterConf.getValue("value")); //兼容value字段 String classVal = clusterConf.getValue("type", clusterConf.getValue("value")); //兼容value字段
@@ -481,7 +471,7 @@ public final class Application {
} }
} }
AnyValue[] mqConfs = resources.getAnyValues("mq"); AnyValue[] mqConfs = config.getAnyValues("mq");
if (mqConfs != null && mqConfs.length > 0) { if (mqConfs != null && mqConfs.length > 0) {
mqs = new MessageAgent[mqConfs.length]; mqs = new MessageAgent[mqConfs.length];
Set<String> mqnames = new HashSet<>(); Set<String> mqnames = new HashSet<>();
@@ -529,7 +519,6 @@ public final class Application {
} }
} }
} }
}
ExecutorService workExecutor0 = null; ExecutorService workExecutor0 = null;
ExecutorService clientExecutor; ExecutorService clientExecutor;
@@ -591,7 +580,8 @@ public final class Application {
} }
private void loadResourceProperties() throws IOException { private void loadResourceProperties() throws IOException {
final String confDir = this.confPath.toString(); final Properties dyncProps = new Properties();
final AtomicInteger propertyIndex = new AtomicInteger();
//------------------------------------ 读取本地DataSource、CacheSource配置 ------------------------------------ //------------------------------------ 读取本地DataSource、CacheSource配置 ------------------------------------
if ("file".equals(this.confPath.getScheme())) { if ("file".equals(this.confPath.getScheme())) {
File sourceFile = new File(new File(confPath), "source.properties"); File sourceFile = new File(new File(confPath), "source.properties");
@@ -603,7 +593,9 @@ public final class Application {
props.forEach((key, val) -> { props.forEach((key, val) -> {
if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[") if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[")
|| key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) { || key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) {
sourceProperties.put(key, val); dyncProps.put(key, val);
} else {
logger.log(Level.WARNING, "skip illegal key " + key + " in source.properties");
} }
}); });
} else { } else {
@@ -612,13 +604,13 @@ public final class Application {
if (persist.isFile() && persist.canRead()) { if (persist.isFile() && persist.canRead()) {
logger.log(Level.WARNING, "persistence.xml is deprecated, replaced by source.properties"); logger.log(Level.WARNING, "persistence.xml is deprecated, replaced by source.properties");
InputStream in = new FileInputStream(persist); InputStream in = new FileInputStream(persist);
sourceProperties.putAll(DataSources.loadSourceProperties(in)); dyncProps.putAll(DataSources.loadSourceProperties(in));
in.close(); in.close();
} }
} }
} else { //从url或jar文件中resources读取 } else { //从url或jar文件中resources读取
try { try {
final URI sourceURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : confDir, "source.properties"); final URI sourceURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), "source.properties");
InputStream in = sourceURI.toURL().openStream(); InputStream in = sourceURI.toURL().openStream();
Properties props = new Properties(); Properties props = new Properties();
props.load(in); props.load(in);
@@ -626,16 +618,18 @@ public final class Application {
props.forEach((key, val) -> { props.forEach((key, val) -> {
if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[") if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[")
|| key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) { || key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) {
sourceProperties.put(key, val); dyncProps.put(key, val);
} else {
logger.log(Level.WARNING, "skip illegal key " + key + " in source.properties");
} }
}); });
} catch (Exception e) { //没有文件 跳过 } catch (Exception e) { //没有文件 跳过
} }
//兼容 persistence.xml 【已废弃】 //兼容 persistence.xml 【已废弃】
try { try {
final URI xmlURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : confDir, "persistence.xml"); final URI xmlURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), "persistence.xml");
InputStream in = xmlURI.toURL().openStream(); InputStream in = xmlURI.toURL().openStream();
sourceProperties.putAll(DataSources.loadSourceProperties(in)); dyncProps.putAll(DataSources.loadSourceProperties(in));
in.close(); in.close();
logger.log(Level.WARNING, "persistence.xml is deprecated, replaced by source.properties"); logger.log(Level.WARNING, "persistence.xml is deprecated, replaced by source.properties");
} catch (Exception e) { //没有文件 跳过 } catch (Exception e) { //没有文件 跳过
@@ -643,22 +637,20 @@ public final class Application {
} }
//------------------------------------ 读取配置项 ------------------------------------ //------------------------------------ 读取配置项 ------------------------------------
AnyValue propertiesConf = config.getAnyValue("properties");
if (propertiesConf == null) {
final AnyValue resources = config.getAnyValue("resources"); final AnyValue resources = config.getAnyValue("resources");
if (resources != null) { if (resources != null) {
resourceFactory.register(RESNAME_APP_GRES, AnyValue.class, resources); logger.log(Level.WARNING, "<resources> in application config file is deprecated");
final AnyValue propertiesConf = resources.getAnyValue("properties"); propertiesConf = resources.getAnyValue("properties");
if (propertiesConf != null) {
for (AnyValue prop : propertiesConf.getAnyValues("property")) {
String key = prop.getValue("name");
String value = prop.getValue("value");
if (key == null || value == null) continue;
updateEnvironmentProperty(key, value, null, null);
} }
String dfloads = propertiesConf.getValue("load"); }
if (dfloads != null) { if (propertiesConf != null) {
for (String dfload : dfloads.split(";")) { final Properties agentEnvs = new Properties();
if (propertiesConf.getValue("load") != null) { //本地配置项文件加载
for (String dfload : propertiesConf.getValue("load").split(";")) {
if (dfload.trim().isEmpty()) continue; if (dfload.trim().isEmpty()) continue;
final URI df = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : confDir, dfload.trim()); final URI df = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), dfload.trim());
if (df != null && (!"file".equals(df.getScheme()) || df.toString().contains("!") || new File(df).isFile())) { if (df != null && (!"file".equals(df.getScheme()) || df.toString().contains("!") || new File(df).isFile())) {
Properties ps = new Properties(); Properties ps = new Properties();
try { try {
@@ -667,7 +659,11 @@ public final class Application {
in.close(); in.close();
if (logger.isLoggable(Level.FINEST)) logger.log(Level.FINEST, "load properties(" + dfload + ") size = " + ps.size()); if (logger.isLoggable(Level.FINEST)) logger.log(Level.FINEST, "load properties(" + dfload + ") size = " + ps.size());
ps.forEach((x, y) -> { //load中的配置项除了redkale.cachesource.和redkale.datasource.开头不应该有其他redkale.开头配置项 ps.forEach((x, y) -> { //load中的配置项除了redkale.cachesource.和redkale.datasource.开头不应该有其他redkale.开头配置项
updateEnvironmentProperty(x.toString(), y, null, null); if (!x.toString().startsWith("redkale.") && !x.toString().startsWith("property.")) {
agentEnvs.put(x, y);
} else {
logger.log(Level.WARNING, "skip illegal(startswith redkale. or property.) key " + x + " in properties file");
}
}); });
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.WARNING, "load properties(" + dfload + ") error", e); logger.log(Level.WARNING, "load properties(" + dfload + ") error", e);
@@ -675,7 +671,6 @@ public final class Application {
} }
} }
} }
{ //可能通过系统环境变量配置信息 { //可能通过系统环境变量配置信息
Iterator<PropertiesAgentProvider> it = ServiceLoader.load(PropertiesAgentProvider.class, classLoader).iterator(); Iterator<PropertiesAgentProvider> it = ServiceLoader.load(PropertiesAgentProvider.class, classLoader).iterator();
RedkaleClassLoader.putServiceLoader(PropertiesAgentProvider.class); RedkaleClassLoader.putServiceLoader(PropertiesAgentProvider.class);
@@ -694,17 +689,113 @@ public final class Application {
if (compileMode) { if (compileMode) {
this.propertiesAgent.compile(propertiesConf); this.propertiesAgent.compile(propertiesConf);
} else { } else {
this.propertiesAgent.init(this, propertiesConf); Properties props = this.propertiesAgent.init(this, propertiesConf);
if (props != null) {
agentEnvs.putAll(props);
}
} }
logger.info("PropertiesAgent (type = " + this.propertiesAgent.getClass().getSimpleName() + ") init in " + (System.currentTimeMillis() - s) + " ms"); logger.info("PropertiesAgent (type = " + this.propertiesAgent.getClass().getSimpleName() + ") init in " + (System.currentTimeMillis() - s) + " ms");
break; break;
} }
} }
final Properties oldEnvs = new Properties();
for (AnyValue prop : propertiesConf.getAnyValues("property")) {
String key = prop.getValue("name");
String value = prop.getValue("value");
if (key == null || value == null) continue;
if (key.startsWith("property.")) {
logger.log(Level.WARNING, "property key (" + key + ") startswith 'property.' is illegal, auto remove the prefix 'property.'");
key = key.substring("property.".length());
}
oldEnvs.put(key, value);
}
agentEnvs.forEach((k, v) -> {
if (k.toString().startsWith("redkale.")) {
dyncProps.put(k, v);
} else if (k.toString().startsWith("property.")) {
logger.log(Level.WARNING, "skip illegal(startswith property.) key " + k + " in remote properties agent");
} else {
oldEnvs.put(k, v); //新配置项会覆盖旧的
}
});
//原有properties节点上的属性同步到dyncEnvs
propertiesConf.forEach((k, v) -> dyncProps.put("redkale.properties." + k, v));
oldEnvs.forEach((k, v) -> { //去重后的配置项
String prefix = "redkale.properties.property[" + propertyIndex.getAndIncrement() + "]";
dyncProps.put(prefix + ".name", k);
dyncProps.put(prefix + ".value", v);
});
//移除旧节点
((DefaultAnyValue) this.config).removeAnyValues("properties");
}
//环境变量的优先级最高
System.getProperties().forEach((k, v) -> {
if (k.toString().startsWith("redkale.executor.") //节点全局唯一
|| k.toString().startsWith("redkale.transport.") //节点全局唯一
|| k.toString().startsWith("redkale.excludelibs.") //节点全局唯一
|| k.toString().startsWith("redkale.cluster.") //节点全局唯一
|| k.toString().startsWith("redkale.mq.")
|| k.toString().startsWith("redkale.mq[")
|| k.toString().startsWith("redkale.group.")
|| k.toString().startsWith("redkale.group[")
|| k.toString().startsWith("redkale.listener.")
|| k.toString().startsWith("redkale.listener[")
|| k.toString().startsWith("redkale.server.")
|| k.toString().startsWith("redkale.server[")) {
dyncProps.put(k, v);
} else if (k.toString().startsWith("redkale.properties.")) {
if (k.toString().startsWith("redkale.properties.property.")
|| k.toString().startsWith("redkale.properties.property[")) {
dyncProps.put(k, v);
} else {
//支持系统变量 -Dredkale.properties.mykey=my-value
String prefix = "redkale.properties.property[" + propertyIndex.getAndIncrement() + "]";
dyncProps.put(prefix + ".name", k.toString().substring("redkale.properties.".length()));
dyncProps.put(prefix + ".value", v);
}
}
});
if (!dyncProps.isEmpty()) {
//合并配置
this.config.merge(AnyValue.loadFromProperties(dyncProps).getAnyValue("redkale"), NodeServer.appConfigmergeFunction);
dyncProps.forEach((key, val) -> {
if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[")
|| key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) {
if (key.toString().endsWith(".name")) {
logger.log(Level.WARNING, "skip illegal key " + key + " in source config, key cannot endsWith '.name'");
} else {
sourceProperties.put(key, val);
}
}
});
}
//使用合并后的新配置节点
propertiesConf = this.config.getAnyValue("properties");
if (propertiesConf != null) {
//清除property节点数组的下坐标
((DefaultAnyValue) propertiesConf).clearParentArrayIndex("property");
//注入配置项
for (AnyValue prop : propertiesConf.getAnyValues("property")) {
String key = prop.getValue("name");
String value = prop.getValue("value");
if (key == null) continue;
value = value == null ? value : replaceValue(value);
if (key.startsWith("system.property.")) {
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
System.setProperty(propName, value);
}
} else if (key.startsWith("mimetype.property.")) {
MimeType.add(key.substring("mimetype.property.".length()), value);
} else if (key.startsWith("property.")) {
envProperties.put(key, value);
resourceFactory.register(key, value);
} else {
envProperties.put(key, value);
resourceFactory.register(false, "property." + key, value);
} }
final AnyValue[] sourceConfs = resources.getAnyValues("source");
if (sourceConfs != null && sourceConfs.length > 0) {
//<source>节点 【已废弃】
throw new RuntimeException("<source> in application.xml is deprecated, replaced by source.properties");
} }
} }
} }
@@ -981,16 +1072,7 @@ public final class Application {
} }
private AnyValue findSourceConfig(String sourceName, String sourceType) { private AnyValue findSourceConfig(String sourceName, String sourceType) {
if (sourceConfig == null) { AnyValue sourceNode = config.getAnyValue(sourceType);
synchronized ((sourceProperties)) {
if (sourceConfig == null) {
sourceConfig = AnyValue.loadFromProperties(sourceProperties);
}
}
}
AnyValue redNode = sourceConfig.getAnyValue("redkale");
if (redNode != null) {
AnyValue sourceNode = redNode.getAnyValue(sourceType);
if (sourceNode != null) { if (sourceNode != null) {
AnyValue confNode = sourceNode.getAnyValue(sourceName); AnyValue confNode = sourceNode.getAnyValue(sourceName);
if (confNode != null) { //必须要设置name属性 if (confNode != null) { //必须要设置name属性
@@ -998,7 +1080,6 @@ public final class Application {
} }
return confNode; return confNode;
} }
}
return null; return null;
} }
@@ -1126,11 +1207,8 @@ public final class Application {
} }
private void initResources() throws Exception { private void initResources() throws Exception {
//-------------------------------------------------------------------------
final AnyValue resources = config.getAnyValue("resources");
if (resources != null) {
//------------------------------------------------------------------------ //------------------------------------------------------------------------
for (AnyValue conf : resources.getAnyValues("group")) { for (AnyValue conf : config.getAnyValues("group")) {
final String group = conf.getValue("name", ""); final String group = conf.getValue("name", "");
final String protocol = conf.getValue("protocol", Transport.DEFAULT_NETPROTOCOL).toUpperCase(); final String protocol = conf.getValue("protocol", Transport.DEFAULT_NETPROTOCOL).toUpperCase();
if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) { if (!"TCP".equalsIgnoreCase(protocol) && !"UDP".equalsIgnoreCase(protocol)) {
@@ -1143,7 +1221,7 @@ public final class Application {
} }
sncpTransportFactory.addGroupInfo(ginfo); sncpTransportFactory.addGroupInfo(ginfo);
} }
for (AnyValue conf : resources.getAnyValues("listener")) { for (AnyValue conf : config.getAnyValues("listener")) {
final String listenClass = conf.getValue("value", ""); final String listenClass = conf.getValue("value", "");
if (listenClass.isEmpty()) continue; if (listenClass.isEmpty()) continue;
Class clazz = classLoader.loadClass(listenClass); Class clazz = classLoader.loadClass(listenClass);
@@ -1155,7 +1233,6 @@ public final class Application {
listener.init(config); listener.init(config);
this.listeners.add(listener); this.listeners.add(listener);
} }
}
//------------------------------------------------------------------------ //------------------------------------------------------------------------
} }
@@ -1633,7 +1710,12 @@ public final class Application {
} }
System.setProperty(RESNAME_APP_CONF_DIR, confDir); System.setProperty(RESNAME_APP_CONF_DIR, confDir);
String text = Utility.readThenClose(appConfFile.toURL().openStream()); String text = Utility.readThenClose(appConfFile.toURL().openStream());
AnyValue conf = text.trim().startsWith("<") ? AnyValue.loadFromXml(text, (k, v) -> v.replace("${APP_HOME}", home)).getAnyValue("application") : AnyValue.loadFromProperties(text).getAnyValue("redkale"); AnyValue conf;
if (text.trim().startsWith("<")) {
conf = AnyValue.loadFromXml(text, (k, v) -> v.replace("${APP_HOME}", home)).getAnyValue("application");
} else {
conf = AnyValue.loadFromProperties(text).getAnyValue("redkale");
}
if (fromCache) ((DefaultAnyValue) conf).addValue("[config-from-cache]", "true"); if (fromCache) ((DefaultAnyValue) conf).addValue("[config-from-cache]", "true");
return conf; return conf;
} }
@@ -1712,84 +1794,101 @@ public final class Application {
return value == null ? value : value.replace("${APP_HOME}", homePath).replace("${APP_NAME}", name); return value == null ? value : value.replace("${APP_HOME}", homePath).replace("${APP_NAME}", name);
} }
//初始化加载时envChangeCache=null void updateEnvironmentProperties(List<ResourceEvent> events) {
//配置项动态变更时 envChangeCache!=null, 由调用方统一执行ResourceFactory.register(envChangeCache) if (events == null || events.isEmpty()) return;
//key只会是system.property.、mimetype.property.、redkale.cachesource(.|[)、redkale.datasource(.|[)和其他非redkale.开头的配置项 synchronized (envProperties) {
void updateEnvironmentProperty(String key, Object value, Properties envChangeCache, Properties sourceChangeCache) { Properties envRegisterProps = new Properties();
if (key == null || value == null) return; Set<String> envRemovedKeys = new HashSet<>();
String val = replaceValue(value.toString()).trim(); Properties envChangedProps = new Properties();
if (key.startsWith("redkale.datasource.") || key.startsWith("redkale.datasource[")
|| key.startsWith("redkale.cachesource.") || key.startsWith("redkale.cachesource[")) { Set<String> sourceRemovedKeys = new HashSet<>();
if (!Objects.equals(val, sourceProperties.getProperty(key))) { Properties sourceChangedProps = new Properties();
if (sourceChangeCache == null) { for (ResourceEvent<String> event : events) {
sourceProperties.put(key, val); if (event.name().startsWith("redkale.datasource.") || event.name().startsWith("redkale.datasource[")
|| event.name().startsWith("redkale.cachesource.") || event.name().startsWith("redkale.cachesource[")) {
if (event.name().endsWith(".name")) {
logger.log(Level.WARNING, "skip illegal key " + event.name() + " in source config, key cannot endsWith '.name'");
} else { } else {
sourceChangeCache.put(key, val); if (!Objects.equals(event.newValue(), sourceProperties.getProperty(event.name()))) {
} if (event.newValue() == null) {
} if (sourceProperties.containsKey(event.name())) {
} else if (key.startsWith("system.property.")) { sourceRemovedKeys.add(event.name());
String propName = key.substring("system.property.".length());
if (envChangeCache != null || System.getProperty(propName) == null) { //命令行传参数优先级高
System.setProperty(propName, val);
}
} else if (key.startsWith("mimetype.property.")) {
MimeType.add(key.substring("mimetype.property.".length()), val);
} else if (key.startsWith("property.")) {
Object old = resourceFactory.find(key, String.class);
if (!Objects.equals(val, old)) {
envProperties.put(key, val);
if (envChangeCache == null) {
resourceFactory.register(key, val);
} else {
envChangeCache.put(key, val);
}
} }
} else { } else {
if (key.startsWith("redkale.")) { sourceChangedProps.put(event.name(), event.newValue());
throw new RuntimeException("property " + key + " cannot redkale. startsWith");
} }
String newkey = "property." + key; }
Object old = resourceFactory.find(newkey, String.class); }
if (!Objects.equals(val, old)) { } else if (event.name().startsWith("system.property.")) {
envProperties.put(key, val); String propName = event.name().substring("system.property.".length());
if (envChangeCache == null) { if (event.newValue() == null) {
resourceFactory.register(newkey, val); System.getProperties().remove(propName);
} else { } else {
envChangeCache.put(newkey, val); System.setProperty(propName, event.newValue());
}
} else if (event.name().startsWith("mimetype.property.")) {
String propName = event.name().substring("system.property.".length());
if (event.newValue() != null) {
MimeType.add(propName, event.newValue());
}
} else if (event.name().startsWith("property.")) {
if (!Objects.equals(event.newValue(), envProperties.getProperty(event.name()))) {
envRegisterProps.put(event.name(), event.newValue());
if (event.newValue() == null) {
if (envProperties.containsKey(event.name())) {
envRemovedKeys.add(event.name());
}
} else {
envChangedProps.put(event.name(), event.newValue());
}
}
} else if (event.name().startsWith("redkale.")) {
logger.log(Level.WARNING, "not support the env property key " + event.name() + " on change event");
} else {
if (!Objects.equals(event.newValue(), envProperties.getProperty(event.name()))) {
envRegisterProps.put("property." + event.name(), event.newValue());
if (event.newValue() == null) {
if (envProperties.containsKey(event.name())) {
envRemovedKeys.add(event.name());
}
} else {
envChangedProps.put(event.name(), event.newValue());
} }
} }
} }
} }
void updateSourceProperties(Properties sourceChangeCache) { //普通配置项的变更
if (sourceChangeCache == null || sourceChangeCache.isEmpty()) return; if (!envRegisterProps.isEmpty()) {
synchronized (sourceProperties) { envProperties.putAll(envChangedProps);
Properties changedProps = new Properties(); envRemovedKeys.forEach(k -> envProperties.remove(k));
for (Map.Entry<Object, Object> en : sourceChangeCache.entrySet()) { resourceFactory.register(envRegisterProps, "", Environment.class);
String key = en.getKey().toString(); }
if (key.startsWith("redkale.datasource.") || key.startsWith("redkale.datasource[") //数据源配置项的变更
|| key.startsWith("redkale.cachesource.") || key.startsWith("redkale.cachesource[")) { if (!sourceChangedProps.isEmpty() || !sourceRemovedKeys.isEmpty()) {
if (!Objects.equals(en.getValue(), sourceProperties.get(key))) { Set<String> cacheSourceNames = new LinkedHashSet<>();
changedProps.put(en.getKey(), en.getValue()); Set<String> dataSourceNames = new LinkedHashSet<>();
if (key.endsWith(".name")) { //不更改source.name属性 List<String> keys = new ArrayList<>();
throw new RuntimeException("source properties contains illegal key: " + key); keys.addAll(sourceRemovedKeys);
keys.addAll((Set) sourceChangedProps.keySet());
for (final String key : keys) {
if (key.startsWith("redkale.cachesource[")) {
cacheSourceNames.add(key.substring("redkale.cachesource[".length(), key.indexOf(']')));
} else if (key.startsWith("redkale.cachesource.")) {
cacheSourceNames.add(key.substring("redkale.cachesource.".length(), key.indexOf('.', "redkale.cachesource.".length())));
} else if (key.startsWith("redkale.datasource[")) {
dataSourceNames.add(key.substring("redkale.datasource[".length(), key.indexOf(']')));
} else if (key.startsWith("redkale.datasource.")) {
dataSourceNames.add(key.substring("redkale.datasource.".length(), key.indexOf('.', "redkale.datasource.".length())));
} }
} }
} else { //更新缓存
throw new RuntimeException("source properties contains illegal key: " + key); for (String sourceName : cacheSourceNames) {
}
}
if (changedProps.isEmpty()) return; //无内容改变
AnyValue newRedNode = AnyValue.loadFromProperties(changedProps).getAnyValue("redkale");
AnyValue newCacheNode = newRedNode.getAnyValue("cachesource");
if (newCacheNode != null) {
newCacheNode.forEach(null, (sourceName, newConf) -> {
CacheSource source = Utility.find(cacheSources, s -> Objects.equals(s.resourceName(), sourceName)); CacheSource source = Utility.find(cacheSources, s -> Objects.equals(s.resourceName(), sourceName));
if (source == null) return; //多余的数据源 if (source == null) return; //多余的数据源
DefaultAnyValue old = (DefaultAnyValue) findSourceConfig(sourceName, "cachesource"); final DefaultAnyValue old = (DefaultAnyValue) findSourceConfig(sourceName, "cachesource");
old.merge(newConf); Properties newProps = new Properties();
List<ResourceEvent> events = new ArrayList<>(); sourceProperties.forEach((k, v) -> {
changedProps.forEach((k, v) -> {
final String key = k.toString(); final String key = k.toString();
String prefix = "redkale.cachesource[" + sourceName + "]."; String prefix = "redkale.cachesource[" + sourceName + "].";
int pos = key.indexOf(prefix); int pos = key.indexOf(prefix);
@@ -1797,21 +1896,52 @@ public final class Application {
prefix = "redkale.cachesource." + sourceName + "."; prefix = "redkale.cachesource." + sourceName + ".";
pos = key.indexOf(prefix); pos = key.indexOf(prefix);
} }
if (pos < 0) return; if (pos < 0) return; //不是同一name数据源配置项
events.add(ResourceEvent.create(key.substring(prefix.length()), v, sourceProperties.get(key))); newProps.put(k, v);
});
((AbstractCacheSource) source).onResourceChange(events.toArray(new ResourceEvent[events.size()]));
}); });
List<ResourceEvent> changeEvents = new ArrayList<>();
sourceChangedProps.forEach((k, v) -> {
final String key = k.toString();
String prefix = "redkale.cachesource[" + sourceName + "].";
int pos = key.indexOf(prefix);
if (pos < 0) {
prefix = "redkale.cachesource." + sourceName + ".";
pos = key.indexOf(prefix);
} }
AnyValue newSourceNode = newRedNode.getAnyValue("datasource"); if (pos < 0) return; //不是同一name数据源配置项
if (newSourceNode != null) { newProps.put(k, v);
newSourceNode.forEach(null, (sourceName, newConf) -> { changeEvents.add(ResourceEvent.create(key.substring(prefix.length()), v, sourceProperties.getProperty(key)));
});
sourceRemovedKeys.forEach(k -> {
final String key = k;
String prefix = "redkale.cachesource[" + sourceName + "].";
int pos = key.indexOf(prefix);
if (pos < 0) {
prefix = "redkale.cachesource." + sourceName + ".";
pos = key.indexOf(prefix);
}
if (pos < 0) return;
newProps.remove(k); //不是同一name数据源配置项
changeEvents.add(ResourceEvent.create(key.substring(prefix.length()), null, sourceProperties.getProperty(key)));
});
if (!changeEvents.isEmpty()) {
DefaultAnyValue back = old.copy();
old.replace(AnyValue.loadFromProperties(newProps).getAnyValue("redkale").getAnyValue("cachesource").getAnyValue(sourceName));
try {
((AbstractCacheSource) source).onResourceChange(changeEvents.toArray(new ResourceEvent[changeEvents.size()]));
} catch (RuntimeException e) {
old.replace(back); //还原配置
throw e;
}
}
}
//更新数据库
for (String sourceName : dataSourceNames) {
DataSource source = Utility.find(dataSources, s -> Objects.equals(s.resourceName(), sourceName)); DataSource source = Utility.find(dataSources, s -> Objects.equals(s.resourceName(), sourceName));
if (source == null) return; //多余的数据源 if (source == null) return; //多余的数据源
DefaultAnyValue old = (DefaultAnyValue) findSourceConfig(sourceName, "datasource"); DefaultAnyValue old = (DefaultAnyValue) findSourceConfig(sourceName, "datasource");
old.merge(newConf); Properties newProps = new Properties();
List<ResourceEvent> events = new ArrayList<>(); sourceProperties.forEach((k, v) -> {
changedProps.forEach((k, v) -> {
final String key = k.toString(); final String key = k.toString();
String prefix = "redkale.datasource[" + sourceName + "]."; String prefix = "redkale.datasource[" + sourceName + "].";
int pos = key.indexOf(prefix); int pos = key.indexOf(prefix);
@@ -1819,13 +1949,48 @@ public final class Application {
prefix = "redkale.datasource." + sourceName + "."; prefix = "redkale.datasource." + sourceName + ".";
pos = key.indexOf(prefix); pos = key.indexOf(prefix);
} }
if (pos < 0) return; if (pos < 0) return; //不是同一name数据源配置项
events.add(ResourceEvent.create(key.substring(prefix.length()), v, sourceProperties.get(key))); newProps.put(k, v);
});
((AbstractDataSource) source).onResourceChange(events.toArray(new ResourceEvent[events.size()]));
}); });
List<ResourceEvent> changeEvents = new ArrayList<>();
sourceChangedProps.forEach((k, v) -> {
final String key = k.toString();
String prefix = "redkale.datasource[" + sourceName + "].";
int pos = key.indexOf(prefix);
if (pos < 0) {
prefix = "redkale.datasource." + sourceName + ".";
pos = key.indexOf(prefix);
}
if (pos < 0) return; //不是同一name数据源配置项
newProps.put(k, v);
changeEvents.add(ResourceEvent.create(key.substring(prefix.length()), v, sourceProperties.getProperty(key)));
});
sourceRemovedKeys.forEach(k -> {
final String key = k;
String prefix = "redkale.datasource[" + sourceName + "].";
int pos = key.indexOf(prefix);
if (pos < 0) {
prefix = "redkale.datasource." + sourceName + ".";
pos = key.indexOf(prefix);
}
if (pos < 0) return;
newProps.remove(k); //不是同一name数据源配置项
changeEvents.add(ResourceEvent.create(key.substring(prefix.length()), null, sourceProperties.getProperty(key)));
});
if (!changeEvents.isEmpty()) {
DefaultAnyValue back = old.copy();
old.replace(AnyValue.loadFromProperties(newProps).getAnyValue("redkale").getAnyValue("datasource").getAnyValue(sourceName));
try {
((AbstractDataSource) source).onResourceChange(changeEvents.toArray(new ResourceEvent[changeEvents.size()]));
} catch (RuntimeException e) {
old.replace(back); //还原配置
throw e;
}
}
}
sourceRemovedKeys.forEach(k -> sourceProperties.remove(k));
sourceProperties.putAll(sourceChangedProps);
} }
sourceProperties.putAll(changedProps);
} }
} }
@@ -1946,7 +2111,7 @@ public final class Application {
} }
if (this.propertiesAgent != null) { if (this.propertiesAgent != null) {
long s = System.currentTimeMillis(); long s = System.currentTimeMillis();
this.propertiesAgent.destroy(config.getAnyValue("resources").getAnyValue("properties")); this.propertiesAgent.destroy(config.getAnyValue("properties"));
logger.info(this.propertiesAgent.getClass().getSimpleName() + " destroy in " + (System.currentTimeMillis() - s) + " ms"); logger.info(this.propertiesAgent.getClass().getSimpleName() + " destroy in " + (System.currentTimeMillis() - s) + " ms");
} }
if (this.clientAsyncGroup != null) { if (this.clientAsyncGroup != null) {

View File

@@ -211,7 +211,6 @@ public abstract class NodeServer {
//--------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------
final ResourceFactory appResFactory = application.getResourceFactory(); final ResourceFactory appResFactory = application.getResourceFactory();
final TransportFactory appSncpTranFactory = application.getSncpTransportFactory(); final TransportFactory appSncpTranFactory = application.getSncpTransportFactory();
final AnyValue resources = application.config.getAnyValue("resources");
final String confURI = appResFactory.find(RESNAME_APP_CONF_DIR, String.class); final String confURI = appResFactory.find(RESNAME_APP_CONF_DIR, String.class);
//------------------------------------- 注册 Resource -------------------------------------------------------- //------------------------------------- 注册 Resource --------------------------------------------------------
resourceFactory.register((ResourceFactory rf, String srcResourceName, final Object srcObj, String resourceName, Field field, final Object attachment) -> { resourceFactory.register((ResourceFactory rf, String srcResourceName, final Object srcObj, String resourceName, Field field, final Object attachment) -> {
@@ -222,7 +221,7 @@ public abstract class NodeServer {
Class type = field.getType(); Class type = field.getType();
if (type != AnyValue.class && type != AnyValue[].class) return; if (type != AnyValue.class && type != AnyValue[].class) return;
Object resource = null; Object resource = null;
final AnyValue properties = resources == null ? null : resources.getAnyValue("properties"); final AnyValue properties = application.getAppConfig().getAnyValue("properties");
if (properties != null && type == AnyValue.class) { if (properties != null && type == AnyValue.class) {
resource = properties.getAnyValue(res.name().substring("properties.".length())); resource = properties.getAnyValue(res.name().substring("properties.".length()));
appResFactory.register(resourceName, AnyValue.class, resource); appResFactory.register(resourceName, AnyValue.class, resource);
@@ -780,4 +779,114 @@ public abstract class NodeServer {
public String getThreadName() { public String getThreadName() {
return this.threadName; return this.threadName;
} }
static final AnyValue.MergeFunction appConfigmergeFunction = (path, key, val1, val2) -> {
if ("".equals(path)) {
if ("executor".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("transport".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("excludelibs".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("cluster".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("listener".equals(key)) {
if (Objects.equals(val1.getValue("value"), val2.getValue("value"))) {
return AnyValue.MergeFunction.SKIP;
} else {
return AnyValue.MergeFunction.NONE;
}
}
if ("mq".equals(key)) {
if (Objects.equals(val1.getValue("name"), val2.getValue("name"))) {
return AnyValue.MergeFunction.REPLACE;
} else {
return AnyValue.MergeFunction.NONE;
}
}
if ("group".equals(key)) {
if (Objects.equals(val1.getValue("name"), val2.getValue("name"))) {
return AnyValue.MergeFunction.REPLACE;
} else {
return AnyValue.MergeFunction.NONE;
}
}
if ("server".equals(key)) {
if (Objects.equals(val1.getValue("name", val1.getValue("protocol") + "_" + val1.getValue("port")),
val2.getValue("name", val2.getValue("protocol") + "_" + val2.getValue("port")))) {
return AnyValue.MergeFunction.REPLACE;
} else {
return AnyValue.MergeFunction.NONE;
}
}
}
if ("cachesource".equals(path)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("datasource".equals(path)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("properties".equals(path)) {
if ("property".equals(key)) {
if (Objects.equals(val1.getValue("name"), val2.getValue("name"))) {
return AnyValue.MergeFunction.REPLACE;
} else {
return AnyValue.MergeFunction.NONE;
}
}
}
if ("server".equals(path)) {
if ("ssl".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("render".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("resource-servlet".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
}
if ("server.request".equals(path)) {
if ("remoteaddr".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("rpc".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("locale".equals(key)) {
if (Objects.equals(val1.getValue("name"), val2.getValue("name"))) {
return AnyValue.MergeFunction.REPLACE;
} else {
return AnyValue.MergeFunction.NONE;
}
}
}
if ("server.response".equals(path)) {
if ("content-type".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("defcookie".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("options".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("date".equals(key)) {
return AnyValue.MergeFunction.REPLACE;
}
if ("addheader".equals(key) || "setheader".equals(key)) {
if (Objects.equals(val1.getValue("name"), val2.getValue("name"))) {
return AnyValue.MergeFunction.REPLACE;
} else {
return AnyValue.MergeFunction.NONE;
}
}
}
return AnyValue.MergeFunction.MERGE;
};
} }

View File

@@ -2,7 +2,7 @@
*/ */
package org.redkale.boot; package org.redkale.boot;
import java.util.Properties; import java.util.*;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.redkale.util.*; import org.redkale.util.*;
@@ -44,8 +44,10 @@ public abstract class PropertiesAgent {
* *
* @param application Application * @param application Application
* @param conf 节点配置 * @param conf 节点配置
*
* @return 加载的配置项
*/ */
public abstract void init(Application application, AnyValue conf); public abstract Properties init(Application application, AnyValue conf);
/** /**
* 销毁动作 * 销毁动作
@@ -54,21 +56,18 @@ public abstract class PropertiesAgent {
*/ */
public abstract void destroy(AnyValue conf); public abstract void destroy(AnyValue conf);
protected void updateEnvironmentProperties(Application application, Properties props) { protected void updateEnvironmentProperties(Application application, List<ResourceEvent> events) {
if (props.isEmpty()) return; if (events == null || events.isEmpty()) return;
Properties envChangeCache = new Properties(); application.updateEnvironmentProperties(events);
Properties sourceChangeCache = new Properties(); // Properties envChangeCache = new Properties();
props.forEach((k, v) -> application.updateEnvironmentProperty(k.toString(), v.toString().trim(), envChangeCache, sourceChangeCache)); // Properties sourceChangeCache = new Properties();
if (!envChangeCache.isEmpty()) { // //props.forEach((k, v) -> application.updateEnvironmentProperty(k.toString(), v.toString().trim(), envChangeCache, sourceChangeCache));
application.resourceFactory.register(envChangeCache, "", Environment.class); // if (!envChangeCache.isEmpty()) {
} // application.resourceFactory.register(envChangeCache, "", Environment.class);
if (!sourceChangeCache.isEmpty()) { // }
application.updateSourceProperties(sourceChangeCache); // if (!sourceChangeCache.isEmpty()) {
} // application.updateSourceProperties(sourceChangeCache);
} // }
protected void putEnvironmentProperty(Application application, String key, Object value) {
application.updateEnvironmentProperty(key, value, null, null);
} }
protected void reconfigLogging(Application application, Properties loggingProperties) { protected void reconfigLogging(Application application, Properties loggingProperties) {

View File

@@ -75,7 +75,7 @@ public class TransportWatchService extends AbstractWatchService {
} }
} }
DefaultAnyValue node = DefaultAnyValue.create("addr", addr).addValue("port", port); DefaultAnyValue node = DefaultAnyValue.create("addr", addr).addValue("port", port);
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) { for (AnyValue groupconf : application.getAppConfig().getAnyValues("group")) {
if (group.equals(groupconf.getValue("name"))) { if (group.equals(groupconf.getValue("name"))) {
((DefaultAnyValue) groupconf).addValue("node", node); ((DefaultAnyValue) groupconf).addValue("node", node);
break; break;
@@ -107,7 +107,7 @@ public class TransportWatchService extends AbstractWatchService {
} }
} }
} }
for (AnyValue groupconf : application.getAppConfig().getAnyValue("resources").getAnyValues("group")) { for (AnyValue groupconf : application.getAppConfig().getAnyValues("group")) {
if (group.equals(groupconf.getValue("name"))) { if (group.equals(groupconf.getValue("name"))) {
((DefaultAnyValue) groupconf).removeValue("node", DefaultAnyValue.create("addr", addr).addValue("port", port)); ((DefaultAnyValue) groupconf).removeValue("node", DefaultAnyValue.create("addr", addr).addValue("port", port));
break; break;

View File

@@ -140,7 +140,8 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
if (readConfProps == writeConfProps) { if (readConfProps == writeConfProps) {
List<ResourceEvent> allEvents = new ArrayList<>(); List<ResourceEvent> allEvents = new ArrayList<>();
Properties newProps = new Properties(this.readConfProps); Properties newProps = new Properties();
newProps.putAll(this.readConfProps);
for (ResourceEvent event : events) { //可能需要解密 for (ResourceEvent event : events) { //可能需要解密
String newValue = decryptProperty(event.name(), event.newValue().toString()); String newValue = decryptProperty(event.name(), event.newValue().toString());
allEvents.add(ResourceEvent.create(event.name(), newValue, event.oldValue())); allEvents.add(ResourceEvent.create(event.name(), newValue, event.oldValue()));
@@ -154,8 +155,10 @@ public abstract class DataSqlSource extends AbstractDataSource implements Functi
} else { } else {
List<ResourceEvent> readEvents = new ArrayList<>(); List<ResourceEvent> readEvents = new ArrayList<>();
List<ResourceEvent> writeEvents = new ArrayList<>(); List<ResourceEvent> writeEvents = new ArrayList<>();
Properties newReadProps = new Properties(this.readConfProps); Properties newReadProps = new Properties();
Properties newWriteProps = new Properties(this.writeConfProps); newReadProps.putAll(this.readConfProps);
Properties newWriteProps = new Properties();
newWriteProps.putAll(this.writeConfProps);
for (ResourceEvent event : events) { for (ResourceEvent event : events) {
if (event.name().startsWith("read.")) { if (event.name().startsWith("read.")) {
String newName = event.name().substring("read.".length()); String newName = event.name().substring("read.".length());

View File

@@ -33,11 +33,15 @@ public abstract class AnyValue {
*/ */
public static interface MergeFunction { public static interface MergeFunction {
public static final int NONE = 0;
public static final int REPLACE = 1; public static final int REPLACE = 1;
public static final int MERGE = 2; public static final int MERGE = 2;
public int apply(String name, AnyValue val1, AnyValue val2); public static final int SKIP = 3;
public int apply(String path, String name, AnyValue val1, AnyValue val2);
} }
/** /**
@@ -158,6 +162,8 @@ public abstract class AnyValue {
@Override @Override
public DefaultAnyValue copy() { public DefaultAnyValue copy() {
DefaultAnyValue rs = new DefaultAnyValue(this.ignoreCase); DefaultAnyValue rs = new DefaultAnyValue(this.ignoreCase);
rs.predicate = this.predicate;
rs.parentArrayIndex = this.parentArrayIndex;
if (this.stringEntrys != null) { if (this.stringEntrys != null) {
rs.stringEntrys = new Entry[this.stringEntrys.length]; rs.stringEntrys = new Entry[this.stringEntrys.length];
for (int i = 0; i < rs.stringEntrys.length; i++) { for (int i = 0; i < rs.stringEntrys.length; i++) {
@@ -177,16 +183,40 @@ public abstract class AnyValue {
return rs; return rs;
} }
/**
* 将另一个对象替换本对象
*
* @param node 替换的对象
*
* @return AnyValue
*/
@Override
public DefaultAnyValue replace(AnyValue node) {
if (node != null) {
DefaultAnyValue rs = (DefaultAnyValue) node;
this.ignoreCase = rs.ignoreCase;
this.predicate = rs.predicate;
this.parentArrayIndex = rs.parentArrayIndex;
this.stringEntrys = rs.stringEntrys;
this.anyEntrys = rs.anyEntrys;
}
return this;
}
/** /**
* 将另一个对象合并过来 * 将另一个对象合并过来
* *
* @param node0 代合并对象 * @param node 代合并对象
* @param func 判断覆盖方式的函数 * @param func 判断覆盖方式的函数
* *
* @return AnyValue * @return AnyValue
*/ */
@Override @Override
public DefaultAnyValue merge(AnyValue node0, MergeFunction func) { public DefaultAnyValue merge(AnyValue node, MergeFunction func) {
return merge(node, "", func);
}
protected DefaultAnyValue merge(AnyValue node0, String path, MergeFunction func) {
if (node0 == null) return this; if (node0 == null) return this;
if (node0 == this) throw new IllegalArgumentException(); if (node0 == this) throw new IllegalArgumentException();
DefaultAnyValue node = (DefaultAnyValue) node0; DefaultAnyValue node = (DefaultAnyValue) node0;
@@ -212,15 +242,19 @@ public abstract class AnyValue {
ok = true; ok = true;
break; break;
} else { } else {
int funcVal = func.apply(en.name, en.value, item.value); int funcVal = func.apply(path, en.name, en.value, item.value);
if (funcVal == MergeFunction.MERGE) { if (funcVal == MergeFunction.MERGE) {
item.value.merge(en.value, func); String subPath = path.isEmpty() ? en.name : (path + "." + en.name);
((DefaultAnyValue) item.value).merge(en.value, subPath, func);
ok = true; ok = true;
break; break;
} else if (funcVal == MergeFunction.REPLACE) { } else if (funcVal == MergeFunction.REPLACE) {
item.value = en.value.copy(); item.value = en.value.copy();
ok = true; ok = true;
break; break;
} else if (funcVal == MergeFunction.SKIP) {
ok = true;
break;
} }
} }
} }
@@ -489,12 +523,32 @@ public abstract class AnyValue {
return this; return this;
} }
public void clearParentArrayIndex(String name) {
for (Entry<AnyValue> item : getAnyValueEntrys(name)) {
if (item.value != null) {
((DefaultAnyValue) item.value).parentArrayIndex = -1;
}
}
}
public DefaultAnyValue removeAnyValues(String name) {
if (name == null || this.anyEntrys == null) return this;
this.anyEntrys = Utility.remove(this.anyEntrys, (t) -> name.equals(((Entry) t).name));
return this;
}
public DefaultAnyValue removeValue(String name, AnyValue value) { public DefaultAnyValue removeValue(String name, AnyValue value) {
if (name == null || value == null || this.anyEntrys == null) return this; if (name == null || value == null || this.anyEntrys == null) return this;
this.anyEntrys = Utility.remove(this.anyEntrys, (t) -> name.equals(((Entry) t).name) && ((Entry) t).getValue().equals(value)); this.anyEntrys = Utility.remove(this.anyEntrys, (t) -> name.equals(((Entry) t).name) && ((Entry) t).getValue().equals(value));
return this; return this;
} }
public DefaultAnyValue removeStringValues(String name) {
if (name == null || this.stringEntrys == null) return this;
this.stringEntrys = Utility.remove(this.stringEntrys, (t) -> name.equals(((Entry) t).name));
return this;
}
public DefaultAnyValue removeValue(String name, String value) { public DefaultAnyValue removeValue(String name, String value) {
if (name == null || value == null || this.stringEntrys == null) return this; if (name == null || value == null || this.stringEntrys == null) return this;
this.stringEntrys = Utility.remove(this.stringEntrys, (t) -> name.equals(((Entry) t).name) && ((Entry) t).getValue().equals(value)); this.stringEntrys = Utility.remove(this.stringEntrys, (t) -> name.equals(((Entry) t).name) && ((Entry) t).getValue().equals(value));
@@ -794,7 +848,7 @@ public abstract class AnyValue {
} }
parent = child; parent = child;
} else { //数组或Map结构, []中间是数字开头的视为数组其他视为map } else { //数组或Map结构, []中间是数字开头的视为数组其他视为map
String itemField = item.substring(0, pos); //[前面一部分 String itemField = item.substring(0, pos); //[前面一部分'sources[1]'中'sources'
String keyOrIndex = item.substring(pos + 1, item.indexOf(']')); String keyOrIndex = item.substring(pos + 1, item.indexOf(']'));
int realIndex = -1; int realIndex = -1;
if (!keyOrIndex.isEmpty() && keyOrIndex.charAt(0) >= '0' && keyOrIndex.charAt(0) <= '9') { if (!keyOrIndex.isEmpty() && keyOrIndex.charAt(0) >= '0' && keyOrIndex.charAt(0) <= '9') {
@@ -808,7 +862,7 @@ public abstract class AnyValue {
for (int j = 0; j < i; j++) { for (int j = 0; j < i; j++) {
prefixKey += keys[j] + "."; prefixKey += keys[j] + ".";
} }
DefaultAnyValue array = prefixArray.get(prefixKey + item); DefaultAnyValue array = prefixArray.get(prefixKey + item); //item: [1]
if (array == null) { if (array == null) {
final int ii = i; final int ii = i;
String findkey = prefixKey + itemField + "["; String findkey = prefixKey + itemField + "[";
@@ -1034,21 +1088,19 @@ public abstract class AnyValue {
public abstract AnyValue copy(); public abstract AnyValue copy();
/** /**
* 将另一个对象合并过来 * 将另一个对象替换本对象
* *
* @param node 代合并对象 * @param node 替换的对象
* *
* @return AnyValue * @return AnyValue
*/ */
public AnyValue merge(AnyValue node) { public abstract AnyValue replace(AnyValue node);
return merge(node, null);
}
/** /**
* 将另一个对象合并过来 * 将另一个对象合并过来
* *
* @param node 代合并对象 * @param node 代合并对象
* @param func 判断覆盖方式的函数 * @param func 覆盖方式的函数
* *
* @return AnyValue * @return AnyValue
*/ */

View File

@@ -2,6 +2,7 @@
*/ */
package org.redkale.util; package org.redkale.util;
import java.util.*;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -37,6 +38,31 @@ public interface ResourceEvent<T> {
return false; return false;
} }
public static List<ResourceEvent> create(Properties oldProps, Properties newProps) {
List<ResourceEvent> rs = new ArrayList<>();
if (oldProps == null && newProps == null) {
return rs;
}
if (oldProps == null) {
newProps.forEach((k, v) -> rs.add(ResourceEvent.create(k.toString(), v, null)));
} else if (newProps == null) {
oldProps.forEach((k, v) -> rs.add(ResourceEvent.create(k.toString(), null, v)));
} else {
newProps.forEach((k, v) -> {
String oldVal = oldProps.getProperty(k.toString());
if (!Objects.equals(v, oldVal)) {
rs.add(ResourceEvent.create(k.toString(), v, oldVal));
}
});
oldProps.forEach((k, v) -> {
if (!newProps.containsKey(k)) {
rs.add(ResourceEvent.create(k.toString(), null, v));
}
});
}
return rs;
}
public static <V> ResourceEvent<V> create(String name, V newValue, V oldValue) { public static <V> ResourceEvent<V> create(String name, V newValue, V oldValue) {
return new ResourceChangeEvent<>(name, newValue, oldValue); return new ResourceChangeEvent<>(name, newValue, oldValue);
} }

View File

@@ -434,6 +434,7 @@ public final class ResourceFactory {
/** /**
* 将多个以指定资源名的String对象注入到资源池中 * 将多个以指定资源名的String对象注入到资源池中
* properties的key一般以"property."开头
* *
* @param properties 资源键值对 * @param properties 资源键值对
* @param environmentName 额外的资源名 * @param environmentName 额外的资源名
@@ -441,7 +442,7 @@ public final class ResourceFactory {
* *
*/ */
public <A> void register(Properties properties, String environmentName, Class<A> environmentType) { public <A> void register(Properties properties, String environmentName, Class<A> environmentType) {
if (properties == null) return; if (properties == null || properties.isEmpty()) return;
List<ResourceChangeWrapper> wrappers = new ArrayList<>(); List<ResourceChangeWrapper> wrappers = new ArrayList<>();
List<ResourceEvent> environmentEventList = new ArrayList<>(); List<ResourceEvent> environmentEventList = new ArrayList<>();
properties.forEach((k, v) -> { properties.forEach((k, v) -> {