簡約之美jodd--props屬性使用


  Prop是一個超級properties;包含了很多jdk缺失的東西:utf-8支持,宏,分區,profiles,全配置等等。

屬性存儲在一個或者多個*.props文件,而且它是開放的,支持多種類型的資源。更重要的是,它和java properties是兼容的。

  Props的目標不是提供一個最大限度地配置解決方案,而是提供一個比java properties更好的選擇。因此如果在應用中使用到properties,考慮使用Props來替代。

 基本規則

下面是介紹props文件格式的一組基本規則。其中的一些規則如下示例:

props example

utf8編碼

默認情況下,props文件是utf8編碼,也可以使用別的任意編碼格式。不管使用哪種編碼格式,props加載java properites時仍然使用ISO 8859-1.

去除空白字符

分區名稱和屬性名稱的開頭結尾的空白字符將被去除掉,而屬性值也會去除開頭和結尾的空白字符。

賦值

可以使用"="或者":"進行賦值。

值連接

使用"+="連接同名屬性的值(以逗號分隔)。

注解

從";"或者"#"開頭到行的結尾來注解。

轉義符

使用"\"作為轉義符,對字符進行轉義(例如 "\#"代表了字符"#","\\"代表"\")。

多行的值(Multi-line values)

如果"\"作為行的連接符,表明下一行仍然是屬性的值。

特殊字符

\\uXXXX將被編譯為字符,同樣\t,\r,\f也會編譯為字符。

多行值(Multiline values)

使用三引號作為一種方便的形式來定義多行的值。

注:三引號的語法是一對連續的單引號或者雙引號(通常都是成對的用)。

三引號讓程序員從引號和特殊字符串的泥潭里面解脫出來,自始至終保持一小塊字符串的格式是所謂的WYSIWYG(所見即所得)格式的。

基本用法

Props的使用非常簡單。概況的說,Props管理着屬性。

    Props p = new Props();
    p.load(new File("example.props"));
    ...
    String story = p.getValue("story");

Props加載屬性的方法有多種形式:文件、輸入流、字符串、屬性Properties。然后通過Props的etValue方法來調用屬性值,這個方法通常返回一個字符串的值。

分區

  分區和INI文件的分區非常相似。在Props中,分區僅表示前綴相同的一組鍵,這組鍵直到分區結尾或者文件結尾。

  分區名稱已[開頭,以]結尾。屬於該分區的屬性在分區的頭部之后。分區名稱將作為前綴加到分區屬性中。分區以空的[]結尾或者新的分區開始或者到文件尾部。

示例如下:

[users.data]
weight = 49.5
height = 87.7
age = 63
[]
comment=this is base property

下面的和上述示例等同:

users.data.weight = 49.5
users.data.height = 87.7
users.data.age = 63
comment=this is base property

因此,分區可以縮短文件,從而使文件更可讀。

Profiles

通常情況下,一個應用有不同的環境,因此要求不同組別的屬性。例如web應用的測試環境、發布環境。一種組織這些屬性的方法是定義不同的profile,在這些profile里同樣的鍵有不同的值。

Props支持屬性的Profile。Profile定義在鍵名內:profile名稱以<>包裝。一個可以可以有一個或者多個profile定義。同樣,profile可以定義在鍵名的任意地方,甚至在單詞的中間;然而,最好還是把它放到鍵名的尾部。

沒有profile的屬性是基於屬性的,若檢索特定profile的屬性失敗,將會檢查基本的屬性。

profile可以看着相同屬性組的一個“不同的視圖”或者“快照”。示例:

db.port=3086

db.url<develop>=localhost
db.username<develop>=root

db.url<deploy>=192.168.1.101
db.username<deploy>=app2499

在上面的示例中,定義了3個鍵,兩個鍵擁有兩個不同的profile(develop/deploy)且沒有基本的值。

上文提到,分區是一個鍵的前綴定義,並且profile可以定義在鍵名的任意地方,因而分區名稱也可以包含profile定義,上述的示例可以改造如下:

db.port=3086

[db<develop>]
url=localhost
username=root

[db<deploy>]
url=192.168.1.101
username=app2499

當檢索上述值時,可以指定活躍的profile:

    String url = props.getValue("db.url", "develop");
    String user = props.getValue("db.username", "develop");

注意:一個profile可以同時定義多次。profile的順序非常重要!當鍵定義到多個活躍的profile時,將返回第一個的值(第一個匹配的profile的值)。

你也可以僅僅檢索基本屬性(忽略profile)--使用getBaseValue()方法。基本屬性不屬於任何profile。

默認的活躍profile

通常,在一個應用的生命周期中,只有一組profile是活躍的。不需要每次在調用getValues()時都傳遞此活躍的profile。Props支持在外部定義這個所謂的活躍profile,這個定義在加載屬性的props文件中。

在使用getValue(String)檢索屬性時,活躍的profile就是默認的profile。活躍profile以@profiles的特殊屬性鍵定義。例如:

key1=hello
key1<one>=Hi!

@profiles=one

則下面的java代碼:

String value = props.getValue("key1");

將會返回值“Hi!”,因為活躍profile是"one".

活躍profile也可以通過java代碼設置,方法是:setActiveProfiles().

內部profile

  有這樣一種場景:兩個或者多個profile共享大部分配置,而只有很少一部分屬性是不同的。為避免在每個profile中重復定義所有的屬性,可以使用內部profile定義哪些不同的屬性。Props首先檢索內部profile的鍵,然后檢索基本屬性,示例如下:

key1<one>=Hi!
key2<one>=...
....
key100<one>=...

key1<one.two>=Hola!

