六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

PASX簡化Java開發

[摘要]你是否曾經編寫了一個程序,卻在復檢的時候發現它的配置過程很不合理?你是否曾經使用過配置文件,卻發現它們不能滿足描述應用程序的需要?你是否為了解決幾個特殊問題而創建過臨時配置補丁,卻把花費更多時間、開發普遍適用方案的希望寄托到了未來? 如果你的回答是肯定的,那么,你和大多數其他Java程序員...
你是否曾經編寫了一個程序,卻在復檢的時候發現它的配置過程很不合理?你是否曾經使用過配置文件,卻發現它們不能滿足描述應用程序的需要?你是否為了解決幾個特殊問題而創建過臨時配置補丁,卻把花費更多時間、開發普遍適用方案的希望寄托到了未來?

如果你的回答是肯定的,那么,你和大多數其他Java程序員一樣幸運,有一些工具能夠幫助你解決這些問題。如果你的回答是否定的,關于屬性文件局限的討論也許能夠讓你信服——還有更好的方法可供使用。

屬性文件是Java編程和運行環境的一個重要組成部分。然而,當一個程序員需要的功能遠遠超過Properties類提供的簡單名字-值對時,他需要有更豐富的表現手法。通常,Java程序員擴展屬性文件的方法是為屬性本身的名字或值(或兩者同時)增加額外的語義信息。很多時候,這種看來有效的方法會使問題越來越復雜。

為說明問題,請利用屬性把一系列的值賦給單個名字。讓我們假定你想要管理一組名稱服務器,可能采用的屬性文件內容如下:

hosts_1=ns.foo.com
hosts_2=ns.bar.com
hosts_3=ns.acme.com


代碼很簡單。改變名字-值對中名字的含義之后,你可以輕松地編寫出把“hosts_”開頭的名字當成“hosts”列表中一個元素的程序。

下面,我們來看看一個更復雜的例子。假設你有同一Bean類InternetHost的兩個不同實例:實例A關聯到一個Web服務器的列表;實例B關聯到一個名稱服務器的列表。要從同一個文件配置這兩個實例,一種可能的方案如下:

name_hosts_1=ns.foo.com
name_hosts_2=ns.bar.com
name_hosts_3=ns.acme.com
web_hosts_1=www.foo.com
web_hosts_2=www.bar.com
web_hosts_3=www.acme.com


這種方法行得通,但總是給人以拼拼湊湊的感覺。如果你還不相信的話,稍微增加一點問題的復雜性:讓這些列表中的某個元素自己也成為一個列表;或者,使得下劃線字符(“_”)在名字-值對中合法。在這些情況下,簡單的屬性文件變得非常復雜。

作為一個細心的讀者,你可能已經發現,InternetHost各個實例的命名方式逐漸模糊。為了把前三個屬性賦值給實例A,把后三個屬性賦值給實例B,你必須用某種與具體實例無關的方法告訴實例它們該用哪一組屬性值。如果用直接編碼的方式,讓實例A尋找以“name_”開頭的屬性,讓實例B尋找以“Web_”開頭的屬性,那么,這兩個實例將不再屬于同一對象類。

最后的例子還顯示出另外一個問題。這就是,如何來調用實例A?簡單地叫它“A”?到哪里去尋找它?它是本地實例還是遠程接口?是否存在指向它的全局靜態引用?如是,如何訪問實例B(或者,那是否是“B”)?

解決這些問題的方案是使用一個組件配置和命名框架。有許多工具能夠幫助你完成這個任務,其中之一就是PASX。PASX是一個源代碼開放的Java工具,它通過XML進行配置,通過JNDI實現命名。PASX框架用XML配置用戶定義的服務、JNDI名稱空間、JDBC連接池、事件樹、工作隊列和系統日志。

PASX利用XML進行配置,因為XML比簡單的屬性列表具有更豐富的描述能力。為了理解為何XML更適合完成這類任務,請再次考慮第一個例子。如果用PASX定義的標記重新描述,則結果應該如下:

<List>
<String>ns.foo.com</String>
<String>ns.bar.com</String>
<String>ns.acme.com</String>
</List>


雖然代碼更加冗長,但它的含義比原來要清楚得多。由于一些列表可能被排序,元素在XML文檔中出現的次序決定了它們在最終數據結構中的次序。屬性文件最終用來構造Properties對象,它的名字必須指示出元素的索引,因為Properties對象直接從Hashtable派生得到。

用XML描述時,第二個屬性示例如下所示:


<List name="name-servers">
<String>ns.foo.com</String>
<String>ns.bar.com</String>
<String>ns.acme.com</String>
</List>
<List name="web-servers">
<String>www.foo.com</String>
<String>www.bar.com</String>
<String>www.acme.com</String>
</List>


