2009-05-16 17 views
45

¿Puede el archivo de propiedades de Java referenciar otro archivo de propiedades?¿Cómo hacer referencia a otra propiedad en java.util.Properties?

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

¿Esto es posible?

+1

se puede utilizar [Configuración Commons Apache] (http: //commons.apache.org/configuration/). – LaurentG

+0

¿Se trata de hacer referencia a otras propiedades en el mismo archivo o hacer referencia a propiedades en otros archivos? –

Respuesta

5

La clase java.util.Properties no hará esto por usted. No sería demasiado difícil crear propiedades por subclase, anular el método load() y hacer la sustitución usted mismo.

6

Los archivos de propiedades estándar son solo pares clave-valor. En el formato de texto, Properties simplemente separa la clave del valor y hace algunas cosas simples como permitir caracteres escapados. Es posible que pueda definir entidades en la sintaxis XML detallada.

Si desea su propia sintaxis de sustitución, puede manipular un valor devuelto como lo haría con cualquier otra cadena. Alternativamente, puede escribir su propia versión de Properties o hacer la sustitución al generar el archivo.

12

Eproperties is the open source project que proporciona sustitución de variables junto con algunas otras características, aunque la sustitución puede ser posiblemente la más útil. Es una subclase de java.util.Properties, y la puede usar cualquier otra clase que pueda tomar información de configuración como Propiedades.

+1

Solo hay un contenedor para instalar y usar, dado que tiene un registro común Apache en su classpath. Una descripción general de la sintaxis [aquí] (http://eproperties.googlecode.com/svn/docs/1.1.2/manual/index.html). – Vladtn

49

Esto es lo que quiere, es un poco viejo, pero puede funcionar para sus necesidades.

Enabling constant substitution in Property Values

Puede sustituir una constante en cualquier parte del valor de la propiedad, e incluso tener más de una constante dentro de un valor, como en el siguiente ejemplo:

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

En este ejemplo, la propiedad "SomeValue" se evalúa como "zapatos y barcos y cera de sellado".

+2

Sí, es viejo, pero funciona y no funciona en dependencias, o intenta hacer demasiado. –

+1

para mí no funciona ... ¿está obsoleto o algo así? : S – ianaz

+2

@ianaz Tenga en cuenta que en el enlace debe usar la subclase XProperties en lugar de Propiedades. Esta puede ser la razón por la que no ves nada. –

1

En este caso particular (y en others también), que le resuelve mejor la duplicación definiendo propiedades diferentes:

  1. cambio: dir.proj1=dir.default /p1 en dir.proj1_extension=/p1
  2. Prefijo: dir.default a dir.proj1_extension a obtenga la ubicación completa de proj1 en su código de aplicación.

Haz lo mismo para los otros proyectos.

6

La librería Commons Config también puede hacer esto. http://commons.apache.org/configuration/userguide/overview.html#Using_Configuration

Sin embargo, como se señaló anteriormente, eche un vistazo a la biblioteca EProperties; http://code.google.com/p/eproperties/

Es compatible con varias características claras (como sustitución, anidamiento, listas) incluyendo inclusión, extiende propiedades Java y es un poco más ligero que Commons Config (que también le permite incluir propiedades usando la sintaxis include).

3

Desde eproperties es una especie de no mantenido y configuración Commons tiene una dependencia en la explotación forestal (que, irónicamente, significa que no se puede utilizar para configurar el registro) utilizo este fragmento de código que sólo requiere commons-lang(3) para cargar propiedades interpoladas:

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

entrada:

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

salida:

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

Obviamente puede convertir el Map<String,String> de nuevo a un objeto Properties si lo necesita. Lo resuelvo en función de las propiedades y las propiedades del sistema previamente declaradas, pero obviamente puede ajustarlo en el StrSubstitutor.lookup.

0

A continuación se muestra un fragmento de código en Java para leer las propiedades que hacen referencia a otras propiedades. Específicamente, estas son consultas reutilizables, pero también pueden ser otras.

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

propiedades Ejemplo:

key1=value1 
key21=value2 ${key1} 

Después de ejecutar este, key21 tendrá el valor value2 value1.

* Usando apache's StrSubstitutor.

+1

** ¡No use 'StrSubstitutor' para SQL! ** No protegerá contra la inyección de SQL. Además, no me importa y tal vez te lo perdiste, pero ya proporcioné una respuesta usando StrSubstitutor 2 años antes que la tuya. –

+0

@AdamGent - Es un mecanismo para hacer referencia a las consultas por claves, no por valores. Todas las consultas son declaraciones preparadas :) –

0

El archivo de configuración consta de declaraciones en el formato key=value o key:value. Son posibles formas en que un valor clave puede hacer referencia al otro valor clave. La cadena entre una apertura "$ {" y cerrando "}" se interpreta como una clave. El valor de la variable sustituida se puede definir como una propiedad del sistema o en el archivo de configuración en sí.

Debido Properties hereda de Hashtable, los métodos put y putAll se puede aplicar a un Properties object.

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

elaborar el puesto de @ Adam Gent en-detallada. 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; 
    } 
} 

archivo de configuración «Si quieres referencia a ser ignorado y no serán reemplazados, puede utilizar el formato de abajo.

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

del archivo: 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}} 

propiedades Java formato (clave = valor) Ejemplo log4j.properties

Cuestiones relacionadas