上述示例定義了兩個profiles,第一個名稱為"one",包含了100個鍵值對。第二個profile是一個名稱為one.two的內部profile。它包含一個屬性(key1)---但上層profile所有屬性都是可用的!當使用java代碼調用上述屬性:props.getValue("key1", "one.two")時將會怎樣呢?

Props將會

  在內部名為one.two的profile中檢索屬性

  如果沒有找到,Props檢查上一層的profile:one。

  如果還檢索不到,沒有更上一層的profile了,Props檢索基本屬性。

內部profile可用有很多層。

Props最大的優點是支持宏。宏是一些鍵值的引用,別的鍵可用使用該值。宏以{}包裝。示例如下:

key1=Something ${foo}
...
foo=nice

key1的值是“Something nice”。宏可用引用任意存在的屬性鍵,不管它們定義在哪里。

同樣也支持嵌套的宏,示例如下:

key1=**${key${key3}}**
key3=2
key2=foo

key1的值是"**foo**".

宏和profile

宏通常使用當前活躍或者提供的profile來解析。若當前的profile改變了,宏的值通常也會改變。

這種行為由標志位useActiveProfilesWhenResolvingMacros來控制。例子如下:

root=/app
root<foo>=/foo
data.path=${root}/data

data.path的值在profile設置為active時是多少?因為foo是活躍的,root的值變為/foo,因此data.path的值為/foo/data.

若我們關閉所有的profile而只使用基本屬性,data.path的值時/app/data.

也可以顯示的設置宏的profile:

root=/app
root<foo>=/foo
data.path=${root<foo>}/data

上述例子中,宏root將一直使用foo profile而不管當前選定的profile,因而data.path的值將一直是"/foo/data".

多行值

多行的值可以通過三引號定義。中間的都看做值:

email.body='''
    Hello $n,

    welcome!
'''

注意:多行的值的空白將不會對剪短!因此上述示例中的值將包含5行。

遍歷和鍵的順序

Props中的鍵是有順序的!因此可以根據屬性文件中鍵的順序遍歷所有的鍵。不用如下代碼:

foo.1=value1
foo.2=value2
...

你可以遍歷props如下:

 Props props = ....
 Iterator<PropsEntry> it = p.iterator();

遍歷的順序和props定義的順序一致。

更進一步,可以通過增加profile來過濾檢索或者/和分區遍歷。你可以這樣寫:

    Iterator<PropsEntry> it = p.entries()
            .section("one.two")
            .profile("prof1", "prof2")
            .iterator();

上述代碼僅僅遍歷給定分區和給定profile的屬性。

由於引入了profile,可以將一個鍵定義在屬性文件的多個地方。例如,你可以為兩個不同的profile定義一個特定的值。在這種情況下,將不能確定鍵的正確順序:是第一個檢索到的鍵還是它所在位置獲取的值?你可以通過使用skipDuplicatesByValue和skipDuplicatesByPosition()來控制。

復制操作符

假定你有一定數量的屬性,即默認情況下,和不同種類的數目一樣,示例如下:

com.jodd.action1=value1
com.jodd.action2=value2
...
org.jodd.action1=value1
org.jodd.action2=value2
...
net.jodd.... # etc

Props支持你使用復制操作符(<=)來最小化重復的屬性,上述屬性可以寫成如下形式:

[actions]
action1=value1
action2=value2
...

[]
org.jodd <= actions

[com]
jodd <= actions

[net.jodd]
<= actions

上述示例顯示了使用復制操作的三種不同方法,沒有使用分區,使用部分分區和完全使用分區。使用這三種方法的哪一種都可以,你可以任意選擇一種。

注意:復制的值設置為宏,因此上述所有復制的屬性也等同於:

org.jodd.action1=${actions.action1}
com.jodd.action1=${actions.action1}
....

配置

 使用幾種配置設置可以很好的對Props進行調優:

  新行轉義值

    當行結尾符(EOL)需要轉義時,指定一個新的字符串。默認值是空的字符串,故多行的值和單行的值連接起來。如果新行轉義值被設置為,例如"\n"時,多行的值將以多行的形式保存。

  截左側值

    如果需要從左邊剪斷的話,設置此值。

  截右側值

    如果需要從右邊剪斷的話,設置此值。

   新行忽略前面的空白值

    若值分割為多行(以轉義EOL)時需要忽略主要的空白值時定義此值。默認值時true,因此下面的多行屬性:

key1=line1\
     line2\
line3

將被讀成line1line2line3(連接成的)

  跳過空的屬性

    跳過空的屬性的標志位。

  連接重復的屬性

    一旦設置,重復的屬性鍵將不會覆蓋舊的鍵,而是連接並且通過逗號分隔。

  多行值

    默認啟用,利用一種更便利的方式來書寫多行的值,以三引號(和python一樣)來書寫。三引號內的所有字符認作一個值,因此新行不需要轉義。

源碼如下:

/**
     * Value that will be inserted when escaping the new line.
     */
    protected String escapeNewLineValue = StringPool.EMPTY;

    /**
     * Trims left the value.
     */
    protected boolean valueTrimLeft = true;

    /**
     * Trims right the value.
     */
    protected boolean valueTrimRight = true;

    /**
     * Defines if starting whitespaces when value is split in the new line
     * should be ignored or not.
     */
    protected boolean ignorePrefixWhitespacesOnNewLine = true;

    /**
     * Defines if multi-line values may be written using triple-quotes
     * as in python.
     */
    protected boolean multilineValues = true;

    /**
     * Don't include empty properties.
     */
    protected boolean skipEmptyProps = true;

 

參考文獻:

http://jodd.org/doc/props.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM