Как ссылаться на другое свойство в java.util.Properties?
Может ли файл свойств Java ссылаться на файл других свойств?
## define a default directory for Input files
dir.default=/home/data/in/
dir.proj1=${dir.default}p1
dir.proj2=${dir.default}p2
dir.proj3=${dir.default}p3
Возможно ли это?
Ответы
Ответ 1
Крис Майр XProperties класс может быть хорошей отправной точкой.
Вы можете заменить константу в любом месте значения свойства и даже иметь более одной константы в значении, как в следующем примере:
CONST_1 = shoes and ships
CONST_2 = sealing wax
SomeValue = {CONST_1} and {CONST_2}
В этом примере свойство SomeValue оценивается как "обувь, корабли и сургуч".
Смотрите также: http://webcache.googleusercontent.com/search?q=cache:gCgFCpEgmsgJ:www2.sys-con.com/itsg/virtualcd/java/source/6-12/52.html+&cd=1&hl=en&ct=clnk&gl=us
Ответ 2
Eproperties - это проект с открытым исходным кодом, который обеспечивает замену переменных наряду с несколькими другими функциями, хотя замена может оказаться наиболее полезной. Это подкласс java.util.Properties и может использоваться любым другим классом, который может получать информацию о конфигурации как Свойства.
Ответ 3
Также может это сделать Commons Config lib. http://commons.apache.org/configuration/userguide/overview.html#Using_Configuration
Однако, как уже указывалось, взгляните на библиотеку EProperties; http://code.google.com/p/eproperties/
Он поддерживает ряд опрятных функций (таких как подстановка, вложенность, списки), включая включение, расширение свойств Java и немного меньший вес, чем Commons Config (который также позволяет включать свойства с использованием синтаксиса include).
Ответ 4
Стандартные файлы свойств - это только пары ключ-значение. В текстовом формате Properties
просто отделяет ключ от значения и выполняет некоторые простые действия, такие как разрешение экранированных символов. Возможно, вы сможете определить объекты в подробном синтаксисе XML.
Если вам нужен собственный синтаксис подстановки, вы можете манипулировать возвращаемым значением, как и с любой другой строкой. Кроме того, вы можете написать свою собственную версию Properties
или выполнить подстановку при создании файла.
Ответ 5
Класс java.util.Properties не сделает этого для вас. Было бы не слишком сложно подклассифицировать свойства, переопределить метод load() и самостоятельно выполнить подстановку.
Ответ 6
Поскольку свойства eproperties не поддерживаются, а общая конфигурация имеет зависимость от ведения журнала (что по иронии судьбы означает, что вы не можете использовать его для настройки ведения журнала), я использую этот фрагмент кода, который требует только commons-lang(3)
для загрузки интерполированных свойств:
@SuppressWarnings("serial")
public static Map<String,String> loadPropertiesMap(InputStream s) throws IOException {
final Map<String, String> ordered = new LinkedHashMap<String, String>();
//Hack to use properties class to parse but our map for preserved order
Properties bp = new Properties() {
@Override
public synchronized Object put(Object key, Object value) {
ordered.put((String)key, (String)value);
return super.put(key, value);
}
};
bp.load(s);
final Map<String,String> resolved = new LinkedHashMap<String, String>(ordered.size());
StrSubstitutor sub = new StrSubstitutor(new StrLookup<String>() {
@Override
public String lookup(String key) {
String value = resolved.get(key);
if (value == null)
return System.getProperty(key);
return value;
}
});
for (String k : ordered.keySet()) {
String value = sub.replace(ordered.get(k));
resolved.put(k, value);
}
return resolved;
}
Ввод
blah=${user.dir}
one=1
two=2
five=5
fifteen=${one}${five}
twoonefive=${two}${fifteen}
six=6
Выход
blah=/current/working/dir
one=1
two=2
five=5
fifteen=15
twoonefive=215
six=6
Очевидно, вы можете преобразовать Map<String,String>
обратно в объект Properties
, если вам это нужно. Я решаю, основываясь на ранее объявленных свойствах и свойствах системы, но вы, очевидно, можете изменить это в StrSubstitutor.lookup
.
Ответ 7
В этом конкретном случае (и в других тоже), вам лучше решить дублирование, указав различные свойства:
- change:
dir.proj1=dir.default /p1
в dir.proj1_extension=/p1
- prepend:
dir.default
до dir.proj1_extension
, чтобы получить полное местоположение proj1 в вашем коде приложения.
Сделайте то же самое для других проектов.
Ответ 8
Файл конфигурации состоит из операторов в формате key=value
или key:value
.
Их возможный путь, когда значение ключа может ссылаться на другое значение ключа. Строка между открытием "$ {" и закрытием "}" интерпретируется как ключ. Значение замещенной переменной может быть определено как системное свойство или в самом файле конфигурации.
Поскольку Properties
наследуется от Hashtable
, методы put
и putAll
могут быть применены к Properties object
.
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("key", "vlaue");
Properties props = new Properties();
props.putAll( map );
выработать сообщение @Adam Gent в деталях. commons-text-1.1.jar
import org.apache.commons.text.StrLookup;
import org.apache.commons.text.StrSubstitutor;
public class Properties_With_ReferedKeys {
public static void main(String[] args) {
ClassLoader classLoader = Properties_With_ReferedKeys.class.getClassLoader();
String propertiesFilename = "keys_ReferedKeys.properties";
Properties props = getMappedProperties(classLoader, propertiesFilename);
System.out.println( props.getProperty("jdk") );
}
public static Properties getMappedProperties( ClassLoader classLoader, String configFilename ) {
Properties fileProperties = new Properties();
try {
InputStream resourceAsStream = classLoader.getResourceAsStream( configFilename );
Map<String, String> loadPropertiesMap = loadPropertiesMap( resourceAsStream );
Set<String> keySet = loadPropertiesMap.keySet();
System.out.println("Provided 'Key':'Value' pairs are...");
for (String key : keySet) {
System.out.println( key + " : " + loadPropertiesMap.get(key) );
}
fileProperties.putAll( loadPropertiesMap );
} catch ( IOException e ) {
e.printStackTrace();
}
return fileProperties;
}
public static Map<String,String> loadPropertiesMap( InputStream inputStream ) throws IOException {
final Map<String, String> unResolvedProps = new LinkedHashMap<String, String>();
/*Reads a property list (key and element pairs) from the input byte stream.
* The input stream is in a simple line-oriented format.
*/
@SuppressWarnings("serial")
Properties props = new Properties() {
@Override
public synchronized Object put(Object key, Object value) {
unResolvedProps.put( (String)key, (String)value );
return super.put( key, value );
}
};
props.load( inputStream );
final Map<String,String> resolvedProps = new LinkedHashMap<String, String>( unResolvedProps.size() );
// Substitutes variables within a string by values.
StrSubstitutor sub = new StrSubstitutor( new StrLookup<String>() {
@Override
public String lookup( String key ) {
/*The value of the key is first searched in the configuration file,
* and if not found there, it is then searched in the system properties.*/
String value = resolvedProps.get( key );
if (value == null)
return System.getProperty( key );
return value;
}
} );
for ( String key : unResolvedProps.keySet() ) {
/*Replaces all the occurrences of variables with their matching values from the resolver using the given
* source string as a template. By using the default ${} the corresponding value replaces the ${variableName} sequence.*/
String value = sub.replace( unResolvedProps.get( key ) );
resolvedProps.put( key, value );
}
return resolvedProps;
}
}
Файл конфигурации "Если вы хотите, чтобы ссылка была проигнорирована и не будет заменена, вы можете использовать формат ниже.
$${${name}} must be used for output ${ Yash }. EX: jdk = ${jre-1.8}
Файл: keys_ReferedKeys.properties
# MySQL Key for each developer for their local machine
dbIP = 127.0.0.1
dbName = myApplicationDB
dbUser = scott
dbPassword = tiger
# MySQL Properties
# To replace fixed-keys with corresponding build environment values. like « predev,testing,preprd.
config.db.driverClassName : com.mysql.jdbc.Driver
config.db.url : jdbc:mysql://${dbIP}:3306/${dbName}
config.db.username : ${dbUser}
config.db.password : ${dbPassword}
# SystemProperties
userDir = ${user.dir}
os.name = ${os.name}
java.version = ${java.version}
java.specification.version = ${java.specification.version}
# If you want reference to be ignored and won't be replaced.
# $${${name}} must be used for output ${ Yash }. EX: jdk = ${jre-1.8}
jdk = $${jre-${java.specification.version}}
Пример свойств Java (ключ = значение) log4j.properties
Ответ 9
Ниже приведен фрагмент кода в Java для чтения свойств, которые ссылаются на другие свойства. В частности, это повторные запросы, но могут быть и другими.
LinkedHashMap<String, String> sqlsRaw = loadPropertiesFromFile();
LinkedHashMap<String, String> sqls = new LinkedHashMap<>();
StrSubstitutor substitutor = new StrSubstitutor(sqls);
for (Map.Entry<String, String> entry : sqlsRaw.entrySet()) {
String sql = entry.getValue();
try {
sql = substitutor.replace(sql);
} catch (Exception e) {
throw new RuntimeException("Found an sql with a non replaced reference to another. Please validate that the required key was defined before this sql: " + entry.getValue(), e);
}
sqls.put(entry.getKey(), sql);
}
Свойства примера:
key1=value1
key21=value2 ${key1}
После запуска key21
будет иметь значение value2 value1
.
* Использование apache StrSubstitutor
.
Ответ 10
Ни одно из приведенных решений мне не очень понравилось. EProperties не поддерживается и недоступен в Maven Central. Commons Config слишком велик для этого. StrSubstitutor в общем достоянии устарел.
Мое решение опирается только на обычный текст:
public static Properties interpolateProperties(Properties rawProperties) {
Properties newProperties = new Properties();
interpolateProperties(rawProperties, newProperties);
return newProperties;
}
public static void interpolateProperties(Properties rawProperties, Properties dstProperties) {
StringSubstitutor sub = new StringSubstitutor((Map)rawProperties);
for (Map.Entry<Object, Object> e : rawProperties.entrySet()) {
dstProperties.put(e.getKey(), sub.replace(e.getValue()));
}
}
то есть:
Properties props = new Properties();
props.put("another_name", "lqbweb");
props.put("car", "this is a car from ${name}");
props.put("name", "${another_name}");
System.out.println(interpolateProperties(props));
распечатывает:
{машина = это машина из рубена, имя = рубен, другое имя = рубен}
Ответ 11
У меня есть вопрос
Я не могу повторно использовать значение ключа для определения другого ключа.
Пример:
alg.Name=claims
${alg.Name}.property1=srcid,extid
${alg.Name}.returnvalue=12
Может ли кто-нибудь предложить какое-нибудь решение или помочь мне в этом?