還記得示例二之后提出的難題嗎?讓列表中的某個元素成為一個子列表,讓其中一個列表成為元素名字可以包含下劃線的映射結構。下面是它的答案:

<List name="name-servers">
<String>ns.foo.com<String>
<List>
<String>ns1.bar.com</String>
<String>ns2.bar.com</String>
</List>
<String>ns.acme.com</String>
</List>
<Map name="web-servers">
<String name="most_visited">www.foo.com<String>
<String name="most_bytes">www.bar.com</String>
</Map>


在PASX中,組件(一個類或者一組有著密切關系的類)是實現PASXService接口的Java Bean。它們由XML <Service>標記定義,這個標記用來命名組件的單個實例。賦予實例“A”名稱服務器列表以及賦予實例“B”Web服務器列表的XML代碼如下所示:

<Service name="A" class="my.InternetHost">
<List name="hosts">
<String>ns.foo.com</String>
<String<ns.bar.com</String>
<String<ns.acme.com</String>
</List>
</Service>
<Service name="B" class="my.InternetHost">
<List name="hosts">
<String>web.foo.com</String>
<String>web.bar.com</String>
<String>web.acme.com</String>
</List>
</Service>


PASX定義了一系列的標準XML標記,用來聲明List、Map、Integer、String、Boolean等類型的屬性。然而,PASXService類還可以經由名稱空間和XML模式使用它自己的XML標記。XML模式允許組件開發者定義自己的標記,允許XML解析器驗證PASX所定義標記和組件開發者所定義標記的合法性。下面的示例模式定義了一個<Server>標記,它必須有hostName和portNumber屬性。<Server>標記必須作為<Cluster>標記的子元素至少出現一次,但可以出現多次。<Cluster>標記必須作為<ServerFarm>標記的子元素出現至少一次,但可以出現多次。

<?xml version="1.0"?>
<schema xmlns="http://www.w3.org/2000/10/XMLSchema"
xmlns:pce="http://pasx.org/PASX/CUSTOM-EXAMPLE"
targetNamespace="http://pasx.org/PASX/CUSTOM-EXAMPLE" elementFormDefault="qualified" >

<annotation>
<documentation>
A custom schema example to be using with PASX (PCE)
</documentation>
</annotation>

<element name="Server">
<complexType content="empty">
<attribute
name="hostName"
use="required"
type="string"/>
<attribute
name="portNumber"
use="required"
type="positiveInteger"/>
</complexType>
</element>

<element name="Cluster">
<complexType>
<sequence>
<element
ref="pce:Server" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute
name="name"
use="required"
type="string"/>
</complexType>
</element>

<element name="ServerFarm">
<complexType>
<sequence>
<element
ref="pce:Cluster" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute
name="name"
use="required"
type="string"/>
</complexType>
</element>

<element name="PCE">
<complexType>
<sequence>
<element
ref="pce:ServerFarm" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
</complexType>
</element>

</schema>


詳細介紹XML模式文檔(XSD)的構造方法已經超出了本文的范圍。重要的是必須認識到,PASXService組件的開發者可以使用一組定制標記。更妙的是,開發者無需編寫任何驗證代碼,就可以確保XML不僅格式良好而且合法(這一切由解析器完成)。下面聲明的<Service>標記用到了前面的模式:

<Service
class="org.pasx.examples.CustomConfigExample"
name="examples.customConfigExample" >

<pce:PCE xmlns="http://pasx.org/PASX/CUSTOM-EXAMPLE"
xmlns:pce="http://pasx.org/PASX/CUSTOM-EXAMPLE"
xsi:schemaLocation="http://pasx.org/PASX/CUSTOM-EXAMPLE /org/pasx/examples/custom-example.xsd" >

<ServerFarm name="farm0">
<Cluster name="cluster0">
<Server hostName="app0.foo.com" portNumber="8080" />
<Server hostName="app1.foo.com" portNumber="8080" />
</Cluster>
<Cluster name="cluster1">
<Server hostName="app2.foo.com" portNumber="8080" />
<Server hostName="app3.foo.com" portNumber="8080" />
</Cluster>
</ServerFarm>
<ServerFarm name="farm1">
<Cluster name="cluster0">
<Server hostName="app4.foo.com" portNumber="8080" />
<Server hostName="app5.foo.com" portNumber="8080" />
</Cluster>
<Cluster name="cluster1">
<Server hostName="app6.foo.com" portNumber="8080" />
<Server hostName="app7.foo.com" portNumber="8080" />
</Cluster>
</ServerFarm>

</pce:PCE>

</Service>


