Как ссылаться на другое свойство в java.util.Properties? - PullRequest
50 голосов
/ 16 мая 2009

Может ли файл свойств 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

Возможно ли это?

Ответы [ 9 ]

51 голосов
/ 07 ноября 2009

Это то, что вы хотите, оно немного старое, но может работать для ваших нужд.

Включение подстановки констант в значениях свойств

Вы можете подставить константу в любом месте значения свойства и даже иметь более одной константы в значении, как в следующем примере:

CONST_1 = shoes and ships
CONST_2 = sealing wax
SomeValue = {CONST_1} and {CONST_2} 

В этом примере свойство SomeValue оценивается как «обувь, корабли и сургуч».

12 голосов
/ 07 ноября 2009

Eproperties - это проект с открытым исходным кодом , который обеспечивает подстановку переменных наряду с несколькими другими функциями - хотя подстановка может быть наиболее полезной. Это подкласс java.util.Properties, и он может использоваться любым другим классом, который может принимать информацию о конфигурации в качестве свойств.

7 голосов
/ 18 февраля 2013

Библиотека Commons Config также может сделать это. http://commons.apache.org/configuration/userguide/overview.html#Using_Configuration

Однако, как уже отмечалось, взгляните на библиотеку EProperties; http://code.google.com/p/eproperties/

Он поддерживает ряд полезных функций (таких как подстановка, вложение, списки), включая включение, расширяет свойства Java и немного более легок, чем Commons Config (который также позволяет включать свойства с использованием синтаксиса include).

6 голосов
/ 16 мая 2009

Стандартные файлы свойств - это просто пары ключ-значение. В текстовом формате Properties просто отделяет ключ от значения и делает некоторые простые вещи, такие как разрешение экранированных символов. Вы можете определить сущности в подробном синтаксисе XML.

Если вам нужен собственный синтаксис замещения, вы можете манипулировать возвращаемым значением, как если бы вы использовали любую другую строку. Кроме того, вы можете написать собственную версию Properties или выполнить подстановку при генерации файла.

5 голосов
/ 16 мая 2009

Класс java.util.Properties не сделает этого за вас. Было бы не сложно создать подкласс Properties, переопределить метод load () и выполнить подстановку самостоятельно.

3 голосов
/ 31 декабря 2014

Поскольку свойства 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;
}

Input

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.

1 голос
/ 15 декабря 2017

Файл конфигурации состоит из операторов в формате 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

1 голос
/ 15 января 2012

В этом конкретном случае (и в других тоже) лучше разрешить дублирование, задав различные свойства:

  1. изменить: dir.proj1=dir.default /p1 на dir.proj1_extension=/p1
  2. prepend: dir.default to dir.proj1_extension, чтобы получить полное местоположение proj1 в коде вашего приложения.

Сделайте то же самое для других проектов.

0 голосов
/ 11 августа 2016

Ниже приведен фрагмент кода на 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's StrSubstitutor.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...