Application.xml废弃<resources>节点
This commit is contained in:
@@ -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
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) -> {
|
||||||
|
|||||||
Reference in New Issue
Block a user