PASXService類如何使用XML配置信息實際上由類的開發者決定。在配置類的時候,它通過configure方法處理聲明它的XML元素(<Service>)。configure方法的特征如下:

public void configure(org.jdom.Element config,
Context context, ServiceManager caller)


注意Element參數是一個對JDOM Element的引用,而不是一個DOM Element的引用。JDOM比DOM更適合Java處理。但是,如果你需要DOM版本,JDOM包提供了轉換它們的方法。使用定制元素時,類的開發者必須使用JDOM API訪問解析后的XML。然而,由于使用了XML模式,類開發者要關心的只是如何使用JDOM數據結構中的信息,但無需編寫代碼去驗證數據結構的合法性(例如,<Cluster>元素只包含<Server>元素)。

如果PASXService的開發者決定只用PASX定義的XML標記,且遵從Java Bean獲取和設置Bean屬性的模式,那么,他可以使用一個稱為XMLBeanUtil的工具類。這個類利用Bean的“內省”機制,實現Bean屬性和PASX所定義XML標記之間的匹配和賦值。它能夠讓代碼編寫變得非常輕松。例如:

public void configure( Element config,
Context context, ServiceManager caller )
{ xbu = new XMLBeanUtil( context ); xbu.populate( config, this );
}


如果某個PASXService組件由一組關系密切的小型Java類構成,populate方法可能被多次調用。請考慮下面這個屬性:

<String name="lastName">Bushaw</String>


對于這個XML片斷,為了把lastName屬性賦給兩個不同的Bean,populate方法可以被多次調用:

Person father = new Person();
Person mother = new Person(); xbu.populate( config, father ); xbu.populate( config, mother );


使用XML模式和定制標記的一個優點是對預計配置的驗證。換句話說,你可以編寫一個XML模式,使得對于給定的<Host>標記,PortNumber和ipAddress屬性也必須同時指定。定義PASX標記集的模式不能這么做,因為它不了解各個PASXService組件所需的語義信息。然而,XMLBeanUtil能夠跟蹤哪些Bean屬性已經設置、哪些還沒有設置,而且允許在配置的時候指定一系列對屬性的約束。PASXService類的編寫者可以根據愛好、需要和方便程度,選用任意一種方法。

XMLBeanUtil把Bean屬性分成三類:Property(普通屬性),Dependent(依賴),Compliment(遵從)。如果這三類屬性的Java類型是List或Map,則它們都可以作為一個集合體設置。如果屬性已經有值且被視為一個集合體,配置中的List或Map被加入到現有的屬性;如果它不被視為一個集合體,則配置中的List或Map將取代屬性值。下面的configure方法實例示范了它的用法。

public void configure( Element config,
Context context, ServiceManager caller )
{ xbu = new XMLBeanUtil( context ); xbu.addProperty( "hostName",
"Host Name Of Mythical TCP Service",
true, false ); xbu.addDependent( "portNumber",
"Port Number Of Mythical TCP Service",
"hostName", false ); xbu.addCompliment( "serverFarm",
"Back-end Server Farm",
"nameServers", true ); xbu.addCompliment( "nameServers",
"Name Servers To Resolve Against",
"serverFarm", true ); xbu.addProperty( "person",
"Person", true, false ); xbu.addProperty( "binaryThing",
"The binary input stream",
true, false ); xbu.addProperty( "props",
"Example Protomatter Properties",
true, false ); xbu.addProperty( "xml",
"An example JDOM XML Document",
true, false ); xbu.populate( config, this );
}


傳遞給addProperty、addDependent、addCompliment方法的屬性描述用于錯誤信息。XMLBeanUtil類的checkService方法將檢查屬性是否已經正確設置。如果還沒有,它將拋出一個異常,在錯誤信息中利用屬性的描述。要查看完整的實例,請參考BeanServiceExample類。

作為一個細心的讀者,你可能已經發現,此前的所有例子都沒有提到JNDI。即使是<Service>標記的name屬性也沒有提到任何有關JNDI的內容。因此,你也許會疑惑PASX的命名部分如何使用JNDI。

