web-dev-qa-db-fra.com

Comment référencer une autre propriété dans Java.util.Properties?

Le fichier de propriétés Java peut-il référencer un autre fichier de propriétés?

## 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

Est-ce possible?

49
yli

C’est ce que vous voulez, c’est un peu vieux, mais cela peut répondre à vos besoins.

Activation de la substitution constante dans les valeurs de propriété

Vous pouvez substituer une constante n'importe où dans la valeur de la propriété et même avoir plus d'une constante dans une valeur, comme dans l'exemple suivant:

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

Dans cet exemple, la propriété "SomeValue" a pour valeur "chaussures, navires et cire à cacheter".

51
OscarRyz

Eproperties est le projet open source qui fournit une substitution de variable avec quelques autres fonctionnalités - bien que la substitution puisse être sans doute la plus utile. Il s'agit d'une sous-classe de Java.util.Properties, qui pourra être utilisée par toute autre classe pouvant prendre des informations de configuration en tant que propriétés.

12
Paul

Le Commons Config lib peut également le faire. http://commons.Apache.org/configuration/userguide/overview.html#Using_Configuration

Cependant, comme cela a déjà été souligné, jetez un coup d’œil à la bibliothèque EProperties; http://code.google.com/p/eproperties/

Il supporte un certain nombre de fonctionnalités intéressantes (telles que la substitution, l'imbrication, les listes), y compris l'inclusion, étend les propriétés Java et est un peu plus léger que Commons Config (qui vous permet également d'inclure des propriétés en utilisant la syntaxe d'inclusion). 

7
NightWolf

Les fichiers de propriétés standard ne sont que des paires clé-valeur. Dans le format texte, Properties sépare simplement la clé de la valeur et effectue certaines tâches simples, telles que l’autorisation des caractères échappés. Vous pourrez peut-être définir des entités dans la syntaxe XML détaillée.

Si vous voulez votre propre syntaxe de substitution, vous pouvez manipuler une valeur renvoyée comme vous le feriez avec n'importe quelle autre chaîne. Vous pouvez également écrire votre propre version de Properties ou effectuer la substitution lors de la génération du fichier.

6

La classe Java.util.Properties ne le fera pas pour vous. Il ne serait pas trop difficile de sous-classer Propriétés, de remplacer la méthode load () et d'effectuer la substitution vous-même 

5

Puisque eproperties est en quelque sorte non maintenu et que la configuration de commons a une dépendance sur la journalisation (ce qui signifie que vous ne pouvez pas l'utiliser pour configurer la journalisation), j'utilise cet extrait de code qui requiert uniquement commons-lang(3) pour charger les propriétés interpolées:

@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;
}

Contribution :

blah=${user.dir}
one=1
two=2
five=5
fifteen=${one}${five}
twoonefive=${two}${fifteen}
six=6

Sortie :

blah=/current/working/dir
one=1
two=2
five=5
fifteen=15
twoonefive=215
six=6

Évidemment, vous pouvez reconvertir le Map<String,String> en un objet Properties si vous en avez besoin. Je résous en fonction des propriétés déclarées précédemment et des propriétés système, mais vous pouvez évidemment l'ajuster dans le StrSubstitutor.lookup.

3
Adam Gent

Dans ce cas particulier (et dans autres aussi), vous feriez mieux de résoudre le problème de duplication en définissant différentes propriétés:

  1. changer: dir.proj1=dir.default /p1 en dir.proj1_extension=/p1
  2. prepend: dir.default à dir.proj1_extension pour obtenir l'emplacement complet de proj1 dans votre code d'application.

Faites la même chose pour les autres projets.

1
The Nail

Le fichier de configuration est composé d'instructions au format key=value ou key:value. Il existe un moyen possible pour lequel une valeur de clé peut faire référence à une autre valeur de clé. La chaîne entre une ouverture "$ {" et une fermeture "}" est interprétée comme une clé. La valeur de la variable substituée peut être définie en tant que propriété système ou dans le fichier de configuration lui-même.

Étant donné que Properties hérite de Hashtable, les méthodes put et putAll peuvent être appliquées à un Properties object.

Map<String, String> map = new LinkedHashMap<String, String>();
map.put("key", "vlaue");
Properties props = new Properties();
props.putAll( map );

élaborer le message de @Adam Gent en détail. 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;
    }
}

Fichier de configuration «Si vous souhaitez que la référence soit ignorée et ne soit pas remplacée, vous pouvez utiliser le format ci-dessous.

 $${${name}} must be used for output ${ Yash }.  EX: jdk = ${jre-1.8}

Fichier: 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}}

Exemple de format des propriétés Java (clé = valeur) log4j.properties

1
Yash

Ci-dessous, un extrait de code en Java permettant de lire les propriétés qui référencent d’autres propriétés. En particulier, ce sont des requêtes réutilisables, mais il peut en être d’autres.

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);
}

Exemple de propriétés:

key1=value1
key21=value2 ${key1}

Après avoir exécuté ceci, key21 aura la valeur value2 value1.

* Utilisation de la StrSubstitutor d'Apache.

0
AlikElzin-kilaka