PropertiesAgent

This commit is contained in:
redkale
2023-12-15 12:45:50 +08:00
parent 56d0ad2711
commit feb063a4ed
5 changed files with 363 additions and 307 deletions

View File

@@ -24,6 +24,7 @@ import java.util.logging.SimpleFormatter;
import static org.redkale.boot.Application.RESNAME_APP_CONF_DIR;
import static org.redkale.boot.Application.RESNAME_APP_CONF_FILE;
import static org.redkale.boot.Application.RESNAME_APP_HOME;
import org.redkale.source.DataSources;
import org.redkale.util.AnyValue;
import org.redkale.util.RedkaleClassLoader;
import org.redkale.util.RedkaleException;
@@ -83,14 +84,14 @@ class AppConfig {
//Server根ClassLoader
RedkaleClassLoader serverClassLoader;
//本地文件system.property.开头的配置项
Properties localEnvProperties = new Properties();
//本地文件所有的配置项, 包含system.property.开头的
final Properties localEnvProperties = new Properties();
//本地文件设置System.properties且不存于System.properties的配置项
Properties localSysProperties = new Properties();
final Properties localSysProperties = new Properties();
//本地文件日志配置项
Properties locaLogProperties = new Properties();
final Properties locaLogProperties = new Properties();
public AppConfig(boolean singletonMode, boolean compileMode) {
this.singletonMode = singletonMode;
@@ -116,6 +117,8 @@ class AppConfig {
this.initLocalProperties();
//读取本地日志配置
this.initLogProperties();
//读取本地数据库配置
this.initSourceProperties();
}
/**
@@ -190,17 +193,56 @@ class AppConfig {
*/
private void initLocalProperties() {
AnyValue propsConf = this.config.getAnyValue("properties");
if (propsConf == null) {
final AnyValue resources = config.getAnyValue("resources");
if (resources != null) {
System.err.println("<resources> in application config file is deprecated");
propsConf = resources.getAnyValue("properties");
}
}
if (propsConf != null) { //设置配置文件中的系统变量
for (AnyValue prop : propsConf.getAnyValues("property")) {
String key = prop.getValue("name", "");
String value = prop.getValue("value");
if (value != null && key.startsWith("system.property.")) {
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
localSysProperties.put(propName, value);
}
} else if (value != null) {
if (value != null) {
localEnvProperties.put(key, value);
if (key.startsWith("system.property.")) {
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
localSysProperties.put(propName, value);
}
}
}
}
if (propsConf.getValue("load") != null) { //加载本地配置项文件
for (String dfload : propsConf.getValue("load").replace(',', ';').split(";")) {
if (dfload.trim().isEmpty()) {
continue;
}
final URI df = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), dfload.trim());
if (df == null) {
continue;
}
if (!"file".equals(df.getScheme()) || df.toString().contains("!") || new File(df).isFile()) {
Properties props = new Properties();
try {
InputStream in = df.toURL().openStream();
props.load(in);
in.close();
props.forEach((x, y) -> {
String key = x.toString();
if (key.startsWith("system.property.")) {
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
localSysProperties.put(propName, y.toString());
}
}
});
localEnvProperties.putAll(props);
} catch (Exception e) {
throw new RedkaleException(e);
}
}
}
}
}
@@ -215,6 +257,69 @@ class AppConfig {
}
}
/**
* 读取本地数据库配置
*/
private void initSourceProperties() {
//------------------------------------ 读取本地DataSource、CacheSource配置 ------------------------------------
if ("file".equals(this.confPath.getScheme())) {
File sourceFile = new File(new File(confPath), "source.properties");
if (sourceFile.isFile() && sourceFile.canRead()) {
Properties props = new Properties();
try {
InputStream in = new FileInputStream(sourceFile);
props.load(in);
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
props.forEach((x, y) -> {
String key = x.toString();
if (key.startsWith("system.property.")) {
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
localSysProperties.put(propName, y.toString());
}
}
});
this.localEnvProperties.putAll(props);
} else {
//兼容 persistence.xml 【已废弃】
File persist = new File(new File(confPath), "persistence.xml");
if (persist.isFile() && persist.canRead()) {
System.err.println("persistence.xml is deprecated, replaced by source.properties");
try {
InputStream in = new FileInputStream(persist);
this.localEnvProperties.putAll(DataSources.loadSourceProperties(in));
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
}
}
} else { //从url或jar文件中resources读取
try {
final URI sourceURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), "source.properties");
InputStream in = sourceURI.toURL().openStream();
Properties props = new Properties();
props.load(in);
in.close();
props.forEach((x, y) -> {
String key = x.toString();
if (key.startsWith("system.property.")) {
String propName = key.substring("system.property.".length());
if (System.getProperty(propName) == null) { //命令行传参数优先级高
localSysProperties.put(propName, y.toString());
}
}
});
this.localEnvProperties.putAll(props);
} catch (Exception e) {
//没有文件 跳过
}
}
}
/**
* 读取本地日志配置
*/
@@ -238,7 +343,10 @@ class AppConfig {
Properties properties0 = new Properties();
properties0.load(fin);
fin.close();
properties0.forEach((k, v) -> locaLogProperties.put(k.toString(), v.toString()));
properties0.forEach((k, v) -> {
locaLogProperties.put(k.toString(), v.toString());
localEnvProperties.put(k.toString(), v.toString());
});
} catch (IOException e) {
throw new RedkaleException("read logging.properties error", e);
}