默認情況下,PASX使用內存中的稱為PAS的扁平JNDI服務提供者(它來自底層的Protomatter包)。這個服務提供者僅僅是一個帶有JNDI接口的Hashtable。其他JNDI服務提供者可以通過URL命名指定甚至一起使用。因此,從一個RMI注冊器或者一個LDAP服務器(也就是rmi://localhost/creditCardAuthorizer或ldap://foo.com/uid=littlek,dc=foo,dc=com)指定一個URL是可能的。

在服務中使用JNDI的默認JNDI動作是bind。然而,通過可選的action屬性,動作也可以指定為rebind或lookup。bind動作嘗試把服務放入JNDI目錄,但如果目錄中已經包含具有指定名字的服務,則操作失敗。rebind動作和bind動作基本相同,例外之處在于,rebind動作將覆蓋已經存在的服務入口。無論是bind還是rebind動作,PASX都會實例化PASXService對象。但對于lookup動作,對象從JNDI目錄提取得到。

<Service>標記中還有兩個屬性可能被用到:preRebind和postRebind。preRebind屬性指定一個名字或一個URL,它被用于在配置生效之前把對象重新綁定到JNDI目錄。類似地,postRebind屬性具有同樣的功能,但不同的是,它在配置之后出現。

結合運用這些功能使得配置文件能夠輕松地完成一些有用的任務。它如,你可以從LDAP服務器“反串行化”一個對象,通過XML配置它,然后把它放入內存,使得其他對象能夠訪問它。考慮這樣一個例子:某些業務過程的終止日期駐留在LDAP服務器上。下面的標記代碼從LDAP服務器獲取終止日期,根據當前的時區設置它,然后把它放入內存:

<Service
name="ldap://foo.com/cn=expirationDate,o=foo.com"
class="my.UtilityDate"
action="lookup" postRebind="pas:expirationDate">
<Integer name="timeZone" value="-6"/>
</Service>


現在,其他服務可以通過<NamedService>標記引用這個經過配置的服務了。例如,考慮一個降價銷售廣告服務,它必須知道降價銷售活動何時終止:

<Service
name="pas:oriellySale"
class="my.SalesAdBanner">
<NamedService name="endDate" serviceName="pas:expirationDate"/>
</Service>


這并不是什么魔術。<NamedService>標記只不過是根據serviceName屬性,讓PASX執行一個JNDI查找,然后把結果放入名為endDate的Bean屬性。盡管如此,這種在配置時把一個對象連接到另一個對象的方法很有用。如果你開始使用這種方式,它可能改變你設計類的習慣。

PASX包含了各種各樣用于JNDI的工具。其中包括狀態和對象工廠,用于在目錄中串行化和保存對象狀態;還有兩個服務提供者。請參考JavaDoc了解有關它們的更多信息。

另外,PASX還包含一個完整的實例包,包括源代碼、JavaDoc和伴隨PASX的配置文件。這些實例從簡單的配置示例開始,涵蓋所有范圍,直至多個JNDI目錄的混合應用。請參考JavaDoc org.pasx.examples。

我希望,本文所介紹概念的優點已經讓你確信:下一次坐下來編寫程序時,不管其規模大小,你有必要考慮一下配置的需求和方法問題。本文所介紹的概念屬于中心主題,但PASX還包含本文沒有介紹的許多其他功能。PASX為完成許多任務提供了大量標準的服務和管理器,甚至還有一個Servlet框架,用戶可以通過這個Servlet框架管理服務和管理器。

最后,有一個稱為Potomac的工程。Potomac是一個基于PASX的源代碼開放Java軟件的集合。有了Potomac,所有你必須做的就是解開壓縮文件,這樣你就有了使用PASX時所有必須的Java組件,比如Protomatter和JDom,還有一些快速啟動腳本和入門學習用的配置文件。



相關文章

主站蜘蛛池模板: 日产国语一区二区三区在线看 | 日韩欧美三级视频 | 五月婷婷丁香花 | 一本草久| 亚洲男人天堂视频 | 亚洲久草视频 | 午夜亚洲一区二区福利 | 一区二区三区视频网站 | 午夜影视在线观看免费完整高清大全 | 天天操天天操天天射 | 色婷婷99综合久久久精品 | 青青草原播放器 | 深夜久久 | 午夜在线观看免费观看大全 | 中文字幕在线视频不卡 | 在线免费视频你懂的 | 日本一区二区不卡视频 | 亚洲欧美日韩国产综合久 | 欧美综合图区亚洲综合图区 | 亚洲高清视频在线 | 天美传媒一区二区三区 | 综合丁香 | 亚洲欧洲eeea在线观看 | 欧美一区二区三 | 亚洲欧洲eeea在线观看 | 四虎午夜影院 | 天天干夜夜爽天天操夜夜爽视频 | 日韩欧美色视频在线观看 | 午夜毛片不卡高清免费 | 亚洲日韩中文字幕在线播放 | 日韩一区二区免费看 | 婷婷激情小说网 | 中国女人特级毛片 | 日本一区二区三区免费观看 | 天堂精品| 天堂网址| 天天艹天天操 | 欧美一级艳片视频免费观看 | 日韩美女在线播放 | 日本道精品一区二区三区 | 日产精品一二三四区国产 |