2009-05-16 22 views
45

Thuộc tính Java có thể tham chiếu tệp thuộc tính khác không?Làm thế nào để tham khảo một thuộc tính khác trong 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 

Điều này có khả thi không?

+1

Bạn có thể sử dụng [Apache Commons Cấu hình] (http: //commons.apache.org/configuration/). – LaurentG

+0

Đây có phải là câu hỏi về việc tham chiếu các thuộc tính khác trong cùng một tệp hoặc tham chiếu các thuộc tính trong các tệp khác không? –

Trả lời

5

Lớp java.util.Properties sẽ không làm điều này cho bạn. Nó sẽ không quá khó khăn để phân lớp Properties, ghi đè lên phương thức load() và tự thay thế.

6

Tệp thuộc tính chuẩn chỉ là cặp khóa-giá trị. Trong định dạng văn bản, Properties chỉ tách khóa khỏi giá trị và thực hiện một số việc đơn giản như cho phép ký tự thoát. Bạn có thể xác định các thực thể trong cú pháp XML dài dòng.

Nếu bạn muốn cú pháp thay thế của riêng mình, khi đó bạn có thể thao tác một giá trị trả về giống như bất kỳ chuỗi nào khác. Ngoài ra, bạn có thể viết phiên bản Properties của riêng bạn hoặc thực hiện thay thế khi tạo tệp.

12

Eproperties is the open source project cung cấp thay thế biến cùng với một số tính năng khác - mặc dù thay thế có thể được cho là hữu ích nhất. Nó là một lớp con của java.util.Properties, và sẽ có thể được sử dụng bởi bất kỳ lớp nào khác có thể lấy thông tin cấu hình như Thuộc tính.

+1

Chỉ có một cái bình để cài đặt và sử dụng, vì bạn có đăng nhập thường gặp trong đường dẫn lớp của bạn. Tổng quan về cú pháp [ở đây] (http://eproperties.googlecode.com/svn/docs/1.1.2/manual/index.html). – Vladtn

49

Đây là những gì bạn muốn, nó hơi cũ, nhưng có thể phù hợp với nhu cầu của bạn.

Enabling constant substitution in Property Values

Bạn có thể thay thế một hằng số bất cứ nơi nào trong giá trị tài sản, và thậm chí có nhiều hơn một liên tục trong vòng một giá trị, như trong ví dụ sau đây:

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

Trong ví dụ này, thuộc tính "SomeValue" được đánh giá là "giày và tàu và sáp bịt kín".

+2

Có, nó cũ, nhưng nó hoạt động và không kéo gobs của phụ thuộc, hoặc cố gắng làm quá nhiều. –

+1

đối với tôi nó không hoạt động .. nó có bị phản đối hay gì đó không? : S – ianaz

+2

@ianaz Xin lưu ý trong liên kết mà bạn phải sử dụng XProperties lớp con thay vì Thuộc tính. Đây có thể là lý do tại sao bạn không thấy gì cả. –

1

Trong trường hợp đặc biệt này (và trong others quá), bạn nên giải quyết việc sao chép bằng cách định nghĩa các thuộc tính khác nhau:

  1. thay đổi: dir.proj1=dir.default /p1 vào dir.proj1_extension=/p1
  2. thêm vào trước: dir.default để dir.proj1_extension để có được vị trí đầy đủ của proj1 trong mã ứng dụng của bạn.

Làm tương tự cho các dự án khác.

6

Libons Config lib cũng có thể thực hiện việc này. http://commons.apache.org/configuration/userguide/overview.html#Using_Configuration

Tuy nhiên, như đã chỉ ra, hãy xem thư viện EProperties; http://code.google.com/p/eproperties/

Nó hỗ trợ một số tính năng gọn gàng (như thay thế, lồng, liệt kê) bao gồm cả, mở rộng Java Properties và trọng lượng nhẹ hơn Commons Config (cũng cho phép bạn bao gồm các thuộc tính sử dụng cú pháp bao gồm).

3

Kể từ eproperties là loại không được duy trì và cấu hình commons có một sự phụ thuộc vào cách đăng nhập (mà trớ trêu thay có nghĩa là bạn không thể sử dụng nó để cấu hình logging) tôi sử dụng đoạn mã này mà chỉ yêu cầu commons-lang(3) để tải thuộc tính nội suy:

@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 

Output:

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

Rõ ràng bạn có thể chuyển đổi Map<String,String> trở lại đối tượng Properties nếu bạn cần. Tôi giải quyết dựa trên các thuộc tính hệ thống và thuộc tính đã được khai báo trước đó nhưng bạn rõ ràng có thể điều chỉnh điều đó trong StrSubstitutor.lookup.

0

Dưới đây là đoạn mã trong Java để đọc các thuộc tính tham chiếu các thuộc tính khác. Cụ thể, đây là những truy vấn có thể sử dụng lại nhưng cũng có thể là các công cụ khác.

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

tính Ví dụ:

key1=value1 
key21=value2 ${key1} 

Sau khi chạy này, key21 sẽ có giá trị value2 value1.

* Sử dụng apache's StrSubstitutor.

+1

** Không sử dụng 'StrSubstitutor' cho SQL! ** Nó sẽ không bảo vệ khỏi việc tiêm SQL. Ngoài ra tôi không nhớ nó và có lẽ bạn đã bỏ lỡ nó nhưng tôi đã cung cấp một câu trả lời bằng cách sử dụng StrSubstitutor 2 năm trước khi bạn. –

+0

@AdamGent - Đây là cơ chế để tham chiếu truy vấn bằng khóa - không phải giá trị. Tất cả các truy vấn được chuẩn bị báo cáo :) –

0

Tệp cấu hình bao gồm các câu lệnh theo định dạng key=value hoặc key:value. Có thể có cách mà giá trị khóa có thể tham chiếu giá trị khóa khác. Chuỗi giữa một mở "$ {" và đóng "}" được hiểu là khóa. Giá trị của biến được thay thế có thể được định nghĩa là thuộc tính hệ thống hoặc trong tệp cấu hình.

Properties thừa hưởng từ Hashtable, các putputAll phương pháp có thể được áp dụng cho một Properties object.

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

xây dựng các bài của @ Adam Gent trong chi tiết. 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; 
    } 
} 

tập tin cấu hình «Nếu bạn muốn tham chiếu được bỏ qua và không được thay thế sau đó bạn có thể sử dụng dưới dạng.

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

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

tính Java định dạng (key = value) ví dụ log4j.properties

Các vấn đề liên quan