View File

@@ -79,7 +79,7 @@ public final class Application {
/**
* 当前进程的配置文件, 类型String、URI、File、Path <br>
* 一般命名为: application.xml、application.properties 若配置文件不是本地文件, 则File、Path类型的值为null
* 一般命名为: application.xml、application.onlyLogProps 若配置文件不是本地文件, 则File、Path类型的值为null
*/
public static final String RESNAME_APP_CONF_FILE = "APP_CONF_FILE";
@@ -134,6 +134,9 @@ public final class Application {
//日志
private final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
//系统初始化时的原始配置项,启动后是不可更改的配置项
final Set<String> sysPropNames;
//本进程节点ID
final int nodeid;
@@ -165,11 +168,8 @@ public final class Application {
//@since 2.7.0
private PropertiesAgent propertiesAgent;
//只存放不以system.property.、mimetype.property.、redkale.开头的配置项
private final Properties envProperties = new Properties();
//envProperties更新锁
private final ReentrantLock envPropertiesLock = new ReentrantLock();
//所有配置项包含本地配置项、logging配置项和配置中心获取的配置项
final Properties envProperties = new Properties();
//配置信息只读版Properties
private final Environment environment;
@@ -240,6 +240,7 @@ public final class Application {
this.compileMode = appConfig.compileMode;
this.config = appConfig.config;
this.configFromCache = appConfig.configFromCache;
this.envProperties.putAll(appConfig.localEnvProperties);
this.environment = new Environment(this.envProperties);
this.name = appConfig.name;
this.nodeid = appConfig.nodeid;
@@ -275,6 +276,7 @@ public final class Application {
System.setProperty("redkale.application.nodeid", String.valueOf(this.nodeid));
System.setProperty("redkale.application.home", this.home.getPath());
System.setProperty("redkale.application.confPath", this.confPath.toString());
this.sysPropNames = Collections.unmodifiableSet((Set) System.getProperties().keySet());
//初始化本地配置的System.properties
appConfig.localSysProperties.forEach((k, v) -> {
@@ -304,7 +306,7 @@ public final class Application {
moduleEngines.add(new ScheduleModuleEngine(this));
//根据本地日志配置文件初始化日志
reconfigLogging(appConfig.locaLogProperties);
reconfigLogging(true, appConfig.locaLogProperties);
//打印基础信息日志
logger.log(Level.INFO, colorMessage(logger, 36, 1, "-------------------------------- Redkale " + Redkale.getDotedVersion() + " --------------------------------"));
@@ -332,13 +334,17 @@ public final class Application {
public void init() throws Exception {
//注册ResourceType
this.initResourceTypeLoader();
this.onAppPreInit();
//读取远程配置
this.loadResourceProperties();
this.initRemoteProperties();
//解析配置
this.onEnvironmentLoaded();
//init起始回调
this.onAppPreInit();
//设置WorkExecutor
this.initWorkExecutor();
initResources();
//结束时回调
//回调Listener
initAppListeners();
//init结束回调
this.onAppPostInit();
}
@@ -550,7 +556,7 @@ public final class Application {
}, HttpRpcClient.class);
}
private void initResources() throws Exception {
private void initAppListeners() throws Exception {
//------------------------------------------------------------------------
for (AnyValue conf : config.getAnyValues("group")) {
final String group = conf.getValue("name", "");
@@ -585,72 +591,10 @@ public final class Application {
//------------------------------------------------------------------------
}
private void loadResourceProperties() {
private void initRemoteProperties() {
final Properties dyncProps = new Properties();
final AtomicInteger propertyIndex = new AtomicInteger();
Properties logProps = null; //新的日志配置项
//------------------------------------ 读取本地DataSource、CacheSource配置 ------------------------------------
if ("file".equals(this.confPath.getScheme())) {
File sourceFile = new File(new File(confPath), "source.properties");
if (sourceFile.isFile() && sourceFile.canRead()) {
Properties props = new Properties();
try {
InputStream in = new FileInputStream(sourceFile);
props.load(in);
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
props.forEach((key, val) -> {
if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[")
|| key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) {
dyncProps.put(key, val);
} else {
logger.log(Level.WARNING, "skip illegal key " + key + " in source.properties");
}
});
} else {
//兼容 persistence.xml 【已废弃】
File persist = new File(new File(confPath), "persistence.xml");
if (persist.isFile() && persist.canRead()) {
logger.log(Level.WARNING, "persistence.xml is deprecated, replaced by source.properties");
try {
InputStream in = new FileInputStream(persist);
dyncProps.putAll(DataSources.loadSourceProperties(in));
in.close();
} catch (IOException e) {
throw new RedkaleException(e);
}
}
}
} else { //从url或jar文件中resources读取
try {
final URI sourceURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), "source.properties");
InputStream in = sourceURI.toURL().openStream();
Properties props = new Properties();
props.load(in);
in.close();
props.forEach((key, val) -> {
if (key.toString().startsWith("redkale.datasource.") || key.toString().startsWith("redkale.datasource[")
|| key.toString().startsWith("redkale.cachesource.") || key.toString().startsWith("redkale.cachesource[")) {
dyncProps.put(key, val);
} else {
logger.log(Level.WARNING, "skip illegal key " + key + " in source.properties");
}
});
} catch (Exception e) { //没有文件 跳过
}
//兼容 persistence.xml 【已废弃】
try {
final URI xmlURI = RedkaleClassLoader.getConfResourceAsURI(configFromCache ? null : this.confPath.toString(), "persistence.xml");
InputStream in = xmlURI.toURL().openStream();
dyncProps.putAll(DataSources.loadSourceProperties(in));
in.close();
logger.log(Level.WARNING, "persistence.xml is deprecated, replaced by source.properties");
} catch (Exception e) { //没有文件 跳过
}
}
//------------------------------------ 读取配置项 ------------------------------------
AnyValue propertiesConf = config.getAnyValue("properties");
if (propertiesConf == null) {
@@ -775,7 +719,7 @@ public final class Application {
|| k.toString().startsWith("redkale.properties.property[")) {
dyncProps.put(k, v);
} else {
//支持系统变量 -Dredkale.properties.mykey=my-value
//支持系统变量 -Dredkale.onlyLogProps.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);
@@ -817,98 +761,107 @@ public final class Application {
}
//重置日志配置
if (logProps != null && !logProps.isEmpty()) {
reconfigLogging(logProps);
reconfigLogging(false, logProps);
}
}
void reconfigLogging(Properties properties0) {
/**
* 设置日志策略
*
* @param first 是否首次设置
* @param allProps 配置项全量
*/
void reconfigLogging(boolean first, Properties allProps) {
String searchRawHandler = "java.util.logging.SearchHandler";
String searchReadHandler = LoggingSearchHandler.class.getName();
Properties properties = new Properties();
properties0.entrySet().forEach(x -> {
properties.put(x.getKey().toString().replace(searchRawHandler, searchReadHandler),
x.getValue().toString()
Properties onlyLogProps = new Properties();
allProps.entrySet().forEach(x -> {
String key = x.getKey().toString();
if (key.startsWith("java.util.logging.") || key.contains(".level") || key.contains("handlers")) {
String val = x.getValue().toString()
.replace("%m", "%tY%tm").replace("%d", "%tY%tm%td") //兼容旧时间格式
.replace(searchRawHandler, searchReadHandler)
);
.replace(searchRawHandler, searchReadHandler);
onlyLogProps.put(key.replace(searchRawHandler, searchReadHandler), val);
}
});
if (properties.getProperty("java.util.logging.FileHandler.formatter") == null) {
if (onlyLogProps.getProperty("java.util.logging.FileHandler.formatter") == null) {
if (compileMode) {
properties.setProperty("java.util.logging.FileHandler.formatter", SimpleFormatter.class.getName());
if (properties.getProperty("java.util.logging.SimpleFormatter.format") == null) {
properties.setProperty("java.util.logging.SimpleFormatter.format", LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
onlyLogProps.setProperty("java.util.logging.FileHandler.formatter", SimpleFormatter.class.getName());
if (onlyLogProps.getProperty("java.util.logging.SimpleFormatter.format") == null) {
onlyLogProps.setProperty("java.util.logging.SimpleFormatter.format", LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
}
} else {
properties.setProperty("java.util.logging.FileHandler.formatter", LoggingFileHandler.LoggingFormater.class.getName());
onlyLogProps.setProperty("java.util.logging.FileHandler.formatter", LoggingFileHandler.LoggingFormater.class.getName());
}
}
if (properties.getProperty("java.util.logging.ConsoleHandler.formatter") == null) {
if (onlyLogProps.getProperty("java.util.logging.ConsoleHandler.formatter") == null) {
if (compileMode) {
properties.setProperty("java.util.logging.ConsoleHandler.formatter", SimpleFormatter.class.getName());
if (properties.getProperty("java.util.logging.SimpleFormatter.format") == null) {
properties.setProperty("java.util.logging.SimpleFormatter.format", LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
onlyLogProps.setProperty("java.util.logging.ConsoleHandler.formatter", SimpleFormatter.class.getName());
if (onlyLogProps.getProperty("java.util.logging.SimpleFormatter.format") == null) {
onlyLogProps.setProperty("java.util.logging.SimpleFormatter.format", LoggingFileHandler.FORMATTER_FORMAT.replaceAll("\r\n", "%n"));
}
} else {
properties.setProperty("java.util.logging.ConsoleHandler.formatter", LoggingFileHandler.LoggingFormater.class.getName());
onlyLogProps.setProperty("java.util.logging.ConsoleHandler.formatter", LoggingFileHandler.LoggingFormater.class.getName());
}
}
if (!compileMode) { //ConsoleHandler替换成LoggingConsoleHandler
final String handlers = properties.getProperty("handlers");
final String handlers = onlyLogProps.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.ConsoleHandler")) {
final String consoleHandlerClass = LoggingFileHandler.LoggingConsoleHandler.class.getName();
properties.setProperty("handlers", handlers.replace("java.util.logging.ConsoleHandler", consoleHandlerClass));
onlyLogProps.setProperty("handlers", handlers.replace("java.util.logging.ConsoleHandler", consoleHandlerClass));
Properties prop = new Properties();
String prefix = consoleHandlerClass + ".";
properties.entrySet().forEach(x -> {
onlyLogProps.entrySet().forEach(x -> {
if (x.getKey().toString().startsWith("java.util.logging.ConsoleHandler.")) {
prop.put(x.getKey().toString().replace("java.util.logging.ConsoleHandler.", prefix), x.getValue());
}
});
prop.entrySet().forEach(x -> {
properties.put(x.getKey(), x.getValue());
onlyLogProps.put(x.getKey(), x.getValue());
});
}
}
String fileHandlerPattern = properties.getProperty("java.util.logging.FileHandler.pattern");
String fileHandlerPattern = onlyLogProps.getProperty("java.util.logging.FileHandler.pattern");
if (fileHandlerPattern != null && fileHandlerPattern.contains("%")) { //带日期格式
final String fileHandlerClass = LoggingFileHandler.class.getName();
Properties prop = new Properties();
final String handlers = properties.getProperty("handlers");
final String handlers = onlyLogProps.getProperty("handlers");
if (handlers != null && handlers.contains("java.util.logging.FileHandler")) {
//singletonrun模式下不输出文件日志
prop.setProperty("handlers", handlers.replace("java.util.logging.FileHandler", singletonMode || compileMode ? "" : fileHandlerClass));
}
if (!prop.isEmpty()) {
String prefix = fileHandlerClass + ".";
properties.entrySet().forEach(x -> {
onlyLogProps.entrySet().forEach(x -> {
if (x.getKey().toString().startsWith("java.util.logging.FileHandler.")) {
prop.put(x.getKey().toString().replace("java.util.logging.FileHandler.", prefix), x.getValue());
}
});
prop.entrySet().forEach(x -> properties.put(x.getKey(), x.getValue()));
prop.entrySet().forEach(x -> onlyLogProps.put(x.getKey(), x.getValue()));
}
if (!compileMode) {
properties.put(SncpClient.class.getSimpleName() + ".handlers", LoggingFileHandler.LoggingSncpFileHandler.class.getName());
onlyLogProps.put(SncpClient.class.getSimpleName() + ".handlers", LoggingFileHandler.LoggingSncpFileHandler.class.getName());
}
}
if (compileMode) {
properties.put("handlers", "java.util.logging.ConsoleHandler");
Map newprop = new HashMap(properties);
onlyLogProps.put("handlers", "java.util.logging.ConsoleHandler");
Map newprop = new HashMap(onlyLogProps);
newprop.forEach((k, v) -> {
if (k.toString().startsWith("java.util.logging.FileHandler.")) {
properties.remove(k);
onlyLogProps.remove(k);
}
});
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(out);
properties.forEach((x, y) -> ps.println(x + "=" + y));
onlyLogProps.forEach((x, y) -> ps.println(x + "=" + y));
try {
LogManager manager = LogManager.getLogManager();
manager.readConfiguration(new ByteArrayInputStream(out.toByteArray()));
this.loggingProperties.clear();
this.loggingProperties.putAll(properties);
this.loggingProperties.putAll(onlyLogProps);
Enumeration<String> en = manager.getLoggerNames();
while (en.hasMoreElements()) {
for (Handler handler : manager.getLogger(en.nextElement()).getHandlers()) {
@@ -1187,9 +1140,9 @@ public final class Application {
*
* @param props 配置项全量
*/
private void onEnvironmentLoaded(Properties props) {
private void onEnvironmentLoaded() {
for (ModuleEngine item : moduleEngines) {
item.onEnvironmentLoaded(props);
item.onEnvironmentLoaded(this.envProperties);
}
}
@@ -1630,12 +1583,8 @@ public final class Application {
newVal = String.valueOf(getStartTime());
} else {
List<Properties> list = new ArrayList<>();
list.addAll(Arrays.asList(envs));
list.add(this.envProperties);
//list.add(this.sourceProperties);
//list.add(this.clusterProperties);
list.add(this.loggingProperties);
//list.add(this.messageProperties);
list.addAll(Arrays.asList(envs));
for (Properties prop : list) {
if (prop.containsKey(key)) {
newVal = getPropertyValue(prop.getProperty(key), envs);
@@ -1656,151 +1605,6 @@ public final class Application {
return val;
}
// public void schedule(Object service) {
// this.scheduleManager.schedule(service);
// }
//
// public void unschedule(Object service) {
// this.scheduleManager.unschedule(service);
// }
void updateEnvironmentProperties(String namespace, List<ResourceEvent> events) {
if (events == null || events.isEmpty()) {
return;
}
envPropertiesLock.lock();
try {
Properties envRegisterProps = new Properties();
Set<String> envRemovedKeys = new HashSet<>();
Properties envChangedProps = new Properties();
// Set<String> sourceRemovedKeys = new HashSet<>();
// Properties sourceChangedProps = new Properties();
Set<String> loggingRemovedKeys = new HashSet<>();
Properties loggingChangedProps = new Properties();
// Set<String> clusterRemovedKeys = new HashSet<>();
// Properties clusterChangedProps = new Properties();
//
// Set<String> messageRemovedKeys = new HashSet<>();
// Properties messageChangedProps = new Properties();
for (ResourceEvent<String> event : events) {
if (namespace != null && namespace.startsWith("logging")) {
if (event.newValue() == null) {
if (this.loggingProperties.containsKey(event.name())) {
loggingRemovedKeys.add(event.name());
}
} else {
loggingChangedProps.put(event.name(), event.newValue());
}
continue;
}
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 " + (namespace == null ? "" : namespace) + ", key cannot endsWith '.name'");
// } else {
// if (!Objects.equals(event.newValue(), this.sourceProperties.getProperty(event.name()))) {
// if (event.newValue() == null) {
// if (this.sourceProperties.containsKey(event.name())) {
// sourceRemovedKeys.add(event.name());
// }
// } else {
// sourceChangedProps.put(event.name(), event.newValue());
// }
// }
// }
} else if (event.name().startsWith("redkale.mq.") || event.name().startsWith("redkale.mq[")) {
// if (event.name().endsWith(".name")) {
// logger.log(Level.WARNING, "skip illegal key " + event.name() + " in mq config " + (namespace == null ? "" : namespace) + ", key cannot endsWith '.name'");
// } else {
// if (!Objects.equals(event.newValue(), this.messageProperties.getProperty(event.name()))) {
// if (event.newValue() == null) {
// if (this.messageProperties.containsKey(event.name())) {
// messageRemovedKeys.add(event.name());
// }
// } else {
// messageChangedProps.put(event.name(), event.newValue());
// }
// }
// }
} else if (event.name().startsWith("redkale.cluster.")) {
// if (!Objects.equals(event.newValue(), this.clusterProperties.getProperty(event.name()))) {
// if (event.newValue() == null) {
// if (this.clusterProperties.containsKey(event.name())) {
// clusterRemovedKeys.add(event.name());
// }
// } else {
// clusterChangedProps.put(event.name(), event.newValue());
// }
// }
} else if (event.name().startsWith("system.property.")) {
String propName = event.name().substring("system.property.".length());
if (event.newValue() == null) {
System.getProperties().remove(propName);
} else {
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("redkale.")) {
logger.log(Level.WARNING, "not support the environment property key " + event.name() + " on change event");
} else {
if (!Objects.equals(event.newValue(), this.envProperties.getProperty(event.name()))) {
envRegisterProps.put(event.name(), event.newValue());
if (event.newValue() == null) {
if (this.envProperties.containsKey(event.name())) {
envRemovedKeys.add(event.name());
}
} else {
envChangedProps.put(event.name(), event.newValue());
}
}
}
}
//普通配置项的变更
if (!envRegisterProps.isEmpty()) {
this.envProperties.putAll(envChangedProps);
envRemovedKeys.forEach(this.envProperties::remove);
DefaultAnyValue oldConf = (DefaultAnyValue) this.config.getAnyValue("properties");
DefaultAnyValue newConf = new DefaultAnyValue();
oldConf.forEach((k, v) -> newConf.addValue(k, v));
this.envProperties.forEach((k, v) -> {
newConf.addValue("property", new DefaultAnyValue().addValue("name", k.toString()).addValue("value", v.toString()));
});
oldConf.replace(newConf);
resourceFactory.register(envRegisterProps, "", Environment.class);
}
//日志配置项的变更
if (!loggingChangedProps.isEmpty() || !loggingRemovedKeys.isEmpty()) {
//只是简单变更日志级别则直接操作,无需重新配置日志
if (loggingRemovedKeys.isEmpty() && loggingChangedProps.size() == 1 && loggingChangedProps.containsKey(".level")) {
try {
Level logLevel = Level.parse(loggingChangedProps.getProperty(".level"));
Logger.getGlobal().setLevel(logLevel);
this.loggingProperties.putAll(loggingChangedProps);
logger.log(Level.INFO, "Reconfig logging level to " + logLevel);
} catch (Exception e) {
logger.log(Level.WARNING, "Reconfig logging level error, new level is " + loggingChangedProps.getProperty(".level"));
}
} else {
Properties newLogProps = new Properties();
newLogProps.putAll(this.loggingProperties);
newLogProps.putAll(loggingChangedProps);
loggingRemovedKeys.forEach(newLogProps::remove);
reconfigLogging(newLogProps);
logger.log(Level.INFO, "Reconfig logging finished ");
}
}
} finally {
envPropertiesLock.unlock();
}
}
private static String generateHelp() {
return ""
+ "Usage: redkale [command] [arguments]\r\n"

View File

@@ -57,7 +57,7 @@ public class LoggingSearchHandler extends LoggingBaseHandler {
final String name = "Redkale-Logging-" + getClass().getSimpleName().replace("Logging", "") + "-Thread";
final int batchSize = 100; //批量最多100条
final List<SearchLogRecord> logList = new ArrayList<>();
final SimpleFormatter formatter = new SimpleFormatter();
final Formatter formatter = new LoggingBaseHandler.LoggingFormater();
final PrintStream outStream = System.out;
new Thread() {
{
@@ -155,41 +155,41 @@ public class LoggingSearchHandler extends LoggingBaseHandler {
if (this.sourceResourceName == null || this.sourceResourceName.isEmpty()) {
throw new RedkaleException("not found logging.property " + cname + ".source");
}
String tagstr = manager.getProperty(cname + ".tag");
if (tagstr != null && !tagstr.isEmpty()) {
if (!checkTagName(tagstr.replaceAll("\\$\\{.+\\}", ""))) {
throw new RedkaleException("found illegal logging.property " + cname + ".tag = " + tagstr);
String tagStr = manager.getProperty(cname + ".tag");
if (tagStr != null && !tagStr.isEmpty()) {
if (!checkTagName(tagStr.replaceAll("\\$\\{.+\\}", ""))) {
throw new RedkaleException("found illegal logging.property " + cname + ".tag = " + tagStr);
}
this.tag = tagstr.replace("${" + RESNAME_APP_NAME + "}", System.getProperty("redkale.application.name", ""));
this.tag = tagStr.replace("${" + RESNAME_APP_NAME + "}", System.getProperty("redkale.application.name", ""));
if (this.tag.contains("%")) {
this.tagDateFormat = this.tag;
Times.formatTime(this.tagDateFormat, -1, System.currentTimeMillis()); //测试时间格式是否正确
}
}
String levelstr = manager.getProperty(cname + ".level");
String levelStr = manager.getProperty(cname + ".level");
try {
if (levelstr != null) {
Level l = Level.parse(levelstr);
if (levelStr != null) {
Level l = Level.parse(levelStr);
setLevel(l != null ? l : Level.ALL);
}
} catch (Exception e) {
//do nothing
}
String filterstr = manager.getProperty(cname + ".filter");
String filterStr = manager.getProperty(cname + ".filter");
try {
if (filterstr != null) {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterstr);
if (filterStr != null) {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(filterStr);
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
setFilter((Filter) clz.getDeclaredConstructor().newInstance());
}
} catch (Exception e) {
//do nothing
}
String formatterstr = manager.getProperty(cname + ".formatter");
String formatterStr = manager.getProperty(cname + ".formatter");
try {
if (formatterstr != null) {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterstr);
if (formatterStr != null) {
Class<?> clz = ClassLoader.getSystemClassLoader().loadClass(formatterStr);
RedkaleClassLoader.putReflectionDeclaredConstructors(clz, clz.getName());
setFormatter((Formatter) clz.getDeclaredConstructor().newInstance());
}
@@ -200,19 +200,19 @@ public class LoggingSearchHandler extends LoggingBaseHandler {
setFormatter(new SimpleFormatter());
}
String encodingstr = manager.getProperty(cname + ".encoding");
String encodingStr = manager.getProperty(cname + ".encoding");
try {
if (encodingstr != null) {
setEncoding(encodingstr);
if (encodingStr != null) {
setEncoding(encodingStr);
}
} catch (Exception e) {
//do nothing
}
String denyregxstr = manager.getProperty(cname + ".denyregx");
String denyRegxStr = manager.getProperty(cname + ".denyregx");
try {
if (denyregxstr != null && !denyregxstr.trim().isEmpty()) {
denyRegx = Pattern.compile(denyregxstr);
if (denyRegxStr != null && !denyRegxStr.trim().isEmpty()) {
denyRegx = Pattern.compile(denyRegxStr);
}
} catch (Exception e) {
//do nothing

View File

@@ -3,8 +3,12 @@
package org.redkale.boot;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.redkale.net.http.MimeType;
import org.redkale.util.*;
import org.redkale.util.AnyValue.DefaultAnyValue;
/**
* 配置源Agent, 在init方法内需要实现读取配置信息如果支持配置更改通知也需要在init里实现监听
@@ -22,6 +26,9 @@ public abstract class PropertiesAgent {
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
//envProperties更新锁
private final ReentrantLock updateLock = new ReentrantLock();
/**
* 编译时进行的操作
*
@@ -56,14 +63,141 @@ public abstract class PropertiesAgent {
*/
public abstract void destroy(AnyValue conf);
protected void updateEnvironmentProperties(Application application, String namespace, List<ResourceEvent> events) {
if (events == null || events.isEmpty()) {
protected final void updateEnvironmentProperties(Application application, String namespace, List<ResourceEvent> events) {
if (Utility.isEmpty(events)) {
return;
}
application.updateEnvironmentProperties(namespace, events);
updateLock.lock();
try {
Properties envRegisterProps = new Properties();
Set<String> envRemovedKeys = new HashSet<>();
Properties envChangedProps = new Properties();
// Set<String> sourceRemovedKeys = new HashSet<>();
// Properties sourceChangedProps = new Properties();
Set<String> loggingRemovedKeys = new HashSet<>();
Properties loggingChangedProps = new Properties();
// Set<String> clusterRemovedKeys = new HashSet<>();
// Properties clusterChangedProps = new Properties();
//
// Set<String> messageRemovedKeys = new HashSet<>();
// Properties messageChangedProps = new Properties();
for (ResourceEvent<String> event : events) {
if (namespace != null && namespace.startsWith("logging")) {
if (event.newValue() == null) {
if (application.loggingProperties.containsKey(event.name())) {
loggingRemovedKeys.add(event.name());
}
} else {
loggingChangedProps.put(event.name(), event.newValue());
}
continue;
}
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 " + (namespace == null ? "" : namespace) + ", key cannot endsWith '.name'");
// } else {
// if (!Objects.equals(event.newValue(), this.sourceProperties.getProperty(event.name()))) {
// if (event.newValue() == null) {
// if (this.sourceProperties.containsKey(event.name())) {
// sourceRemovedKeys.add(event.name());
// }
// } else {
// sourceChangedProps.put(event.name(), event.newValue());
// }
// }
// }
} else if (event.name().startsWith("redkale.mq.") || event.name().startsWith("redkale.mq[")) {
// if (event.name().endsWith(".name")) {
// logger.log(Level.WARNING, "skip illegal key " + event.name() + " in mq config " + (namespace == null ? "" : namespace) + ", key cannot endsWith '.name'");
// } else {
// if (!Objects.equals(event.newValue(), this.messageProperties.getProperty(event.name()))) {
// if (event.newValue() == null) {
// if (this.messageProperties.containsKey(event.name())) {
// messageRemovedKeys.add(event.name());
// }
// } else {
// messageChangedProps.put(event.name(), event.newValue());
// }
// }
// }
} else if (event.name().startsWith("redkale.cluster.")) {
// if (!Objects.equals(event.newValue(), this.clusterProperties.getProperty(event.name()))) {
// if (event.newValue() == null) {
// if (this.clusterProperties.containsKey(event.name())) {
// clusterRemovedKeys.add(event.name());
// }
// } else {
// clusterChangedProps.put(event.name(), event.newValue());
// }
// }
} else if (event.name().startsWith("system.property.")) {
String propName = event.name().substring("system.property.".length());
if (event.newValue() == null) {
System.getProperties().remove(propName);
} else {
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("redkale.")) {
logger.log(Level.WARNING, "not support the environment property key " + event.name() + " on change event");
} else {
if (!Objects.equals(event.newValue(), application.envProperties.getProperty(event.name()))) {
envRegisterProps.put(event.name(), event.newValue());
if (event.newValue() == null) {
if (application.envProperties.containsKey(event.name())) {
envRemovedKeys.add(event.name());
}
} else {
envChangedProps.put(event.name(), event.newValue());
}
}
}
}
//普通配置项的变更
if (!envRegisterProps.isEmpty()) {
application.envProperties.putAll(envChangedProps);
envRemovedKeys.forEach(application.envProperties::remove);
DefaultAnyValue oldConf = (DefaultAnyValue) application.getAppConfig().getAnyValue("properties");
DefaultAnyValue newConf = new DefaultAnyValue();
oldConf.forEach((k, v) -> newConf.addValue(k, v));
application.envProperties.forEach((k, v) -> {
newConf.addValue("property", new DefaultAnyValue().addValue("name", k.toString()).addValue("value", v.toString()));
});
oldConf.replace(newConf);
application.getResourceFactory().register(envRegisterProps, "", Environment.class);
}
//日志配置项的变更
if (!loggingChangedProps.isEmpty() || !loggingRemovedKeys.isEmpty()) {
//只是简单变更日志级别则直接操作,无需重新配置日志
if (loggingRemovedKeys.isEmpty() && loggingChangedProps.size() == 1 && loggingChangedProps.containsKey(".level")) {
try {
Level logLevel = Level.parse(loggingChangedProps.getProperty(".level"));
Logger.getGlobal().setLevel(logLevel);
application.loggingProperties.putAll(loggingChangedProps);
logger.log(Level.INFO, "Reconfig logging level to " + logLevel);
} catch (Exception e) {
logger.log(Level.WARNING, "Reconfig logging level error, new level is " + loggingChangedProps.getProperty(".level"));
}
} else {
Properties newLogProps = new Properties();
newLogProps.putAll(application.loggingProperties);
newLogProps.putAll(loggingChangedProps);
loggingRemovedKeys.forEach(newLogProps::remove);
application.reconfigLogging(false, newLogProps);
logger.log(Level.INFO, "Reconfig logging finished ");
}
}
} finally {
updateLock.unlock();
}
}
protected void reconfigLogging(Application application, Properties loggingProperties) {
application.reconfigLogging(loggingProperties);
}
}

View File

@@ -23,6 +23,7 @@ import org.redkale.net.Servlet;
import org.redkale.net.sncp.Sncp;
import org.redkale.service.Service;
import org.redkale.util.AnyValue;
import org.redkale.util.AnyValue.DefaultAnyValue;
import org.redkale.util.InstanceProvider;
import org.redkale.util.RedkaleClassLoader;
import org.redkale.util.RedkaleException;
@@ -51,7 +52,7 @@ public class SourceModuleEngine extends ModuleEngine {
private final ReentrantLock dataSourceLock = new ReentrantLock();
//原生sql解析器
private DataNativeSqlParser nativeSqlParser;
DataNativeSqlParser nativeSqlParser;
public SourceModuleEngine(Application application) {
super(application);
@@ -95,7 +96,7 @@ public class SourceModuleEngine extends ModuleEngine {
this.resourceFactory.register(DataNativeSqlParser.class, this.nativeSqlParser);
break; //only first provider
}
//------------------------------------- 注册 DataSource --------------------------------------------------------
resourceFactory.register((ResourceFactory rf, String srcResourceName, final Object srcObj, String resourceName, Field field, final Object attachment) -> {
try {
@@ -480,15 +481,24 @@ public class SourceModuleEngine extends ModuleEngine {
}
private AnyValue findSourceConfig(String sourceName, String sourceType) {
AnyValue sourceNode = application.getAppConfig().getAnyValue(sourceType);
if (sourceNode != null) {
AnyValue confNode = sourceNode.getAnyValue(sourceName);
if (confNode != null) { //必须要设置name属性
((AnyValue.DefaultAnyValue) confNode).setValue("name", sourceName);
Properties props = new Properties();
String bprefix = "redkale." + sourceType;
String prefix1 = bprefix + "." + sourceName + ".";
String prefix2 = bprefix + "[" + sourceName + "].";
this.sourceProperties.forEach((k, v) -> {
String key = k.toString();
if (key.startsWith(prefix1)) {
props.put(key.substring(prefix1.length()), v);
} else if (key.startsWith(prefix2)) {
props.put(key.substring(prefix2.length()), v);
}
return confNode;
});
if (props.isEmpty()) {
return null;
}
return null;
AnyValue conf = DefaultAnyValue.loadFromProperties(props);
((DefaultAnyValue) conf).setValue("name", sourceName);
return conf;
}
}