web-dev-qa-db-ja.com

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

これは可能ですか?

50
yli

Chris Mairの 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 = ja&ct = clnk&gl = us

51
OscarRyz

Epropertiesはオープンソースプロジェクトです これは、変数の置換と他のいくつかの機能を提供します-置換は間違いなく最も有用かもしれません。これはJava.util.Propertiesのサブクラスであり、構成情報をプロパティとして取得する他のクラスで使用できます。

12
Paul

Commons Config libもこれを行うことができます。 http://commons.Apache.org/configuration/userguide/overview.html#Using_Configuration

ただし、既に指摘したように、EPropertiesライブラリをご覧ください。 http://code.google.com/p/eproperties/

インクルード、extends Java Properties)を含む多くの端正な機能(置換、ネスト、リストなど)をサポートし、Commons Config(これを使用してプロパティを含めることもできます)構文を含める)。

7
NightWolf

標準プロパティファイルは、単にキーと値のペアです。テキスト形式では、Propertiesはキーを値から分離するだけで、エスケープされた文字を許可するなどの簡単なことを行います。詳細なXML構文でエンティティを定義できる場合があります。

独自の置換構文が必要な場合は、他の文字列と同様に戻り値を操作できます。または、独自のバージョンのPropertiesを記述するか、ファイルを生成するときに置換を行うことができます。

Java.util.Propertiesクラスはこれを行いません。プロパティをサブクラス化し、load()メソッドをオーバーライドし、自分で置換を行うことはそれほど難しくありません。

5

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

3
Adam Gent

この特定の場合(および others でも)、異なるプロパティを定義することで重複を解決した方が良いでしょう。

  1. 変化する: dir.proj1=dir.default /p1 into dir.proj1_extension=/p1
  2. 付加:dir.defaultからdir.proj1_extensionアプリケーションコードでproj1の完全な場所を取得します。

他のプロジェクトについても同じことを行います。

1
The Nail

構成ファイルは、key=valueまたはkey:value形式のステートメントで構成されます。キー値が別のキー値を参照できる可能な方法です。開始 "$ {"と終了 "}"の間の文字列はキーとして解釈されます。置換された変数の値は、システムプロパティとして、または構成ファイル自体で定義できます。

PropertiesHashtableから継承するため、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プロパティ(key = value)形式の例 log4j.properties

1
Yash

私が本当に気に入った特定の解決策はありません。 EPropertiesは維持されておらず、Maven Centralでは使用できません。 Commons Configはこれには大きすぎます。 commons-langの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));

プリントアウト:

{car =これはルーベンの車、name = ruben、another_name = ruben}

0
lqbweb

以下は、他のプロパティを参照するプロパティを読み取るための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を使用します。

0