2011-05-14 67 views
9

是否有一個良好的Java配置庫,它允許我以類型安全的方式讀取設置?例如,通過將我製作的IConfiguration接口與獲取器和setter聲明並允許我通過它讀取/寫入配置。用於Java的類型安全配置讀/寫庫?

使用properties.getProperty("group.setting")讀取設置然後將其轉換爲所需的類型會有點無聊。 Apache公共配置允許使用類似config.getDouble("number")的東西,但是「數字」在這裏是一個字符串,我希望能夠做一些事情,如double value = config.GetNumber()

回答

0

我不這麼認爲,因爲java不是一種動態語言。這是可以實現的唯一方法是如果你有一個代碼生成器可以獲取你的屬性文件並生成配置類。或者,如果您爲每個媒體資源手動添加吸氣劑。

我認爲,commons-configuration是最好的選擇。

0

您應該能夠通過使用XStream來序列化配置類來獲得一些牽引力。但缺點是:

  • 該配置文件將不會在一個標準的屬性文件格式。它將是任意的XML代替。
  • 序列化格式將會很脆弱。對配置類的微小更改可能會導致舊的配置文件無法讀取。

另一方面,基於任意XML的格式可以表示具有比標準屬性文件格式更好的結構的配置項。

2

如果你有一個配置界面,如:

public interface IConfig { 
    int getNumber(); 
    void setNumber(int number); 

    String getSomeProperty(); 
    void setSomeProperty(String someProperty); 
} 

那麼你可以使用一個Proxy映射的方法和屬性:

public class ConfigWrapper implements InvocationHandler { 
    @SuppressWarnings(value="unchecked") 
    public static <T> T wrap(Class c, Properties p) { 
    return (T)Proxy.newProxyInstance(c.getClassLoader(), new Class[] {c}, 
     new ConfigWrapper(p)); 
    } 

    private final Properties properties; 

    private ConfigWrapper(Properties p) { 
    this.properties = p; 
    } 

    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) { 
    if(method.getName().startsWith("get")) { 
     if(method.getReturnType().equals(int.class)) { 
     return Integer.parseInt(
      this.properties.getProperty(method.getName().substring(3))); 
     } else if(method.getReturnType().equals(String.class)) { 
     return this.properties.getProperty(method.getName().substring(3)); 
     } else { 
     // obviously in a real application you'd want to handle more than just 
     // String and int 
     throw new RuntimeException(method.getName() + " returns unsupported type: " 
      + method.getReturnType()); 
     } 
    } else if(method.getName().startsWith("set")) { 
     this.properties.setProperty(method.getName().substring(3), 
      args[0].toString()); 
     return null; 
    } else { 
     throw new RuntimeException("Unknown method: " + method.getName()); 
    } 
    } 
} 

要使用:

Properties p = new Properties(); 

IConfig config = wrap(IConfig.class, p); 

config.setNumber(50); 
config.setSomeProperty("some value"); 
System.out.println(config.getNumber()); 
System.out.println(config.getSomeProperty()); 
System.out.println(p); 

調用其中一種接口方法會導致致電ConfigWrapper.invoke(),該更新從Properties對象中進行測試或檢索(取決於您是否稱爲getter或setter)。

注意,此實現是明顯的不安全因爲:在Properties對象

  • 值已經沒有生效,直到消氣叫
  • setter和getter沒有接受/返回相同的類型

我不知道現有的庫可以這樣做,也許是因爲Properties對象在它們可以描述的配置方面相當有限。

2

我的Config4J庫(這是成熟的,有據可查的但不廣爲人知)提供了你想要的大部分。

特別是,Config4J爲內置類型(如字符串,布爾值,整型,浮點型和持續時間(如"500 milliseconds""2.5 days"))提供了類型安全的「查找」(即「get」)操作。持續時間字符串會自動轉換爲表示(您選擇的)毫秒或秒的整數值。

庫還提供了構建塊,所以你可以在形式"<float> <units>"的執行字符串類型安全查詢(例如,用於距離"2 cm""10.5 meters")或"<units> <float>"(例如,"$0.99""£10.00"費錢)。

該庫還提供了一個簡單易用的模式驗證程序(如果您感興趣的話)。

Config4J不能滿足您所聲明的要求的方式是庫的「插入」(即「put」)功能僅以字符串形式工作。所以你必須將一個int/boolean/float/int-denoting-duration/whatever值轉換成一個字符串,然後將其「插入」到Config4J對象中。但是,這種字符串轉換通常不是一項繁重的任務。

插入一些名稱=值雙到Config4J對象後,你可以調用dump()整個對象序列化到一個字符串,然後你可以寫回的配置文件。

閱讀「入門指南」(PDF,HTML)的第2章和第3章應該給你一個足夠好的Config4J概述,以決定它是否適合您的需求。您可能還想看看源代碼下載(compressed tar,zip)中提供的「簡單封裝」演示。

+0

謝謝,我會看。順便說一句,該網站的第一章在哪裏? :)我只看到2-4 – 2011-05-17 14:26:39

+0

@FractalizeR:在www.config4star.org網站上,向下滾動到「下載手冊」部分,您將可以訪問所有手冊。 – 2011-05-17 15:42:05

3

您可以使用XSD定義XML配置文件,然後使用XJC生成JAXB源代碼。每個XSD類型都映射到Java類,您可以輕鬆地編組/解組編碼XSD:

<xsd:simpleType name="GroupType"> 
    <xsd:restriction base="xsd:int"> 
    <xsd:minInclusive value="1"/> 
    <xsd:maxInclusive value="255"/> 
    </xsd:restriction> 
</xsd:simpleType> 

生成的Java代碼:

public class ElementType { 
    @XmlAttribute(name = "Group", required = true) 
    protected int group; 

    public int getGroup() { 
     return group; 
    } 
    public void setGroup(int value) { 
     this.group = value; 
    } 
} 

從教程摘自:

http://jaxb.java.net/tutorial/

8

OWNER庫你想要做什麼。

+0

它的頁面充滿了404錯誤...文檔在哪裏? – 2013-07-06 13:45:05

+1

它似乎已轉移到http://owner.aeonbits.org/docs/welcome/ – 2013-07-06 14:44:44

4

我認爲類型安全的配置庫是你可能需要的。這是link

它是一個類型安全的庫。下面是關於如何使用這個庫的例子:爲什麼我建議這個庫是它可以讀取HOCON文件

import com.typesafe.config.ConfigFactory 

Config conf = ConfigFactory.load(); 
int bar1 = conf.getInt("foo.bar"); 
Config foo = conf.getConfig("foo"); 
int bar2 = foo.getInt("bar"); 

的主要原因。它代表着「以人優化配置對象符號」,是JSON的一個超集:

{ 
    "foo" : { 
     "bar" : 10, 
     "baz" : 12 
    } 
} 

它有許多功能,使它更具可讀性。就像省略特殊字符(,,:,{})。而最酷的事情就是繼承:

standard-timeout = 10ms 
foo.timeout = ${standard-timeout} 
bar.timeout = ${standard-timeout} 

如果你複製一個字段與對象的值,然後將對象與最後一勝合併。所以:

foo = { a : 42, c : 5 } 
foo = { b : 43, c : 6 } 

意思是一樣的:

foo = { a : 42, b : 43, c : 6 } 

請看項目的自述文件找到更多關於這個偉大的配置庫https://github.com/typesafehub/config