|
2006年5月25日
System.getProperty()參數(shù)大全
java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path
java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX)
path.separator Path separator (":" on UNIX)
line.separator Line separator ("\n" on UNIX)
user.name User's account name
user.home User's home directory
user.dir User's current working directory
服務(wù)類型
在axis中有4中服務(wù)類型
RPC服務(wù)采用soap rpc的標(biāo)準(zhǔn),and also the SOAP "section 5" encoding.
Document 服務(wù)沒有采用任何編碼(所以你在組裝時(shí)不會(huì)看到復(fù)雜對(duì)象的序列化以及soap-style數(shù)組),但是仍然作了xml和java對(duì)象的互映射。
Wrapped服務(wù)和Document服務(wù)類似
Message 服務(wù)接受和返回soap Envelope中的任意的xml而不需要mapping/data得榜定。如果你想處理來(lái)自外部的原始的xml,可以采用Message 服務(wù)。
RPC服務(wù)
這個(gè)服務(wù)是axis默認(rèn)的服務(wù)。我們?cè)谇懊娴睦又袑懙木褪莚pc服務(wù)。<service ... provider="java:RPC"> 。rpc服務(wù)遵從soap rpc規(guī)范和編碼規(guī)則,意味著來(lái)自rpc服務(wù)的xml將類似上面例子中的“echoString”--每個(gè)rpc調(diào)用被模塊化為一個(gè)外部元素,匹配操作名稱,并包含了很多內(nèi)部元素,每一個(gè)都是操作的一個(gè)參數(shù)。axis將把這些xml轉(zhuǎn)化為java對(duì)象,配送給你得服務(wù),并將序列化來(lái)自服務(wù)的java對(duì)象為xml.因?yàn)閞pc服務(wù)默認(rèn)采用soap section 5規(guī)則,對(duì)象將會(huì)通過"multi-ref" 序列化來(lái)編碼。
Document / Wrapped 服務(wù)
這2個(gè)服務(wù)很類似,都不需要用soap編碼來(lái)處理數(shù)據(jù)。他就是一個(gè)普通的xml格式。無(wú)論哪種情況,axis還是對(duì)他們做了xml到j(luò)ava得榜定,所以你最終處理的還是java對(duì)象,而不是xml結(jié)構(gòu)的字符串。
下面的例子來(lái)說(shuō)明他們2個(gè)之間的區(qū)別。
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<soap:Body>
<myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
<item>SK001</item>
<quantity>1</quantity>
<description>Sushi Knife</description>
</myNS:PurchaseOrder>
</soap:Body>
</soap:Envelope>
相關(guān)的PurchaseOrder類型定義如下:
<schema targetNamespace="http://commerce.com/PO">
<complexType name="POType">
<sequence>
<element name="item" type="xsd:string"/>
<element name="quantity" type="xsd:int"/>
<element name="description" type="xsd:string"/>
</sequence>
</complexType>
<element name="PurchaseOrder" type="POType"/>
</schema>
對(duì)于一個(gè)document服務(wù)來(lái)說(shuō),他將對(duì)應(yīng)到這樣的方法
public void method(PurchaseOrder po)
換句話說(shuō),整個(gè)PurchaseOrder元素將被處理為一個(gè)單一的對(duì)象,包含3個(gè)屬性。
而對(duì)于wrapped服務(wù)來(lái)說(shuō),他對(duì)應(yīng)于下面的方法
public void purchaseOrder(String item, int quantity, String description)
注意到,在wrapped中,PurchaseOrder元素被映射為代表了一個(gè)方法。他的參數(shù)就是他的那些元素。
他們?cè)趙sdd得使用如下
<service ... style="document"> for document style
<service ... style="wrapped"> for wrapped style
Message 服務(wù)
當(dāng)你需要處理純xml而不是java對(duì)象時(shí),你將會(huì)用到這種服務(wù)。
message服務(wù)的方法有4中簽名
public Element [] method(Element [] bodies);
public SOAPBodyElement [] method (SOAPBodyElement [] bodies);
public Document method(Document body);
public void method(SOAPEnvelope req, SOAPEnvelope resp);
發(fā)布service
有2種發(fā)布方式,一種是實(shí)例發(fā)布,一種是描述符發(fā)布
實(shí)例發(fā)布很簡(jiǎn)單
把我們的java源文件拷貝到axis目錄下,改擴(kuò)展名為jws
然后就可以直接訪問了,例如:
java samples.userguide.example2.CalcClient -p8080 add 2 5
他將調(diào)用add方法,傳遞的2個(gè)變量分別為2和5。
很顯然,第一種方法有很多弊端,比如需要源文件,不能有包路徑等等
描述符發(fā)布
一個(gè)最簡(jiǎn)單的例子如下:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="MyService" provider="java:RPC">
<parameter name="className" value="samples.userguide.example3.MyService"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
一個(gè)服務(wù)是一個(gè)targeted chain ,可能包含下面的一些或者全部:請(qǐng)求Handler,pivot Handler 支點(diǎn)Handler,響應(yīng)Handler。支點(diǎn)hander在服務(wù)中叫做provider,在例子中我們的provider是java:RPC,他被axis內(nèi)嵌,代表了Java RPC service,具體的類是org.apache.axis.providers.java.RPCProvider.
我們告訴RPCProvider 我們要調(diào)用的服務(wù)MyService,并以參數(shù)的形式告訴他具體的目標(biāo)以及可以被調(diào)用的方法。
我們也可以給我們要調(diào)用的對(duì)象設(shè)置作用范圍scope,和servlet的scope一樣,有request,session,application.
我們需要把這個(gè)描述符定義的內(nèi)容告訴應(yīng)用服務(wù)器才能真正提供我們需要的服務(wù)。
如果已經(jīng)部署axis到tomcat,我們可以這樣發(fā)布
org.apache.axis.client.AdminClient deploy.wsdd
這樣我們的服務(wù)就可以通過soap來(lái)訪問了
測(cè)試一下
java samples.userguide.example3.Client
-lhttp://localhost:8080/axis/services/MyService "test me!"
可以通過下面來(lái)查看所有已經(jīng)部署的服務(wù)
java org.apache.axis.client.AdminClient list
來(lái)看看更進(jìn)一步的應(yīng)用,使用一下request handler
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<!-- define the logging handler configuration -->
<handler name="track" type="java:samples.userguide.example4.LogHandler">
<parameter name="filename" value="MyService.log"/>
</handler>
<!-- define the service, using the log handler we just defined -->
<service name="LogTestService" provider="java:RPC">
<requestFlow>
<handler type="track"/>
</requestFlow>
<parameter name="className" value="samples.userguide.example4.Service"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>
這個(gè)例子會(huì)在客戶端掉用LogTestService的時(shí)候,先調(diào)用samples.userguide.example4.LogHandler作記錄操作
遠(yuǎn)程管理
默認(rèn)狀態(tài)下,axis只允許在axis部署的機(jī)器上使用管理請(qǐng)求,如果希望在其他的機(jī)器上進(jìn)行管理操作可以參照下面的例子
<service name="AdminService" provider="java:MSG">
<parameter name="className" value="org.apache.axis.util.Admin"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="enableRemoteAdmin" value="true"/>
</service>
注意,這樣配置需要作必要的安全配置
原文見:
http://blog.csdn.net/huabingl/archive/2008/02/12/2089145.aspx
說(shuō)dtree是使用最廣泛的目錄樹javascript應(yīng)該也不為過.這得意于他簡(jiǎn)單的使用方式和良好的結(jié)構(gòu).
可能這里是他最早的發(fā)源地之一http://www.destroydrop.com/javascripts/tree/
上面有他的示例和api文檔.
dtree使用簡(jiǎn)單,使用起來(lái)就是引入一個(gè)dtree.js,dtree.css和一些小圖片文件。.在需要顯示樹的地方,插入類似下面的代碼
可以參照這里做些配置,觀看效果.可選的選項(xiàng)有folderLinks, useIcons, useLines, useSelection, useStatusText, closeSameLevel
http://www.destroydrop.com/javascripts/tree/example/
你可以放置radio或者checkbox在相應(yīng)的節(jié)點(diǎn)上,或者在節(jié)點(diǎn)上加上鏈接.
原文見
http://blog.csdn.net/huabingl/archive/2008/02/12/2088711.aspx
opencms列表顯示
先準(zhǔn)備要顯示的數(shù)據(jù)。比如在站點(diǎn)下建立一個(gè)sports目錄,里面以news的格式放入一些xmlpage.
注意給這些xmlpage準(zhǔn)備好detail顯示頁(yè)面。
<%@ taglib prefix="cms" uri="
<%@ page import="java.util.*"%>
<%@ page import="org.opencms.jsp.*"%>
<%
String sPageIndex=request.getParameter("pageIndex");
int iPageIndex=1;
if(sPageIndex!=null){
iPageIndex=Integer.parseInt(sPageIndex);
}
pageContext.setAttribute("pageIndex", iPageIndex+"");
%>
<cms:contentload collector="allInFolderDateReleasedDesc" param="/myfirstsite/sports/%(number)_news.html|news" pageIndex="%(pageContext.pageIndex)" pageSize="2">
<cms:contentinfo var="contentInfo" scope="request" />
<a href="<cms:link><cms:contentshow element="%(opencms.filename)"/></cms:link>" target=_blank><cms:contentshow element="Title"/> </a>
<%out.println("---");%>
</cms:contentload>
<%
CmsContentInfoBean info = (CmsContentInfoBean)request.getAttribute("contentInfo");
int totalNum=info.getResultSize();
%>
共<%=totalNum%>條數(shù)據(jù),當(dāng)前第<%=info.getPageIndex()%>/<%=info.getPageCount()%>
<a href="list_taglib?pageIndex=<%=info.getPageNavStartIndex()%>">第一頁(yè)</a>
<a href="list_taglib?pageIndex=<%=(info.getPageNavStartIndex()-1)>0?(info.getPageNavStartIndex()-1):1%>">上一頁(yè)</a>
<a href="list_taglib?pageIndex=<%=(info.getPageNavStartIndex()+1)>info.getPageCount()?info.getPageCount():(info.getPageNavStartIndex()+1)%>">下一頁(yè)</a>
<a href="list_taglib?pageIndex=<%=info.getPageNavEndIndex()%>">最后頁(yè)</a>
上面的例子力求盡可能少的使用標(biāo)簽。主要使用了CmsContentInfoBean ,CmsJspXmlContentBean ,I_CmsXmlContentContainer(CmsJspTagContentLoad )等多個(gè)對(duì)象。分頁(yè)的關(guān)鍵在CmsContentInfoBean 和 CmsJspTagContentLoad的關(guān)系上。
參考資料:
http://www.javaedu.com/bbs/viewthread?thread=128
http://wangyi878750.blog.sohu.com/41725191.html
http://l--w.blog.sohu.com/47996664.html
http://wangyi878750.blog.sohu.com/41378072.html
Ruby之Blocks,Iterator -------讀《Programming Ruby 2nd》
Ruby是”一種用于迅速和簡(jiǎn)便的面向?qū)ο缶幊痰慕忉屝阅_本語(yǔ)言”;這意味著什么? 解釋性腳本語(yǔ)言:
- 有直接呼叫系統(tǒng)調(diào)用的能力
- 強(qiáng)大的字符串操作和正則表達(dá)式
- 開發(fā)中快速回饋
迅速和簡(jiǎn)便:
- 無(wú)需變量聲明
- 變量無(wú)類型
- 語(yǔ)法簡(jiǎn)單而堅(jiān)實(shí)
- 自動(dòng)內(nèi)存管理
面向?qū)ο缶幊?/p>
- 任何事物都是一個(gè)對(duì)象
- 類,繼承,方法,等等
- 單態(tài)方法
- 模塊糅合
- 迭代器和閉包(closures)
以及:
- 多精度整數(shù)
- 異常處理模式
- 動(dòng)態(tài)裝載
- 線程
如果你對(duì)上面的那些概念還不熟悉,繼續(xù)讀,別擔(dān)心.Ruby的箴言是”迅速和簡(jiǎn)便”.
<script language="javascript"> //定義全局變量,用于清理工作 var word; var doc; function editFile(){ //調(diào)用word控件 word= new ActiveXObject("Word.Application"); //屏蔽“另存為”按鈕 word.CommandBars("File").Controls(5).Enabled= false; word.CommandBars("File").Controls(5).visible= false; //屏蔽"另存為網(wǎng)頁(yè)"按鈕
word.CommandBars("File").Controls(6).Enabled= false; word.CommandBars("File").Controls(6).visible= false;
word.visible = true; // word.activate(); try{ //打開文件 doc=word.Documents.Open(" //痕跡保留 word.ActiveDocument.TrackRevisions =true; //切換成web視圖 word.ActiveDocument.ActiveWindow.View.Type=3 }catch(e){ alert(e.message); }; } function myfinalize(){ //文檔保存 doc.save(); //文檔關(guān)閉 doc.close(); //把屏蔽的功能打開 word.CommandBars("File").Controls(5).Enabled= true; word.CommandBars("File").Controls(5).visible= true; //word退出 word.quit(); } //參考文檔 http://bbs.hidotnet.com/712/ShowPost.aspx
原文:
http://blog.csdn.net/huabingl/archive/2008/02/11/2088477.aspx
摘要: AXIS User Guide(1) 閱讀全文
摘要: Sliding into WebDAV 閱讀全文
摘要: HibernateTemplate方法索引 閱讀全文
最近又遇到個(gè)對(duì)js取名不帥導(dǎo)致錯(cuò)誤的問題,特開此貼,以示警戒: 不要把自己的js函數(shù)取成close(),open(),start()之類的名字!!
window得resizeto和resizeby方法對(duì)模式窗口無(wú)效。
最近研究了一下webdav,關(guān)于webdav的詳細(xì)信息可以在 google上搜索或者參看官方網(wǎng)站 筆者簡(jiǎn)單的嘗試了它下面的slide和mod_dav. slide是jakarta下面的子項(xiàng)目,分為服務(wù)端和客戶端.個(gè)人認(rèn)為服務(wù)端是專門為tomcat定做的一個(gè)webdav實(shí)現(xiàn).關(guān)于slide,javaeye上有些討論,可以參考http://www.javaeye.com/t/5267.html.本人涉入的不是很深,中文問題讓我碰到了,slide提供2中存儲(chǔ)方式,文件形式和數(shù)據(jù)庫(kù)形式,限于時(shí)間,筆者沒有對(duì)數(shù)據(jù)庫(kù)形式進(jìn)行測(cè)試.slide的工作目錄默認(rèn)在服務(wù)器bin目錄下. 用mod_dav來(lái)實(shí)現(xiàn)相比就簡(jiǎn)單多了,如果你熟悉apache httpserver,應(yīng)該很容易搞定.http://www.webdav.org/mod_dav/ 上的有部分資料.可以根據(jù)http://www.webdav.org/mod_dav/install.html 的講解來(lái)配置.apache server1.3以后(包括1.3)在發(fā)布的時(shí)候都自帶了mod_dav包.需要做的就是加載和配置它. LoadModule dav_module libexec/libdav.so AddModule mod_dav.c 筆者在配置的時(shí)候由于沒有認(rèn)真看文檔,犯了個(gè)小小的錯(cuò)誤.所以注意下面的文字: "In the following example, the DAV lock database will be stored in the /usr/local/apache/var directory (which must be writable by the server process). The file's name will be DAVLock when mod_dav needs to create it. (actually, mod_dav will create one or more files using this file name plus an extension)
DAVLockDB /usr/local/apache/var/DAVLock" 然后你需要配置一個(gè)webdav的工作目錄,由于訪問apache服務(wù)的用戶會(huì)默認(rèn)是nobody用戶,所以你至少得讓工作目錄對(duì)nobody可讀寫.在目錄的定義中加入DAV on這樣的屬性就 ok了 eg: "Alias /pages /home/www/davhome <Location /pages> DAV On </Location> " 測(cè)試webdav 安裝完webdav后,你可以做簡(jiǎn)單的測(cè)試: IE瀏覽器-〉文件-〉打開,然后輸入配置的url,客戶端API. 如果是 java可以 采用slide的客戶端.(php用戶咋辦?). 這個(gè)最新的客戶端使用的是最新的jdom,注意哦.. 參考資料: http://www.uplinux.com/www/net/02/131.shtml
?? mvnforum是一個(gè)開源的論壇軟件.網(wǎng)址如下: http://sourceforge.net/projects/mvnforum/ ?? 本文主要研究它的權(quán)限部分,以作為使用借鑒. ?? 這里有篇中文的文檔,以作參考: ? http://www.cn-java.com/target/news.php?news_id=3298
權(quán)限部分的UML圖如下: ?? 
數(shù)據(jù)流程: 1,系統(tǒng)從OnlineUserManager這個(gè)入口進(jìn)入.這個(gè)部件有個(gè)Map用來(lái)存儲(chǔ)當(dāng)前的非過期用戶。OnlineUserManager會(huì)先根據(jù)當(dāng)前時(shí)間和最后一個(gè)用戶的請(qǐng)求時(shí)間做對(duì)比,檢查是否有刷新過期用戶的必要,如果超過所設(shè)置的時(shí)間,那么先更新Map。然后OnlineUserManager根據(jù)提供的用戶的 sessionid和username在這個(gè)Map中查找。如果找到,則刷新該用戶的最后一次訪問時(shí)間;否則,OnlineUserManager調(diào)用OnlineUserFactory部件創(chuàng)建該OnlineUser,并把這個(gè)OnlineUser存入Map之中。 判對(duì)用戶是否過期的原理是:從OnlineUser的OnlineUserAction中取出最后一次的訪問時(shí)間和當(dāng)前時(shí)間做對(duì)比. 2,OnlineUserFactory負(fù)責(zé)創(chuàng)建OnlineUser并為該OnlineUser提供完整的權(quán)限信息.OnlineUser包括3大部分信息,一部分是用戶的基本信息,一部分是用戶的權(quán)限信息,一部分是用戶的在線信息.在線信息由OnlineUserManager負(fù)責(zé)管理,其他2部分信息由OnlineUserFactory從持久層獲得. 獲得權(quán)限信息并把它設(shè)置到OnlineUser部件上,提供給OnlineUserManager管理. 3.CNMPermissionFactory類似我們常說(shuō)的service.主要負(fù)責(zé)和持久層通信,最終返回一個(gè)CNMPermission部件供OnlineUserFactory合成OnlineUser部件.在下面的章節(jié)里,筆者會(huì)對(duì)他細(xì)化討論. 權(quán)限結(jié)構(gòu): 用來(lái)實(shí)現(xiàn)用戶權(quán)限的主要的是CNMPermission接口和他是2個(gè)子類AbstractPermission和CNMPermissionImpl.CNMPermission接口負(fù)責(zé)定義權(quán)限有關(guān)的常量和對(duì)外API.AbstractPermission設(shè)置了保存權(quán)限信息的變量并實(shí)現(xiàn)了CNMPermission接口中定義的抽象方法,因此,筆者把這個(gè)抽象類叫做鑒權(quán)類.CNMPermissionImpl 則負(fù)責(zé)對(duì)AbstractPermission使用的變量進(jìn)行設(shè)值,因此,筆者稱之為賦權(quán)類. 先看看AbstractPermission的結(jié)構(gòu)。這里涉及到這么幾個(gè)概念:全局權(quán)限,特定權(quán)限,單個(gè)權(quán)限,組合權(quán)限。 全局權(quán)限用true/false來(lái)設(shè)置。 特定權(quán)限是指某一個(gè)動(dòng)作所作用的不同的對(duì)象。比如:某用戶只能將寫操作作用于1,2,4這3個(gè)論壇板塊之上。表示為這個(gè)特定權(quán)限內(nèi)部的ArrayList容器中只有1,2,4三個(gè)編號(hào)。 單個(gè)權(quán)限是指單個(gè)動(dòng)作。比如讀操作。 組合權(quán)限是為了方便設(shè)置提供的對(duì)單個(gè)權(quán)限的組合。比如對(duì)某用戶一次設(shè)置某板塊的“讀”和“發(fā)布”2種權(quán)限。 前2種權(quán)限是一個(gè)緯度的劃分,后2個(gè)是另一個(gè)緯度的劃分。 如何鑒權(quán)? 鑒權(quán)的接口都會(huì)在CNMPermission中定義。對(duì)全局權(quán)限,直接返回對(duì)應(yīng)的標(biāo)志位的值,對(duì)于特定權(quán)限,則先判斷是否特定權(quán)限全開,否,則然后判斷其ArrayList中是否包含對(duì)應(yīng)的對(duì)象編號(hào)。 如何賦權(quán)? 這里要承接到上述數(shù)據(jù)流程的第三步。由CNMPermissionFactory根據(jù)一定先后循序(其實(shí)無(wú)關(guān)順序,因?yàn)椴捎玫臑檎娓采w原則,即持久層返回的權(quán)限都是真值,后面的真值對(duì)前面的真值可覆蓋)從持久層獲得所有的全局權(quán)限和特定權(quán)限。mvnforum只有用戶和角色2種概念(當(dāng)然也可以擴(kuò)展),因此它的順序是:用戶全局全縣-〉用戶特定權(quán)限-〉角色全局全縣-〉角色特定權(quán)限。當(dāng)然無(wú)論哪一部都是對(duì)同一個(gè)CNMPermission進(jìn)行操作。 無(wú)論在設(shè)置全局權(quán)限還是特定權(quán)限的時(shí)候都可能會(huì)遇到所定義的組合權(quán)限。具體的組合權(quán)限拆分是由CNMPermissionImpl來(lái)做的. 相關(guān)的表結(jié)構(gòu): ?? member表,存貯用戶基本信息。 ?? membergroup ,存儲(chǔ)用戶和組(角色)的對(duì)應(yīng)關(guān)系。 ?? groups表,存儲(chǔ)組/角色的基本信息 ?? grouppermission,存儲(chǔ)組/角色的全局權(quán)限,字段為groupid permissionid ?? groupforum,存儲(chǔ)組/角色 的論壇權(quán)限, 字段為groupid ,forum,permissionid ?? memberpermission 存貯用戶的全局權(quán)限,字段為 memberid permissionid ?? memberforum 存貯用戶的論壇權(quán)限,字段為memberid ,forum,permissionid
? 修改于2006/12/16? 晚8時(shí)
? 目前的很多商業(yè)和非商業(yè)的服務(wù)器中間件都默認(rèn)集成了common-log甚至是log4j.因此當(dāng)我門把我們的應(yīng)用發(fā)布在上面的時(shí)候,都會(huì)遇到關(guān)于log方面的問題. ? 1.webshpere下面集成log4j. ? "WebSphere的類裝入器方式有兩種方式:PARENT_FIRST和PARENT_LAST。默認(rèn)值是PARENT_FIRST,這種方式在載入當(dāng)前classpath的類之前先載入其上一級(jí)classloader能夠裝入的類。這是標(biāo)準(zhǔn)的JVM classloader的默認(rèn)策略。如果采用PARENT_LAST,則過程正好相反,即先載入當(dāng)前classpath的類,再載入其上一級(jí)classloader能夠裝入的類,這樣可以用當(dāng)前classpath中更新的類覆蓋其上一級(jí)classloader的相同類。受類裝入器方式影響的classloader包括application classloader、WAR classloader以及共享類庫(kù)的classloader。" ?因?yàn)閣ebsphere在共享類庫(kù)的classloader中有一套common logging,但是確沒有合適配置文件.如果我們把配置正確的log4j.properties文件放在共享類庫(kù)下,我們會(huì)發(fā)現(xiàn)log4j可以運(yùn)行.但還有另外一個(gè)很通用的方式--改變webshpere的類庫(kù)加載順序.我們讓他先加載我們web應(yīng)用所需的類庫(kù).即我們把web應(yīng)用的加栽方式改為PARENT_LAST. ? 哎,盡管我小心的提防,今天還是中招了,在我的配置里,log4j的配置文件只能讀取一次,不能一個(gè)應(yīng)用一個(gè)配置文件.為了讓它加載自己的配置,可以自己寫(或者用spring的)servlet/listener去手動(dòng)加載這個(gè)配置文件. ?2.jboss下面的集成log4j ? 大家可能都曾在為jboss下面配置log4j郁悶過.jboss比webshpere走的還遠(yuǎn).無(wú)論你的項(xiàng)目是否使用了log4j,jboss在自己?jiǎn)?dòng)的時(shí)候就已經(jīng)運(yùn)行他了.也就是說(shuō)在jboss加載自己共享類庫(kù)的時(shí)候,已經(jīng)讀取了自己log4j.xml文件配置.這個(gè)文件在conf中可以找到.如果你需要為你的應(yīng)用單獨(dú)配置一個(gè)catagory,你需要直接在這里配置. ???在webloader裝載應(yīng)用的時(shí)候,如果應(yīng)用中有l(wèi)og4j的包,似乎總出現(xiàn)appender已被占用的問題.筆者把log4j的包連帶應(yīng)用中的log4j配置文件一并移去,世界清凈了. 關(guān)于為了讓應(yīng)用自帶的log4j配置文件生效,有人建議修改 ?<attribute name="Java2ClassLoadingCompliance">false</attribute> 和 ?<attribute name="UseJBossWebLoader">false</attribute> 這兩個(gè)屬性. 3.sunone下面集成log4j ??? 距離上次用SunOne服務(wù)器已經(jīng)好長(zhǎng)時(shí)間了,似乎sunOne的log有些類似jboss,也是一個(gè)服務(wù)器的log集中管理.由于使用的不是很多,暫且在這里站個(gè)位子. 隨手貼點(diǎn)關(guān)于log的信息: http://wiki.apache.org/jakarta-commons/Logging/FrequentlyAskedQuestionshttp://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/0408_baigang/part3.html?
OpenLDAP
快速上手
?? Ben
的項(xiàng)目里面要用到
OpenLDAP,
我的項(xiàng)目里面也要用到
LDAP,
所以這
2
天集中看了一下
LDAP
相關(guān)的內(nèi)容。做了個(gè)筆記,也算是為人類知識(shí)的積累做點(diǎn)或有或無(wú)的貢獻(xiàn)。
?? OpenLDAP
的官方站點(diǎn)是
http://www.openldap.org
。
??????
上面有個(gè)
QuickStart,
我將大致按照這個(gè)來(lái)講解。
一、
安裝
在官方站點(diǎn)上發(fā)布的是
linux/unix
下的
OpenLDAP
源文件,當(dāng)然也很容易找到
windows
系統(tǒng)下的版本。筆者學(xué)習(xí)安裝的就是
windows
版本的。
二、
配置
OpenLDAP
有
2
個(gè)用戶最關(guān)注的配置文件。
一個(gè)是
slapd.conf
,
在他里面定義了最基本的
DN
以及管理員的賬號(hào)和密碼。
另一個(gè)是
LDIF
的文件。在它里面可以配置所有的用戶和組織。
1、?
我們先來(lái)了解
LDAP
的相關(guān)概念。
我們知道
LDAP
的全稱為(
Lightweight Directory Access Protocol
),即輕量級(jí)目錄訪問協(xié)議。
Ldap
是怎樣的一個(gè)結(jié)構(gòu)呢
?用官方的話說(shuō):“
In LDAP, directory entries are arranged in a hierarchical tree-like structure. Traditionally, this structure reflected the geographic and/or organizational boundaries. Entries representing countries appear at the top of the tree. Below them are entries representing states and national organizations. Below them might be entries representing organizational units, people, printers, documents, or just about anything else you can think of..
”他是一個(gè)樹狀的結(jié)構(gòu)。每一個(gè)節(jié)點(diǎn)被稱為一個(gè)
Entry
。這些
Entry
有著有趣的含義。
下面是他的
2
個(gè)實(shí)例。一個(gè)反映了
geographic
,一個(gè)反映了
organizational
。
?????????????????????????????????????????????????????????? 傳統(tǒng)命名
 ?????????????????????????????????????????????????????????? 網(wǎng)絡(luò)命名
我們來(lái)看看個(gè)個(gè)節(jié)點(diǎn)的定義方式。
每個(gè)
Entry
都有一個(gè)自己得一個(gè)標(biāo)示
,我們把他叫
DN(Distinguished Name)
,這個(gè)
dn
包含了一個(gè)
RDN
(
Relative Distinguished Name
)。在上面的第二個(gè)圖例
中,Barbara Jensen的RDN是
uid=babs,他的dn是
uid=babs,ou=People,dc=example, dc=com。
每個(gè)節(jié)點(diǎn)都需要一個(gè)類別
,
這個(gè)類別信息用objectClass來(lái)表示。ObjectClass就是該節(jié)點(diǎn)的schema,他定義了該節(jié)點(diǎn)該有和不該有的屬性。默認(rèn)的objectClass都在schema/core.schema中有定義。如果在你的配置過程中出現(xiàn)了關(guān)于找不到objectClass的問題,您不妨參看一下這里面有沒有你用到的objectClass
. 在schema文件夾下還有其他一些schema文件,你也可以定義自己的schema.想要加載其他的schema,你可以在slapd.conf文件中用include加入.如:include??./schema/core.schema.
為了方便識(shí)別,其實(shí)我們?cè)?span lang="EN-US">DN里面用的都是objectClass的簡(jiǎn)寫形式。如:ou代表organizationUnit,c代表country,st代表state,dc代表??等。
2、?
來(lái)看看
slapd.conf
這個(gè)文件
這個(gè)文件的主要信息是如下幾行:
database bdb
suffix "dc=<MY-DOMAIN>,dc=<COM>"
rootdn "cn=Manager,dc=<MY-DOMAIN>,dc=<COM>"
rootpw secret
directory /usr/local/var/openldap-data
定義了數(shù)據(jù)庫(kù),最基本的后綴,管理員的
dn
和密碼,以及數(shù)據(jù)存放路徑。
編輯好這個(gè)文件,我們就可以啟動(dòng)了。
如果你把
ldap
安裝為
windows
服務(wù),你可以像我一樣啟動(dòng):
net start OpenLDAP-slapd
?
3、?
我們主要操作的就是這個(gè)
LDIF
文件
我們需要在這個(gè)文件里面加入所需要的
dn.
注意,因?yàn)槲覀冊(cè)?/span>
slapd.conf
中定義了一個(gè)
base dn
和一個(gè)管理員
dn
,所以我們需要首先把這
2
個(gè)
dn
加進(jìn)來(lái)。
dn: dc=<MY-DOMAIN>,dc=<COM>
objectclass: dcObject
objectclass: organization
o: <MY ORGANIZATION>
dc: <MY-DOMAIN>
?
dn: cn=Manager,dc=<MY-DOMAIN>,dc=<COM>
objectclass: organizationalRole
cn: Manager
保存為
ldif
后綴的文件。然后我們用命令把這些信息加到
ldap
中去:
ldapadd -x -D "cn=Manager,dc=<MY-DOMAIN>,dc=<COM>" -W -f example.ldif
讓我們來(lái)查看以下我們的設(shè)置是否出現(xiàn)問題:
ldapsearch -x -b 'dc=example,dc=com' '(objectclass=*)'
上面的是
linux/unix
下的命令,
windows
下我們需要做點(diǎn)更改:
ldapsearch -x -b dc=example,dc=com (objectclass=*)
對(duì),就是去掉引號(hào)。
為了察看方便,筆者建議使用
GUI
工具來(lái)查看,比如筆者使用的
Softerra LDAP Browser 2.6
。
?
三、
和
java
集成
我們的
ldap Server
已經(jīng)搭建起來(lái)了,我們需要在我們的
java
程序中訪問這個(gè)服務(wù)。
Openldap.org
上有沒有講?有講?下面介紹的
JLDAP
就是干這個(gè)的。
我們需要看一下“
Java LDAP Overview
”里面的內(nèi)容。內(nèi)容不是很多,但很實(shí)用。
要在
java
中訪問
ldap
,我們需要一套
api,
你可以在下面的網(wǎng)站上獲得:
http://developer.novell.com/wiki/index.php/LDAP_Classes_for_Java
在下在的文件里面有許多的例子,在
novell
的網(wǎng)站上也有很多的例子。我就不講了。
Try yourself
。
?? 沒有華麗的Rose,也沒有Togather,用JUDE的感覺也不錯(cuò).剛剛把PicoContainer反向了.可惜,好東西都陸續(xù)要收費(fèi)了.只能用用 Community /Free 版. ? JUDE的一個(gè)下載地址: ?? http://jude.change-vision.com/jude-web/product/community.html
摘要: 一、簡(jiǎn)介?? 感謝“簡(jiǎn)易java框架”分享的學(xué)習(xí)心得。循著他的足跡,我把picocontainer讀了一遍。源代碼的版本是1.2-RC-2。?? pico的官方站點(diǎn):http://www.picocontainer.org/?? 由于它是一個(gè)專門的ioc容器,所以使用起來(lái)沒有spring那么麻煩。關(guān)于他的文檔,在官方站點(diǎn)上有一篇《5分鐘搞定pico》的文章。國(guó)人似乎也有很多的翻譯版本。講解得很詳細(xì)... 閱讀全文
一個(gè)簡(jiǎn)單的ThreadPool ? 原文來(lái)自 http://www.informit.com/articles/printerfriendly.asp?p=30483&r1=1&rl=1? 項(xiàng)目是多線程的,所以引入了線程池這個(gè)東西。池子是個(gè)老美寫的。在項(xiàng)目中表現(xiàn)的還不錯(cuò)。所以把它摘出來(lái),介紹給以后或許需要用到它的同行們。 ? 關(guān)于為什么要采用ThreadPool,原文已經(jīng)提到了:創(chuàng)建一個(gè)線程是需要開銷的;如果線程數(shù)量過大的話,cpu就會(huì)浪費(fèi)很大的精力做線程切換。 ? ThreadPool的實(shí)現(xiàn)過程就是對(duì)WorkerThread的同步和通信的管理過程。 ? 我們來(lái)看代碼。 ? 首先,在ThreadPool構(gòu)造的時(shí)候,創(chuàng)建10個(gè)WorkerThread(size=10)并讓他們運(yùn)行。每個(gè)WorkerThread線程都有個(gè)ThreadPool的引用,用于查詢ThreadPool的狀態(tài)和獲得同步鎖.WorkerThread運(yùn)行以后,循環(huán)調(diào)用ThreadPool的方法進(jìn)行查詢,如果沒有發(fā)現(xiàn)任務(wù),ThreadPool告訴正在查詢的線程進(jìn)入休眠狀態(tài),WorkerThread釋放對(duì)查詢方法的鎖定.這樣在還沒有任務(wù)的時(shí)候,所有的10個(gè)WorkerThread都會(huì)進(jìn)入休眠狀態(tài),進(jìn)入等待ThreadPool對(duì)象的等待鎖定池,只有ThreadPool對(duì)象發(fā)出notify方法(或notifyAll)后WorkerThread線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備獲得對(duì)象鎖進(jìn)入運(yùn)行狀態(tài)。 代碼片斷: while ( !assignments.iterator().hasNext() ) ??? wait(); 如果你有jprofile或者其他的觀察線程的工具,你可以看到有10個(gè)線程都在休眠狀態(tài). ? 接著,我們向ThreadPool中加入任務(wù),這些任務(wù)都實(shí)現(xiàn)了Runnable的run方法.(至于為什么把任務(wù)都做成Runnable,譯者至今也有些疑問?預(yù)定俗成?TimerTask也是實(shí)現(xiàn)自Runnable,弄得初學(xué)者經(jīng)常把真正運(yùn)行的線程搞混).ThreadPool每assign一個(gè)任務(wù),就會(huì)發(fā)出一條消息,通知它的等待鎖定池中的線程.各個(gè)線程以搶占的方式獲得對(duì)象鎖,然后很順利的獲得一條任務(wù).并把此任務(wù)從ThreadPool里面刪除.沒有搶到的繼續(xù)等待. Runnable r = (Runnable)assignments.iterator().next(); ?? assignments.remove(r); WorkerThread從ThreadPool那里獲得了任務(wù),繼續(xù)向下執(zhí)行。 target = owner.getAssignment(); ?? if (target!=null) { ??? target.run();????? ??? owner.done.workerEnd(); ?? } 記住,這里調(diào)用的是target.run();而不是調(diào)用的線程的start()方法。也就是說(shuō)在這里表現(xiàn)出的WorkerThread和task之間的關(guān)系僅僅是簡(jiǎn)單的方法調(diào)用的關(guān)系,并沒有額外產(chǎn)生新線程。(這就是我上面納悶為什么大家都實(shí)現(xiàn)Runnable來(lái)做task的原因) ?大家可能注意到,WorkerThread并沒有對(duì)異常作處理。而我們知道發(fā)生在線程上的異常會(huì)導(dǎo)致線程死亡。解決的辦法有2中,一種是通過threadpool的管理來(lái)重新激起一個(gè)線程,一種是把異常在線程之內(nèi)消滅。在項(xiàng)目中,我采用的是第二中,因此這個(gè)片斷改稱這樣: if (target!=null) { ? try{ ??? target.run();????? ?? } ? catch(Throwable t){ ?....... ?? } ??? owner.done.workerEnd(); } 在WorkerThread完成一個(gè)task以后,繼續(xù)循環(huán)作同樣的流程. 在這個(gè)ThreadPool的實(shí)現(xiàn)里面,Jeff Heaton用了一個(gè)Done類來(lái)觀察WorkerThread的執(zhí)行情況.和ThreadPoool的等待鎖定池不同,Done的等待鎖定池里面放的是初始化ThreadPool的線程(可能是你的主線程),我們叫他母線程. ? 在給出的測(cè)試?yán)又?母線程在調(diào)用complete()方法后進(jìn)入休眠(在監(jiān)視中等待),一開始是waitBegin()讓他休眠,在assign加入task以后,waitDone()方法讓他休眠.在WorkerThread完成一個(gè)task以后,通知waitDone()起來(lái)重新檢查activeThreads的數(shù)值.若不為0,繼續(xù)睡覺.若為0,那么母線程走完,死亡(這個(gè)時(shí)候該做的task已經(jīng)做完了).母線程走完,ThreadPool還存在嗎?答案是存在,因?yàn)閃orkerThread還沒有消亡,他們?cè)诘却乱慌蝿?wù),他們有ThreadPool的引用,保證ThreadPool依然存在.大家或許已經(jīng)明白Done這個(gè)類的作用了. ? 細(xì)心的讀者或許會(huì)發(fā)現(xiàn),發(fā)生在Done實(shí)例上的notify()并不是像ThreadPool上的notify()那樣每次都能完成一項(xiàng)工作.比如除了第一個(gè)被assign的task,其他的task在assign進(jìn)去的時(shí)候,發(fā)出的notify()對(duì)于waitDone()來(lái)說(shuō)是句"狼來(lái)了". ?最后在ThreadPool需要被清理得時(shí)候,使每一個(gè)WorkerThread中斷(這個(gè)時(shí)候或許所有的WorkerThread都在休眠)并銷毀.記住這里也是一個(gè)異步的過程.等到每一個(gè)WorkerThread都已經(jīng)銷毀,finalize()的方法體走完.ThreadPool被銷毀. ?for (int i=0;i<threads.length;i++) { ?? threads[i].interrupt(); ?? done.workerBegin(); ?? threads[i].destroy(); ? } ? done.waitDone(); 為什么有句done.workerBegin();?不明白. 參考文章: http://www.zdnet.com.cn/developer/common/printfriend/printfriendly.htm?AT=39276905-3800066897t-20000560c
??? 呂華兵,男,24歲。 ??? 2000-2004年,在中國(guó)民航大學(xué)讀書。學(xué)習(xí)期間,筆者以技術(shù)部長(zhǎng)身份參與了校易航工作室暨易航網(wǎng)站的創(chuàng)建和發(fā)展工作,參與和獨(dú)立完成了多個(gè)項(xiàng)目的設(shè)計(jì)和開發(fā)。 ?? 2004年5月到2006年5月,在北京環(huán)亞時(shí)代(港新合資)天津軟件中心從事Java的開發(fā)工作。參與了CMCC的OA的實(shí)施工作,主力開發(fā)了MOCHA AM的前端顯示和MOCHA ITAM的報(bào)表系統(tǒng)。 ? 2006年5月至今,在美國(guó)易達(dá)軟件有限公司工作。設(shè)計(jì)并開發(fā)了Information Publisher的多線程后端程序。 ?? ? 筆者長(zhǎng)期從事j2se,j2ee的開發(fā)工作,對(duì)各種設(shè)計(jì)模式亦有豐富的使用經(jīng)驗(yàn)。 ? 筆者從來(lái)重視規(guī)范的軟件流程,對(duì)RUP有很深的理解。 ? 對(duì)于javascript,dhtml,ajax,筆者有著豐富的經(jīng)驗(yàn)。 ? 筆者也是“拿來(lái)主義”的擁躉,不遺余力的翻譯、學(xué)習(xí)、使用和宣傳各種開源項(xiàng)目。目前使用過的開源項(xiàng)目有:spring、picocontainer、hibernate、ibatis、struts、webwork等框架系列,DOM系列,commons系列,Quartz,log4j,ant,oscache,proxool以及各種報(bào)表工具等等。
?筆者從來(lái)重視知識(shí)的提取和積累,這也是筆者開此blog的主要原因,同時(shí),也希望通過此blog結(jié)交更多的朋友。
譯者安:你敢大膽采用最新的技術(shù)嗎?你顧慮哪些方面?下面的采訪將給我們提供一個(gè)參考。 ?原文:Interview: Real-world Experience with Google Web Toolkit (GWT) ? ?? 在java中,對(duì)技術(shù)的采用是一件讓人心煩的事情,因?yàn)槲覀儷@得通知的途徑太多。不同的會(huì)議,不同的站點(diǎn)如slashdot和theserverside,而且還有數(shù)不清的個(gè)人博客如dhh和o'Reilly's Radar. 一個(gè)讓人感興趣的技術(shù)總是讓業(yè)界議論紛紛,正如人們所意識(shí)到的,這個(gè)產(chǎn)品并不是成熟期。 ??? 為了讓一個(gè)產(chǎn)品成為主流,早期的采用者必須足夠喜歡這項(xiàng)產(chǎn)品來(lái)承擔(dān)很多非常的任務(wù)以便 讓更為膽怯的開發(fā)者相信這項(xiàng)新技術(shù)值得采用。像Hibernate和Spring Framework這樣的技術(shù)花了好幾年 才成為一個(gè)成熟產(chǎn)品。許多產(chǎn)品,比如maven,在版本確定之前經(jīng)歷了痛苦的時(shí)期因?yàn)樗麄冊(cè)缙谌狈?br />足夠的文檔或者有不同的足夠強(qiáng)大的挑戰(zhàn)者比如ant.本人對(duì)這個(gè)過程中的盲點(diǎn)很感興趣,從議論這個(gè)產(chǎn)品的介紹到大范圍的采用往往要經(jīng)歷成月上年,而且很難指定時(shí)間表。hibernate并不是暴雨似的到來(lái),而是通過大量用戶自我采用.一個(gè)失敗的項(xiàng)目比如ojb出來(lái)的時(shí)候也是引起轟動(dòng),但是它最終沒有承諾的那么好.在這種情況下,早期的hibernate使用者其實(shí)信心不足. ? 讓我們來(lái)看Google Web Toolkit (GWT)… GWT在這個(gè)進(jìn)程中處于什么位置? gwt看起來(lái)是在早期使用(early-adopter)的中期。一開始的議論聲已經(jīng)消去,現(xiàn)在陸續(xù)出現(xiàn)了許多關(guān)于gwt的文章和博客,表明了人們正在期待關(guān)于gwt的第一個(gè)helloworld的反饋報(bào)告。我的很多謹(jǐn)慎的同行都在回避他,事實(shí)上認(rèn)為它是個(gè)不好的主意。風(fēng)險(xiǎn)阻礙了開發(fā)者對(duì)大多數(shù)新技術(shù)的評(píng)估直到他們?cè)诂F(xiàn)實(shí)中看到了一個(gè)活生生的實(shí)例解決方案--就像maven被ibm使用一樣。那些有能力來(lái)嘗試風(fēng)險(xiǎn)的開發(fā)者正在對(duì)這個(gè)框架進(jìn)行測(cè)試。他們中的某一個(gè)或許宣稱gwt不適合它的組織。另外一個(gè)同行已經(jīng)原則上接受了gwt的觀點(diǎn),但是沒有時(shí)間來(lái)在他的應(yīng)用中集成。所以,到底gwt處于什么時(shí)期?早期的使用人群有哪些經(jīng)驗(yàn)?zāi)兀?br />?? 關(guān)于這個(gè)問題,我專門采訪了Grassroots Technologies公司的Michael Podrazik。Grassroots Technologies是一個(gè)在紐約的咨詢小組。通過在Grassroots的工作,michael已經(jīng)正在把gwt應(yīng)用在他們的一個(gè)新的正在開發(fā)的web應(yīng)用當(dāng)中。在下面的采訪里面,我要求他來(lái)交流他的產(chǎn)品經(jīng)驗(yàn)來(lái)幫助其他人去理解gwt.我特別要求他給一些gwt客觀的意見,而且細(xì)致的描述他在用gwt開發(fā)過程中遇到的挑戰(zhàn)。幸運(yùn)的是,他的信息將會(huì)幫助你決定是否gwt是你項(xiàng)目的正確選擇。 采訪內(nèi)容: q:什么使你選擇了gwt? a:我訂閱了google的blog,所以我聽說(shuō)了gwt當(dāng)他發(fā)布到j(luò)avaone的時(shí)候。在閱讀了他的文檔之后我開始對(duì)這種方式很好奇,因此我把它down了下來(lái)而且開始使用它(play with it).我剛剛開始了一個(gè)項(xiàng)目,這個(gè)項(xiàng)目是把遺留的 Access/VBA的桌面應(yīng)用升級(jí)為一個(gè)web應(yīng)用。在UI方面有許多ajaxian特性所以我想我可以讓gwt一展身手。我認(rèn)為(figure)只要我保持我的架構(gòu)足夠抽象,我就有能力用更為傳統(tǒng)的web應(yīng)用框架來(lái)替換gwt層。gwt會(huì)很傷腦筋嗎?至少目前為止我很開心。 q:gwt出現(xiàn)了那些挑戰(zhàn)?你圍繞著gwt設(shè)計(jì)的web框架嗎?gwt是否挑戰(zhàn)了你關(guān)于web應(yīng)用開發(fā)的觀點(diǎn)? a:你確實(shí)不能簡(jiǎn)單的認(rèn)為gwt是一個(gè)webapp的框架,他更是一個(gè)有著rpc和對(duì)象序列化的ui類庫(kù)。因?yàn)槟阈枰淖兡沩?xiàng)目組織的assumptions以及包的結(jié)構(gòu)。在java服務(wù)端開發(fā)rich-client用戶界面我們有大量的經(jīng)驗(yàn),比如flash/actionscript.gwt和他們十分類似,因此可以想象有這些元素的項(xiàng)目--分隔的服務(wù)端和客戶端而不是同一的webapp--很爽。 ? 朝著這個(gè)方向,你需要明確區(qū)分服務(wù)端和客戶端的功能。我相信一個(gè)好的哲學(xué)就是使你的客戶端僅僅用于展示。 ? 你需要思考你服務(wù)接口的設(shè)計(jì),比如每個(gè)操作的粒度 ? 你不能在客戶端代碼上用java5得語(yǔ)法 Q:你的意思是不能再gwt的具體類或者普通的web應(yīng)用里面用java5的語(yǔ)法? a:你不能在客戶代碼里面使用java5的語(yǔ)法。我們?cè)诜?wù)端代碼中使用了許多java5的特性,但是所有將要被轉(zhuǎn)換成javascript的代碼必須是1.4的規(guī)范。 這個(gè)也包括許多事實(shí)上你用在服務(wù)端的類。因?yàn)閞pc框架允許用戶定義的數(shù)據(jù)類型的序列化,意思是你將在瀏覽器端得到一個(gè)已經(jīng)被轉(zhuǎn)化為javascript實(shí)例的類,這個(gè)類作為一個(gè)參數(shù)傳遞到服務(wù)端的實(shí)現(xiàn)中。在你的服務(wù)端代碼中,你將操縱同一個(gè)class而且是編譯過的字節(jié)碼。 ?這個(gè)時(shí)候就出現(xiàn)了一個(gè)選擇,domain module和gwt的耦合度怎樣才合適呢? What we decided was to keep value objects implementation-agnostic so as to avoid “infecting” the API and persistence layers with beans implementing GWT’s IsSerializable interface. 舉個(gè)例子,在服務(wù)端我們有個(gè)IUser接口的用戶模塊,這個(gè)借口繼承自IPersistable.gwt的實(shí)現(xiàn)接受和返回實(shí)現(xiàn)IsSerializable接口的GwtUser的實(shí)例并把這些實(shí)例利用commons-beanutils發(fā)送到服務(wù)端。 ?對(duì)于這一點(diǎn)可能有些爭(zhēng)論,這樣做并不非必要。但是我覺得這點(diǎn)額外的工作將帶給你更為清晰的層次劃分。我們可以嵌入gwt到任何一點(diǎn),而且可以轉(zhuǎn)換到springmvc或者struct或者其他的地方,而不需要擔(dān)心代碼上?的反應(yīng)。 q:你發(fā)現(xiàn)gwt產(chǎn)生的javascript不能垮瀏覽器的地方了嗎?你發(fā)現(xiàn)gwt產(chǎn)生的javascript包含一些錯(cuò)誤需要手動(dòng)調(diào)試了嗎? a:都沒有,這正是令我們驚訝的地方。跨瀏覽器javascript的開發(fā)是PITA,而且GWT真正的把你從他那里隔離開來(lái)。 我發(fā)現(xiàn)了大量的在FIREFOX和IE不同的地方,但是這些最后被確認(rèn)都是CSS支持的問題而于GWT無(wú)關(guān)。 我也遇到了一大隊(duì)JAVASCRIPT錯(cuò)誤,但是這些錯(cuò)誤都是應(yīng)為變量而不在初始化,這些問題很快就會(huì)找到并且不需要大量的調(diào)試。目前已經(jīng)完成的大多數(shù)工作并不全是ui控件的問題,或許隨著我們的深入,我們會(huì)遇到一些問題,但是目前為止,我們還沒有多少麻煩。 q:你的工作組的成員是更喜歡java還是javascript呢? 顯然是java,哈哈。但是我們有人對(duì)javascript和actionscript也很精通。就像譯者本人。 q:一句話,對(duì)正在考慮gwt的人,你有什么建議?你會(huì)推薦他嗎?你對(duì)這項(xiàng)技術(shù)的客觀觀點(diǎn)是什么?thumbs up or thumbs down? a:目前是thumbs up.我們目前仍然在開發(fā)的早期,而且我還不想說(shuō)在它是完美的或者在以后的進(jìn)程中不會(huì)咬我們一口。意思是說(shuō),你的建構(gòu)要搭好。 它真的像是在作swing或者其他UI的桌面應(yīng)用。 ?我們用基于Controller和IView實(shí)現(xiàn)的GWT生成了全部的ui.除了gwt模塊引入以外,那里沒有html。 ? 這是對(duì)幾乎所有主流web應(yīng)用范例的違背,但是如果你喜歡ui編程,他完美的抽象了ajax/dhtml的行為到一個(gè)十分友好和可擴(kuò)展的api. ? 我或許會(huì)說(shuō)如果你的工作是php,asp或者其他語(yǔ)言,你或許需要花更多的功夫。如果你已經(jīng)是一個(gè)有經(jīng)驗(yàn)的java程序員,那么你可以很快投入其中。
java.sql.Date,java.sql.Time和java.sql.Timestamp三個(gè)都是java.util.Date的子類(包裝類)。 但是為什么java.sql.Date類型的值插入到數(shù)據(jù)庫(kù)中Date字段中會(huì)發(fā)生數(shù)據(jù)截取呢? java.sql.Date是為了配合SQL DATE而設(shè)置的數(shù)據(jù)類型。“規(guī)范化”的java.sql.Date只包含年月日信息,時(shí)分秒毫秒都會(huì)清零。格式類似:YYYY-MM-DD 當(dāng)我們調(diào)用ResultSet的getDate()方法來(lái)獲得返回值時(shí),java程序會(huì)參照"規(guī)范"的java.sql.Date來(lái)格式化數(shù)據(jù)庫(kù)中的數(shù)值。因此,如果 數(shù)據(jù)庫(kù)中存在的非規(guī)范化部分的信息將會(huì)被劫取。在sun提供的ResultSet.java中這樣對(duì)getDate進(jìn)行注釋的: Retrieves the value of the designated column in the current row of this <code>ResultSet</code> object as a “java.sql.Date” object in the Java programming language. 同理。如果我們把一個(gè)java.sql.Date值通過PrepareStatement的setDate方法存入數(shù)據(jù)庫(kù)時(shí),java程序會(huì)對(duì)傳入的java.sql.Date規(guī)范化 ,非規(guī)范化的部分將會(huì)被劫取。 ?然而,我們java.sql.Date一般由java.util.Date轉(zhuǎn)換過來(lái),如:java.sql.Date sqlDate=new java.sql.Date(new java.util.Date().getTime()). ?顯然,這樣轉(zhuǎn)換過來(lái)的java.sql.Date往往不是一個(gè)規(guī)范的java.sql.Date. ?在 http://www.thunderguy.com/semicolon/2003/08/14/java-sql-date-is-not-a-real-date/ 文章中提到,要保存java.util.Date的精確值, ?我們需要利用java.sql.Timestamp. ?感謝這篇文章的鋪墊: http://community.csdn.net/Expert/topic/4354/4354971.xml?temp=.5256616
官方網(wǎng)址:
http://logging.apache.org/log4j/docs/index.html
一個(gè)中文翻譯的文檔:
http://www.jaxwiki.org/zh/project/logging.apache.org/log4j/docs/manual.html
我摘出黃色字體表明幾條列在下面,也是筆者認(rèn)為log4j最主要特點(diǎn)的濃縮:
1.階層式的命名:
如果一個(gè)logger 的名字后面跟著一個(gè)點(diǎn)號(hào)(dot),它就是點(diǎn)號(hào)(dot)后面的那個(gè)logger的前輩( ancestor),是這個(gè)晚輩(descendant) 的前綴。如果在它自己和這個(gè)晚輩之間沒有其它的前輩,它和這個(gè)晚輩之間就是父子關(guān)系。
2.級(jí)別繼承
對(duì)于一個(gè)給定的logger C,它繼承的級(jí)別等于logger階層里,從C開始往root logger上去的第一個(gè)non-null級(jí)別。
3.執(zhí)行規(guī)則
在一個(gè)級(jí)別為q(被指定的或繼承的)的logger里,一個(gè)級(jí)別為p的日志請(qǐng)求,只有在p >= q 時(shí)才能夠被執(zhí)行。
4.appender添加性的規(guī)則
Logger C的log輸出信息將被輸出到C的所有appenders和它的前輩的 appenders。這就是"appender additivity"的意思。但是,如果logger C的前輩,比如說(shuō)P,P的additivity flag被設(shè)置為 false ,那么,C的輸出信息將被輸出到C的所有appenders中去,以及它的前輩的——截止在P那里,包括P在內(nèi)的,appenders中去,但是不會(huì)輸出到P的前輩的 appenders中去。 默認(rèn)情況下,Loggers的additivity flag設(shè)置為true 。
關(guān)于日志格式:暫貼幾個(gè)樣例:
log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %-c (%13F:%L) %3x - %m%n
在配置文件中,log4j可以訪問到系統(tǒng)環(huán)境變量。具體的變量參考相關(guān)資料。
一篇我很早以前在csdn寫的文章:
http://blog.csdn.net/huabingl/archive/2005/02/19/293933.aspx
我承認(rèn)我用mysql有很長(zhǎng)時(shí)間了,不過似乎我仍然很白。好吧,還是寫寫吧。 1。1067錯(cuò)誤,無(wú)法啟動(dòng)。7/3/2006 解決步驟和方案:察看日至,mysql.user表莫名其妙的弄丟了。從其他地方扒下一個(gè)放在這里就可以了。 2.非安裝版mysql的安裝和啟動(dòng)。 一般情況下,本人習(xí)慣用非安裝版的軟件。為了安裝方便,你可以把解壓后的文件拷貝到c盤根目錄下,并把總目錄改為mysql.然后進(jìn)入windows命令 控制臺(tái),在c:/mysql/bin下面運(yùn)行mysqld-nt --install把它安裝為一個(gè)服務(wù),然后調(diào)用net start mysql啟動(dòng)它,停止的命令是net stop mysql .想要移除這個(gè)服務(wù),用命令mysqld-nt --remove 3.訪問mysql的命令:mysql -h host -u user -p 。不過有好多好用的客戶端可以使用,比如5.0自帶的工具和SQLyog Enterprise 4。庫(kù)表相關(guān)的命令:SHOW DATABASES;SHOW TABLES;DESCRIBE table1/desc table1; 5.察看當(dāng)前配置:show variables; 6.關(guān)于中文亂碼問題,到一定積累,筆者準(zhǔn)備開專題。目前簡(jiǎn)要列下: 在mysql的一次會(huì)話中,服務(wù)器收到客戶端發(fā)來(lái)的指令后,大致要執(zhí)行3個(gè)動(dòng)作: 1、服務(wù)器認(rèn)為收到的指令是按當(dāng)前character_set_client環(huán)境變量所指定的字符集編碼的, 2、然后再將其轉(zhuǎn)換成character_set_connection所指定的字符集編碼 3、分析、執(zhí)行該指令。 4、 用character_set_results變量所指定的字符集返回服務(wù)器向客戶端傳輸?shù)臄?shù)據(jù) 解決這個(gè)問題的關(guān)鍵點(diǎn)在于設(shè)置 default-character-set 變量。 7,在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候,我們有時(shí)會(huì)需要提供一些編碼上的參數(shù),如: #1. Create mvnforum database with the "Create database" syntax (for unicode and others): # mysql> CREATE DATABASE mvnforum CHARACTER SET [charater_set] COLLATE [collation] # mysql> CREATE DATABASE mvnforum CHARACTER SET utf8 collate # Where charater_set and collation : @see http://dev.mysql.com/doc/refman/4.1/en/charset-mysql.html # # a, practice to view all supported character set # mysql> SHOW CHARACTER SET; # b, practice to view all supported collation: # mysql> SHOW COLLATION; # # c, Example for Unicode: # mysql> CREATE DATABASE mvnforum CHARACTER SET utf8 COLLATE utf8_general_ci #" " 未完待續(xù)。 歡迎回帖。
1。什么是異常 ???異常是一種狀態(tài),是程序出現(xiàn)了符合該異常條件的一種狀態(tài)。因此,他也可以說(shuō)成是一種條件。 2。為什么要捕獲異常 ? 捕獲異常是為了對(duì)程序中出現(xiàn)的某種狀況進(jìn)行處理。如果有異常而沒有捕獲,異常將會(huì)向上一層傳播,最終導(dǎo)致線程在此中止。 3。什么是check異常和unchecked異常 ? uncheck異常一般是RuntimeException.出現(xiàn)這類異常,編譯器不會(huì)強(qiáng)制要用戶去捕獲(當(dāng)然你可以捕獲)。?? 編譯器會(huì)強(qiáng)制要求用戶對(duì)checked異常進(jìn)行捕獲并作出一定的處理。 4。為什么不推薦捕獲頂層異常(Exception) ? 程序中會(huì)發(fā)生各種各樣的異常。除非你的程序是個(gè)終端(一個(gè)業(yè)務(wù)的終點(diǎn)),否則不推薦捕獲頂層異常。 ?在程序的中間環(huán)節(jié)捕獲所有異常毫無(wú)意義,并有可能導(dǎo)致流程上的隱患。比如,出現(xiàn)某種異常后,期望線程就此結(jié)束,不去做下面的工作,但是如果在中間環(huán)節(jié)對(duì)頂層異常進(jìn)行了非法處理,程序有可能會(huì)運(yùn)行下去,將導(dǎo)致不可控的錯(cuò)誤。 5。為什么要自定義異常 ?自定義異常是為了設(shè)置異常鏈的起點(diǎn)。一般情況下,我們都是允許每個(gè)程序員看到所有的異常信息,這個(gè)時(shí)候大多數(shù)都是把下一層的異常直接重?cái)S到上一層。然而在多層次的結(jié)構(gòu)中,我們有時(shí)候需要隱藏底層異常(這種異常的信息很多,很枯燥),而給消費(fèi)者提供一個(gè)更為直觀的異常,這個(gè)時(shí)候我們需要自定義異常。有的異常類jdk已經(jīng)給我們提供,比如常用的IllegalArgumentException。如果你想在此再作包裝,你可以創(chuàng)建自己的異常類。如此,消費(fèi)者將以此異常作為異常鏈的起點(diǎn)。 6。為什么要重?cái)S異常 ?重?cái)S異常是處理異常的一種方式。在捕獲了某種異常后,用戶可能不希望在這一層做出裁決,或者即使做出了一定的處理,但仍然需要向上一層報(bào)告,因此需要重?cái)S異常。 7。異常機(jī)制。 ?? 一旦某個(gè)點(diǎn)發(fā)生異常,這個(gè)點(diǎn)下面和catch語(yǔ)句之間的代碼將不會(huì)被執(zhí)行。因此,異常是一種中止流程的很有效的機(jī)制。 ?? 關(guān)于異常,在effective java中提到“異常轉(zhuǎn)譯”和“異常連接”的概念。本人傾向于用“異常轉(zhuǎn)譯”,前提是要配置log4j,并作詳細(xì)的日志紀(jì)錄。
?XmlBeans由 BEA公司發(fā)明,后捐贈(zèng)給Apache基金會(huì)的。 ?在項(xiàng)目中遇到這樣的需求,根據(jù)已有的schema對(duì)xml進(jìn)行格式校驗(yàn),并讀取出xml得數(shù)據(jù)。 ?在大搜一番后,我最終把目光停留在xmlbeans上面。被淘汰的是digester. ?下面是一篇dev2dev得文章: ??http://dev2dev.bea.com/pub/a/2006/05/xmlbeans-2.html?page=4 ?我就不炒飯了。 ?好心的人給簡(jiǎn)單翻譯了一下: http://dev2dev.bea.com.cn/techdoc/200403127.html ?翻譯得內(nèi)容很少,有空本人補(bǔ)上。 ibm dw上也有個(gè)豆腐塊: http://www-128.ibm.com/developerworks/cn/xml/x-beans1/ 關(guān)于digester的內(nèi)容,只選了一篇文章:來(lái)自devx得 http://www.devx.com/Java/Article/21832/1763
關(guān)于2中方法的對(duì)比,他們的文章已經(jīng)說(shuō)的很詳細(xì)了。
xmlbeans采用的是sax來(lái)讀取數(shù)據(jù)。2004年,由bea公司發(fā)明的stax(stream API for XML)已經(jīng)被jcp列為標(biāo)準(zhǔn)jsr-173,在jdk6.0中會(huì)出現(xiàn)。 ? 關(guān)于stax,sax和dom的對(duì)比超出本篇范圍,在此略過。 后記: ? 在正在完成的項(xiàng)目中,我采用了xmlbeans,它的引入給我?guī)?lái)了很大的方便.
-
You have to get noticed to get promoted.
-
You have to get noticed to get hired.
-
It really impresses people when you say “Oh, I’ve written about that, just google for XXX and I’m on the top page” or “Oh, just google my name.”
-
No matter how great you are, your career depends on communicating. The way to get better at anything, including communication, is by practicing. Blogging is good practice.
-
Bloggers are better-informed than non-bloggers. Knowing more is a career advantage.
-
Knowing more also means you’re more likely to hear about interesting jobs coming open.
-
Networking is good for your career. Blogging is a good way to meet people.
-
If you’re an engineer, blogging puts you in intimate contact with a worse-is-better 80/20 success story. Understanding this mode of technology adoption can only help you.
-
If you’re in marketing, you’ll need to understand how its rules are changing as a result of the current whirlwind, which nobody does, but bloggers are at least somewhat less baffled.
-
It’s a lot harder to fire someone who has a public voice, because it will be noticed.
from http://www.tbray.org/ongoing/When/200x/2005/03/08/BloggingIsGood
http://www.javaalmanac.com
??? Java開發(fā)者年鑒一書的在線版本. 要想快速查到某種Java技巧的用法及示例代碼, 這是一個(gè)不錯(cuò)的去處.
http://www.onjava.com
??? O'Reilly的Java網(wǎng)站. 每周都有新文章
http://java.sun.com
??? 官方的Java開發(fā)者網(wǎng)站 - 每周都有新文章發(fā)表
http://www.developer.com/java
??? 由Gamelan.com 維護(hù)的Java技術(shù)文章網(wǎng)站
http://www.java.net
??? Sun公司維護(hù)的一個(gè)Java社區(qū)網(wǎng)站
http://www.builder.com
??? Cnet的Builder.com網(wǎng)站 - 所有的技術(shù)文章, 以Java為主.
http://www.ibm.com/developerworks/java
??? IBM的Developerworks技術(shù)網(wǎng)站; 這是其中的Java技術(shù)主頁(yè)
http://www.javaworld.com
??? 最早的一個(gè)Java站點(diǎn). 每周更新Java技術(shù)文章
http://www.devx.com/java
??? DevX維護(hù)的一個(gè)Java技術(shù)文章網(wǎng)站
http://www.fawcette.com/javapro
??? JavaPro在線雜志網(wǎng)站.
http://www.sys-con.com/java
??? Java Developers Journal的在線雜志網(wǎng)站.
http://www.javadesktop.org
??? 位于Java.net的一個(gè)Java桌面技術(shù)社區(qū)網(wǎng)站.
http://www.theserverside.com
??? 這是一個(gè)討論所有Java服務(wù)器端技術(shù)的網(wǎng)站.
http://www.jars.com
??? 提供Java評(píng)論服務(wù). 包括各種framework和應(yīng)用程序
http://www.jguru.com
??? 一個(gè)非常棒的采用Q&A形式的Java技術(shù)資源社區(qū).
http://www.javaranch.com
???? 一個(gè)論壇,得到Java問題答案的地方,初學(xué)者的好去處。
http://www.ibiblio.org/javafaq/javafaq.html
??? comp.lang.java的FAQ站點(diǎn) - 收集了來(lái)自comp.lang.java新聞組的問題和答案的分類目錄.
http://java.sun.com/docs/books/tutorial/
??? 來(lái)自SUN公司的官方Java指南 - 對(duì)于了解幾乎所有的java技術(shù)特性非常有幫助.
http://www.javablogs.com
??? 互聯(lián)網(wǎng)上最活躍的一個(gè)Java Blog網(wǎng)站.
http://java.about.com/
轉(zhuǎn)自51cto
一般情況下,J2EE應(yīng)用服務(wù)器支持JDBC事務(wù)、JTA事務(wù)、容器管理事務(wù)。這里討論JTA和JDBC事務(wù)的區(qū)別。這2個(gè)是常用的DAO模式事務(wù)界定方式。 JDBC 事務(wù) JDBC 事務(wù)是用 Connection 對(duì)象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務(wù)模式:自動(dòng)提交和手工提交。 ★ 在jdbc中,事務(wù)操作缺省是自動(dòng)提交。也就是說(shuō),一條對(duì)數(shù)據(jù)庫(kù)的更新表達(dá)式代表一項(xiàng)事務(wù)操作,操作成功后,系統(tǒng)將自動(dòng)調(diào)用commit()來(lái)提交,否則將調(diào)用rollback()來(lái)回滾。 ★ 在jdbc中,可以通過調(diào)用setAutoCommit(false)來(lái)禁止自動(dòng)提交。之后就可以把多個(gè)數(shù)據(jù)庫(kù)操作的表達(dá)式作為一個(gè)事務(wù),在操作完成后調(diào)用commit()來(lái)進(jìn)行整體提交,倘若其中一個(gè)表達(dá)式操作失敗,都不會(huì)執(zhí)行到commit(),并且將產(chǎn)生響應(yīng)的異常;此時(shí)就可以在異常捕獲時(shí)調(diào)用rollback()進(jìn)行回滾。這樣做可以保持多次更新操作后,相關(guān)數(shù)據(jù)的一致性,示例如下:
try {
conn =
DriverManager.getConnection
("jdbc:oracle:thin:@host:1521:SID","username","userpwd";
conn.setAutoCommit(false);//禁止自動(dòng)提交,設(shè)置回滾點(diǎn)
stmt = conn.createStatement();
stmt.executeUpdate(“alter table …”); //數(shù)據(jù)庫(kù)更新操作1
stmt.executeUpdate(“insert into table …”); //數(shù)據(jù)庫(kù)更新操作2
conn.commit(); //事務(wù)提交
}catch(Exception ex) {
ex.printStackTrace();
try {
conn.rollback(); //操作不成功則回滾
}catch(Exception e) {
e.printStackTrace();
}
}
JDBC 事務(wù)的一個(gè)缺點(diǎn)是事務(wù)的范圍局限于一個(gè)數(shù)據(jù)庫(kù)連接。一個(gè) JDBC 事務(wù)不能跨越多個(gè)數(shù)據(jù)庫(kù)。 JTA事務(wù) JTA(Java Transaction API) 為 J2EE 平臺(tái)提供了分布式事務(wù)服務(wù)。 要用 JTA 進(jìn)行事務(wù)界定,應(yīng)用程序要調(diào)用 javax.transaction.UserTransaction 接口中的方法。例如: utx.begin(); // ... DataSource ds = obtainXADataSource(); Connection conn = ds.getConnection(); pstmt = conn.prepareStatement("UPDATE MOVIES ..."); pstmt.setString(1, "Spinal Tap"); pstmt.executeUpdate(); // ... utx.commit();
讓我們來(lái)關(guān)注下面的話: “用 JTA 界定事務(wù),那么就需要有一個(gè)實(shí)現(xiàn) javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅(qū)動(dòng)程序。一個(gè)實(shí)現(xiàn)了這些接口的驅(qū)動(dòng)程序?qū)⒖梢詤⑴c JTA 事務(wù)。一個(gè) XADataSource 對(duì)象就是一個(gè) XAConnection 對(duì)象的工廠。 XAConnection s 是參與 JTA 事務(wù)的 JDBC 連接。” 要使用JTA事務(wù),必須使用XADataSource來(lái)產(chǎn)生數(shù)據(jù)庫(kù)連接,產(chǎn)生的連接為一個(gè)XA連接。 XA連接(javax.sql.XAConnection)和非XA(java.sql.Connection)連接的區(qū)別在于:XA可以參與JTA的事務(wù),而且不支持自動(dòng)提交。 Note: Oracle, Sybase, DB2, SQL Server等大型數(shù)據(jù)庫(kù)才支持XA, 支持分布事務(wù)。 My SQL 連本地都支持不好,更別說(shuō)分布事務(wù)了。 JTA方式的實(shí)現(xiàn)過程: 用XADataSource產(chǎn)生的XAConnection它擴(kuò)展了一個(gè)getXAResource()方法,事務(wù)通過這個(gè)方法把它加入到事務(wù)容器中進(jìn)行管理.對(duì)于調(diào)用者來(lái)說(shuō),根本看不到事務(wù)是如果管理的,你只要聲明開始事務(wù),告訴容器我下面的操作要求事務(wù)參與了,最后告訴事務(wù)說(shuō)到這兒可以提交或回滾了,別的都是黑箱操作。 在使用JTA之前,你必須首先實(shí)現(xiàn)一個(gè)Xid類用來(lái)標(biāo)識(shí)事務(wù)(在普通情況下這將由事務(wù)管理程序來(lái)處理)。Xid包含三個(gè)元素:formatID、gtrid(全局事務(wù)標(biāo)識(shí)符)和bqual(分支修飾詞標(biāo)識(shí)符)。 下面的例子說(shuō)明Xid的實(shí)現(xiàn):
import javax.transaction.xa.*; public class MyXid implements Xid { protected int formatId; protected byte gtrid[]; protected byte bqual[]; public MyXid() { } public MyXid(int formatId, byte gtrid[], byte bqual[]) { this.formatId = formatId; this.gtrid = gtrid; this.bqual = bqual; }
public int getFormatId() { return formatId; }
public byte[] getBranchQualifier() { return bqual; }
public byte[] getGlobalTransactionId() { return gtrid; }
} 其次,你需要?jiǎng)?chuàng)建一個(gè)你要使用的數(shù)據(jù)庫(kù)的數(shù)據(jù)源:
public DataSource getDataSource() throws SQLException { SQLServerDataSource xaDS = new com.merant.datadirect.jdbcx.sqlserver.SQLServerDataSource(); xaDS.setDataSourceName("SQLServer"); xaDS.setServerName("server"); xaDS.setPortNumber(1433); xaDS.setSelectMethod("cursor"); return xaDS; }
例1?這個(gè)例子是用“兩步提交協(xié)議”來(lái)提交一個(gè)事務(wù)分支:
XADataSource xaDS; XAConnection xaCon; XAResource xaRes; Xid xid; Connection con; Statement stmt; int ret; xaDS = getDataSource(); xaCon = xaDS.getXAConnection("jdbc_user", "jdbc_password"); xaRes = xaCon.getXAResource(); con = xaCon.getConnection(); stmt = con.createStatement(); xid = new MyXid(100, new byte[]{0x01}, new byte[]{0x02}); try { xaRes.start(xid, XAResource.TMNOFLAGS); stmt.executeUpdate("insert into test_table values (100)"); xaRes.end(xid, XAResource.TMSUCCESS); ret = xaRes.prepare(xid); if (ret == XAResource.XA_OK) { xaRes.commit(xid, false); } } catch (XAException e) { e.printStackTrace(); } finally { stmt.close(); con.close(); xaCon.close(); } 當(dāng)然,實(shí)際過程中,我們不需要寫這些代碼,這些代碼是JTA最終的實(shí)現(xiàn)代碼。 關(guān)于“兩步提交協(xié)議”,可以參看下面的文章: http://www.jspcn.net/htmlnews/11049371131251752.html
http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html
選擇最好的方式 用 JDBC API 進(jìn)事務(wù)界定來(lái)構(gòu)建 DAO 類的。這些 DAO 類可以總結(jié)如下:
事務(wù)界定代碼嵌入在 DAO 類中。 DAO 類使用 JDBC API 進(jìn)行事務(wù)界定。 調(diào)用者不能界定事務(wù)。 事務(wù)范圍局限于單個(gè) JDBC 連接。 JDBC 事務(wù)并不總是適合復(fù)雜的企業(yè)應(yīng)用程序。如果您的事務(wù)要跨越多個(gè) DAO 或者多個(gè)數(shù)據(jù)庫(kù),那么下列實(shí)現(xiàn)策略也許更合適:
事務(wù)用 JTA 界定。 事務(wù)界定代碼從 DAO 中分離出來(lái)。 調(diào)用者負(fù)責(zé)界定事務(wù)。 DAO 加入一個(gè)全局事務(wù)。 JDBC 方式由于其簡(jiǎn)單性而具有吸引力,JTA 方式提供了更大的靈活性。您所選擇的實(shí)現(xiàn)將取決于應(yīng)用程序的特定需求。 XADataSource例子: <?xml version="1.0" encoding="UTF-8"?>
<!-- ===================================================================== --> <!-- --> <!-- JBoss Server Configuration --> <!-- Thanks to Horia Muntean <horia@bvb.ro> --> <!-- ===================================================================== -->
<!-- $Id: db2-xa-ds.xml,v 1.1.2.1 2003/05/30 18:25:57 d_jencks Exp $ -->
<datasources> <!-- XADatasource for DB2 V8.1 (app driver) copy $db2_install_dir/java/db2java.zip into $jboss_install_dir/server/default/lib -->
<xa-datasource> <jndi-name>DB2XADS</jndi-name> <xa-datasource-class>COM.ibm.db2.jdbc.DB2XADataSource</xa-datasource-class> <xa-datasource-property name="DatabaseName">yout_database_name</xa-datasource-property> <xa-datasource-property name="User">your_user</xa-datasource-property> <xa-datasource-property name="Password">your_password</xa-datasource-property> </xa-datasource> </datasources>
引用: http://www.jspcn.net/htmlnews/11049371131251752.html http://www-128.ibm.com/developerworks/cn/java/j-dao/ http://www.vermicelli.pasta.cs.uit.no/ipv6/students/andrer/doc/html/node18.html
33.2 基本的jms api概念
?? 33.2.1 jms api體系結(jié)構(gòu)
???? jms應(yīng)用程序組成部分:
????a. jms提供者--------j2ee平臺(tái).
??? b.jms客戶端--------需要用戶完成的應(yīng)用程序.
??? c.消息----在客戶端之間傳遞信息的對(duì)象
?? d.管理的對(duì)象----連接工廠和目的地
?33.2.2 消息域
???分為"點(diǎn)到點(diǎn)消息傳遞域"和"發(fā)表/訂閱小心傳遞域"
?33.2.3 消費(fèi)消息
???兩種方式:同步和異步.同步直接用receive方法提取消息.異步需要可湖段為消費(fèi)者注冊(cè)一個(gè)見聽器.通過調(diào)用見聽器的onMessage方法來(lái)分發(fā)消息.
33.3 jms api編程模型
? 33.3.1 管理的對(duì)象
?? a.連接工廠
??? 通常是執(zhí)行jndi查找獲得連接工廠.eg:
? Context ctx= new InitialContext();
? ConnectionFactory cf=(ConnectionFactory )?ctx.lookup("jms/QueueConnectionFactory");
ConnectionFactory cf=(ConnectionFactory )?ctx.lookup("jms/TopicConnectionFactory");
?b.目的地
?? 在ptp中,目的地是"隊(duì)列".在發(fā)表/訂閱中,目的地是"主題".
? eg:
Destination mydest=(Topic)ctx.lookup("jms/mytopic");
33.3.2 連接
?連接由連接工廠來(lái)創(chuàng)建.eg:
Connection conn=ConnectionFactory .createConnection();
33.3.3 會(huì)話
會(huì)話 由 Connection來(lái)創(chuàng)建
Session session=Connection.createSession(false,Session.AUTO_ACKOWLEDGE);
事務(wù)性的會(huì)話
Session session=Connection.createSession(true,0);
33.3.4 消息生產(chǎn)者
由session 來(lái)創(chuàng)建,實(shí)現(xiàn)MessageProducer接口.
?? MessageProducer mp=session.createProducer(myQueue);
發(fā)送動(dòng)作
mp.send(message);
33.3.5 消息消費(fèi)者
?由session創(chuàng)建,實(shí)現(xiàn)MessageConsumer接口.
eg:
MessageConsumer mc=session.createConsumer(myQueue);
bwt:
利用session.createDurableSubscriber可以創(chuàng)建長(zhǎng)期的訂閱者.
? ========獲得消息==
同步方式.
connection.start();
Message m=consumer.receive();
connection.start();
Message m=consumer.receive(1000); //time out afer a second
異步方式.
構(gòu)造一個(gè)消息艦艇器,用setMessageListener方法向具體的MessageConsumer中注冊(cè).eg:
? Listener myListener= new Listener ();
consumer.setMessageListener (myListener );
33.3.6 消息
分為消息頭,消息屬性和消息體,只有消息頭是必須的.
消息頭存放了可護(hù)短和提供者用來(lái)識(shí)別和路由消息的值.
常見的消息體的格式(消息類型)有5種.
?
?
六種異常處理的陋習(xí) 你覺得自己是一個(gè)Java專家嗎?是否肯定自己已經(jīng)全面掌握了Java的異常處理機(jī)制?在下面這段代碼中,你能夠迅速找出異常處理的六個(gè)問題嗎? 1 OutputStreamWriter out = ... 2 java.sql.Connection conn = ... 3 try { // ⑸ 4 Statement stat = conn.createStatement(); 5 ResultSet rs = stat.executeQuery( 6 "select uid, name from user"); 7 while (rs.next()) 8 { 9 out.println("ID:" + rs.getString("uid") // ⑹ 10 ",姓名:" + rs.getString("name")); 11 } 12 conn.close(); // ⑶ 13 out.close(); 14 } 15 catch(Exception ex) // ⑵ 16 { 17 ex.printStackTrace(); //⑴,⑷ 18 } 作為一個(gè)Java程序員,你至少應(yīng)該能夠找出兩個(gè)問題。但是,如果你不能找出全部六個(gè)問題,請(qǐng)繼續(xù)閱讀本文。 本文討論的不是Java異常處理的一般性原則,因?yàn)檫@些原則已經(jīng)被大多數(shù)人熟知。我們要做的是分析各種可稱為“反例”(anti-pattern)的違背優(yōu)秀編碼規(guī)范的常見壞習(xí)慣,幫助讀者熟悉這些典型的反面例子,從而能夠在實(shí)際工作中敏銳地察覺和避免這些問題。 反例之一:丟棄異常 代碼:15行-18行。 這段代碼捕獲了異常卻不作任何處理,可以算得上Java編程中的殺手。從問題出現(xiàn)的頻繁程度和禍害程度來(lái)看,它也許可以和C/C++程序的一個(gè)惡名遠(yuǎn)播的問題相提并論??不檢查緩沖區(qū)是否已滿。如果你看到了這種丟棄(而不是拋出)異常的情況,可以百分之九十九地肯定代碼存在問題(在極少數(shù)情況下,這段代碼有存在的理由,但最好加上完整的注釋,以免引起別人誤解)。 這段代碼的錯(cuò)誤在于,異常(幾乎)總是意味著某些事情不對(duì)勁了,或者說(shuō)至少發(fā)生了某些不尋常的事情,我們不應(yīng)該對(duì)程序發(fā)出的求救信號(hào)保持沉默和無(wú)動(dòng)于衷。調(diào)用一下printStackTrace算不上“處理異常”。不錯(cuò),調(diào)用printStackTrace對(duì)調(diào)試程序有幫助,但程序調(diào)試階段結(jié)束之后,printStackTrace就不應(yīng)再在異常處理模塊中擔(dān)負(fù)主要責(zé)任了。 丟棄異常的情形非常普遍。打開JDK的ThreadDeath類的文檔,可以看到下面這段說(shuō)明:“特別地,雖然出現(xiàn)ThreadDeath是一種‘正常的情形’,但ThreadDeath類是Error而不是Exception的子類,因?yàn)樵S多應(yīng)用會(huì)捕獲所有的Exception然后丟棄它不再理睬。”這段話的意思是,雖然ThreadDeath代表的是一種普通的問題,但鑒于許多應(yīng)用會(huì)試圖捕獲所有異常然后不予以適當(dāng)?shù)奶幚恚訨DK把ThreadDeath定義成了Error的子類,因?yàn)镋rror類代表的是一般的應(yīng)用不應(yīng)該去捕獲的嚴(yán)重問題。可見,丟棄異常這一壞習(xí)慣是如此常見,它甚至已經(jīng)影響到了Java本身的設(shè)計(jì)。 那么,應(yīng)該怎樣改正呢?主要有四個(gè)選擇: 1、處理異常。針對(duì)該異常采取一些行動(dòng),例如修正問題、提醒某個(gè)人或進(jìn)行其他一些處理,要根據(jù)具體的情形確定應(yīng)該采取的動(dòng)作。再次說(shuō)明,調(diào)用printStackTrace算不上已經(jīng)“處理好了異常”。 2、重新拋出異常。處理異常的代碼在分析異常之后,認(rèn)為自己不能處理它,重新拋出異常也不失為一種選擇。 3、把該異常轉(zhuǎn)換成另一種異常。大多數(shù)情況下,這是指把一個(gè)低級(jí)的異常轉(zhuǎn)換成應(yīng)用級(jí)的異常(其含義更容易被用戶了解的異常)。 4、不要捕獲異常。 結(jié)論一:既然捕獲了異常,就要對(duì)它進(jìn)行適當(dāng)?shù)奶幚怼2灰东@異常之后又把它丟棄,不予理睬。 反例之二:不指定具體的異常 代碼:15行。 許多時(shí)候人們會(huì)被這樣一種“美妙的”想法吸引:用一個(gè)catch語(yǔ)句捕獲所有的異常。最常見的情形就是使用catch(Exception ex)語(yǔ)句。但實(shí)際上,在絕大多數(shù)情況下,這種做法不值得提倡。為什么呢? 要理解其原因,我們必須回顧一下catch語(yǔ)句的用途。catch語(yǔ)句表示我們預(yù)期會(huì)出現(xiàn)某種異常,而且 希望能夠處理該異常。異常類的作用就是告訴Java編譯器我們想要處理的是哪一種異常。由于絕大多數(shù)異常都直接或間接從java.lang.Exception派生,catch(Exception ex)就相當(dāng)于說(shuō)我們想要處理幾乎所有的異常。 再來(lái)看看前面的代碼例子。我們真正想要捕獲的異常是什么呢?最明顯的一個(gè)是SQLException,這是JDBC操作中常見的異常。另一個(gè)可能的異常是IOException,因?yàn)樗僮鱋utputStreamWriter。顯然,在同一個(gè)catch塊中處理這兩種截然不同的異常是不合適的。如果用兩個(gè)catch塊分別捕獲SQLException和IOException就要好多了。這就是說(shuō),catch語(yǔ)句應(yīng)當(dāng)盡量指定具體的異常類型,而不應(yīng)該指定涵蓋范圍太廣的Exception類。 另一方面,除了這兩個(gè)特定的異常,還有其他許多異常也可能出現(xiàn)。例如,如果由于某種原因,executeQuery返回了null,該怎么辦?答案是讓它們繼續(xù)拋出,即不必捕獲也不必處理。實(shí)際上,我們不能也不應(yīng)該去捕獲可能出現(xiàn)的所有異常,程序的其他地方還有捕獲異常的機(jī)會(huì)??直至最后由JVM處理。 結(jié)論二:在catch語(yǔ)句中盡可能指定具體的異常類型,必要時(shí)使用多個(gè)catch。不要試圖處理所有可能出現(xiàn)的異常。 反例之三:占用資源不釋放 代碼:3行-14行。 異常改變了程序正常的執(zhí)行流程。這個(gè)道理雖然簡(jiǎn)單,卻常常被人們忽視。如果程序用到了文件、Socket、JDBC連接之類的資源,即使遇到了異常,也要正確釋放占用的資源。為此,Java提供了一個(gè)簡(jiǎn)化這類操作的關(guān)鍵詞finally。 finally是樣好東西:不管是否出現(xiàn)了異常,F(xiàn)inally保證在try/catch/finally塊結(jié)束之前,執(zhí)行清理任務(wù)的代碼總是有機(jī)會(huì)執(zhí)行。遺憾的是有些人卻不習(xí)慣使用finally。 當(dāng)然,編寫finally塊應(yīng)當(dāng)多加小心,特別是要注意在finally塊之內(nèi)拋出的異常??這是執(zhí)行清理任務(wù)的最后機(jī)會(huì),盡量不要再有難以處理的錯(cuò)誤。 結(jié)論三:保證所有資源都被正確釋放。充分運(yùn)用finally關(guān)鍵詞。 反例之四:不說(shuō)明異常的詳細(xì)信息 代碼:3行-18行。 仔細(xì)觀察這段代碼:如果循環(huán)內(nèi)部出現(xiàn)了異常,會(huì)發(fā)生什么事情?我們可以得到足夠的信息判斷循環(huán)內(nèi)部出錯(cuò)的原因嗎?不能。我們只能知道當(dāng)前正在處理的類發(fā)生了某種錯(cuò)誤,但卻不能獲得任何信息判斷導(dǎo)致當(dāng)前錯(cuò)誤的原因。 printStackTrace的堆棧跟蹤功能顯示出程序運(yùn)行到當(dāng)前類的執(zhí)行流程,但只提供了一些最基本的信息,未能說(shuō)明實(shí)際導(dǎo)致錯(cuò)誤的原因,同時(shí)也不易解讀。 因此,在出現(xiàn)異常時(shí),最好能夠提供一些文字信息,例如當(dāng)前正在執(zhí)行的類、方法和其他狀態(tài)信息,包括以一種更適合閱讀的方式整理和組織printStackTrace提供的信息。 結(jié)論四:在異常處理模塊中提供適量的錯(cuò)誤原因信息,組織錯(cuò)誤信息使其易于理解和閱讀。 反例之五:過于龐大的try塊 代碼:3行-14行。 經(jīng)常可以看到有人把大量的代碼放入單個(gè)try塊,實(shí)際上這不是好習(xí)慣。這種現(xiàn)象之所以常見,原因就在于有些人圖省事,不愿花時(shí)間分析一大塊代碼中哪幾行代碼會(huì)拋出異常、異常的具體類型是什么。把大量的語(yǔ)句裝入單個(gè)巨大的try塊就象是出門旅游時(shí)把所有日常用品塞入一個(gè)大箱子,雖然東西是帶上了,但要找出來(lái)可不容易。 一些新手常常把大量的代碼放入單個(gè)try塊,然后再在catch語(yǔ)句中聲明Exception,而不是分離各個(gè)可能出現(xiàn)異常的段落并分別捕獲其異常。這種做法為分析程序拋出異常的原因帶來(lái)了困難,因?yàn)橐淮蠖未a中有太多的地方可能拋出Exception。 結(jié)論五:盡量減小try塊的體積。 反例之六:輸出數(shù)據(jù)不完整 代碼:7行-11行。 不完整的數(shù)據(jù)是Java程序的隱形殺手。仔細(xì)觀察這段代碼,考慮一下如果循環(huán)的中間拋出了異常,會(huì)發(fā)生什么事情。循環(huán)的執(zhí)行當(dāng)然是要被打斷的,其次,catch塊會(huì)執(zhí)行??就這些,再也沒有其他動(dòng)作了。已經(jīng)輸出的數(shù)據(jù)怎么辦?使用這些數(shù)據(jù)的人或設(shè)備將收到一份不完整的(因而也是錯(cuò)誤的)數(shù)據(jù),卻得不到任何有關(guān)這份數(shù)據(jù)是否完整的提示。對(duì)于有些系統(tǒng)來(lái)說(shuō),數(shù)據(jù)不完整可能比系統(tǒng)停止運(yùn)行帶來(lái)更大的損失。 較為理想的處置辦法是向輸出設(shè)備寫一些信息,聲明數(shù)據(jù)的不完整性;另一種可能有效的辦法是,先緩沖要輸出的數(shù)據(jù),準(zhǔn)備好全部數(shù)據(jù)之后再一次性輸出。 結(jié)論六:全面考慮可能出現(xiàn)的異常以及這些異常對(duì)執(zhí)行流程的影響。 改寫后的代碼 根據(jù)上面的討論,下面給出改寫后的代碼。也許有人會(huì)說(shuō)它稍微有點(diǎn)?嗦,但是它有了比較完備的異常處理機(jī)制。 OutputStreamWriter out = ... java.sql.Connection conn = ... try { Statement stat = conn.createStatement(); ResultSet rs = stat.executeQuery( "select uid, name from user"); while (rs.next()) { out.println("ID:" + rs.getString("uid") + ",姓名: " + rs.getString("name")); } } catch(SQLException sqlex) { out.println("警告:數(shù)據(jù)不完整"); throw new ApplicationException("讀取數(shù)據(jù)時(shí)出現(xiàn)SQL錯(cuò)誤", sqlex); } catch(IOException ioex) { throw new ApplicationException("寫入數(shù)據(jù)時(shí)出現(xiàn)IO錯(cuò)誤", ioex); } finally { if (conn != null) { try { conn.close(); } catch(SQLException sqlex2) { System.err(this.getClass().getName() + ".mymethod - 不能關(guān)閉數(shù)據(jù)庫(kù)連接: " + sqlex2.toString()); } } if (out != null) { try { out.close(); } catch(IOException ioex2) { System.err(this.getClass().getName() + ".mymethod - 不能關(guān)閉輸出文件" + ioex2.toString()); } } } 本文的結(jié)論不是放之四海皆準(zhǔn)的教條,有時(shí)常識(shí)和經(jīng)驗(yàn)才是最好的老師。如果你對(duì)自己的做法沒有百分之百的信心,務(wù)必加上詳細(xì)、全面的注釋。 另一方面,不要笑話這些錯(cuò)誤,不妨問問你自己是否真地徹底擺脫了這些壞習(xí)慣。即使最有經(jīng)驗(yàn)的程序員偶爾也會(huì)誤入歧途,原因很簡(jiǎn)單,因?yàn)樗鼈兇_確實(shí)實(shí)帶來(lái)了“方便”。所有這些反例都可以看作Java編程世界的惡魔,它們美麗動(dòng)人,無(wú)孔不入,時(shí)刻誘惑著你。也許有人會(huì)認(rèn)為這些都屬于雞皮蒜毛的小事,不足掛齒,但請(qǐng)記住:勿以惡小而為之,勿以善小而不為。
摘要: Configuration
簡(jiǎn)介
?Configuration
的參數(shù)可能來(lái)自下面的資源:
??? *? Properties files??? * XML documents??? * Property list files (.plist)??? * JNDI??? * JDBC Datasource??? * System prope... 閱讀全文
官方地址: http://jakarta.apache.org/commons/lang/概述: ???標(biāo)準(zhǔn)的java庫(kù)并沒有提供足夠的處理他的核心類的方法, Lang組件提供了這些擴(kuò)展的方法 ???lang 組件為java.lang API提供了一套幫助類。特別是String處理方法,基本的數(shù)字處理方法,對(duì)象反射,創(chuàng)建和序列化和系統(tǒng)屬性。另外他包含了一個(gè)可繼承的 enum類型,一個(gè)exception結(jié)構(gòu),對(duì)java.util.Date的基本加強(qiáng)以及一系列構(gòu)建方法,比如hashCode,toString和equals 可以點(diǎn)擊下面的連接獲得體驗(yàn): http://www.j2medev.com/bbs/dispbbs.asp?boardid=3&id=3835&star=1&page=3http://www.sentom.net/list.asp?id=76?? lang.*
???? String字符串處理-StringUtils,StringEscapeUtils,RondomStringUtils,Tokenizer,WordUtils.??? RandomStringUtils 顧名思義,它提供了一段文本,常用來(lái)做默認(rèn)密碼的值。 StringEscapeUtils 包含了escape和unescape "java,javascript,html,xml和sql"的方法。 Tokenizer 是java.util.StringTokenizer的改良。 ?? 另外,WordUtils是另一個(gè)String處理類。他在String的單詞層次上工作,比如,WordUtils.capitalize方法會(huì)將一段文本中的每個(gè)單詞都首字母大寫。WordUtils也包含了包裝文本的方法。 ??? 字符處理- CharSetUtils, CharSet, CharRange, CharUtils字符的處理也很重要,CharUtils因此而存在。CharSetUtils則是為了對(duì)字符串作批處理。注意,盡管CharSetUtils接受一個(gè)String參數(shù),但卻把它當(dāng)成一組字符。比如:CharSetUtils.delete("testtest", "tr")將刪除所有的t和所有的r,而不僅僅是tr這個(gè)字符串。 CharRange和CharSet是CharSetUtils內(nèi)部將要用到的類。 JVM交互-SystemUtils, CharEncoding
SystemUtils是個(gè)很小的類,他將使你獲得你的JVM平臺(tái)信息變得更為簡(jiǎn)單。比如: SystemUtils.isJavaVersionAtLeast(1.3f) 。CharEncoding也是被用來(lái)做和jvm的交互,可能會(huì)被用來(lái)查看特定的環(huán)境上支持那種字符編碼。 序列化-SerializationUtils, SerializationException ?序列化并不難!一個(gè)簡(jiǎn)單的工具類就可以刈除你的痛苦。而且,他提供一個(gè)方法通過反序列化和重序列化來(lái)克隆對(duì)象,這是個(gè)很老的java訣竅。 Assorted functions -ObjectUtils,ClassUtils,ArrayUtils,BooleanUtils
? ObjectUtils提供了許多對(duì)對(duì)象便利的操作,以及大部分的對(duì)java.lang.Object的方法的null-safe實(shí)現(xiàn)。 ???ClassUtils提供了一套用于反射的幫助函數(shù)。值得留意的是在ClassUtils隱含的comparators,他可以對(duì)Class和package按名稱進(jìn)行排序。這個(gè)排序僅僅是字典排序。 ???接下來(lái),我們介紹ArrayUtils.他有很多方法和這些方法的重載方法。這個(gè)類值得我們深入的了解一下。開始之前,我們假設(shè)所有的被提及的方法都被重載(無(wú)論是基本類型還是對(duì)象類型)。而且,‘xxx’代表了一個(gè)基本類型,有時(shí)候也包含了對(duì)象。 - ArrayUtils 為基本類型提供了一個(gè)單態(tài)的空疏組.這些將被Collections API的toArray()方法中用到, 也可以在用在那些希望在發(fā)生錯(cuò)誤時(shí)返回空數(shù)組的方法中.
add(xxx[], xxx) 添加一個(gè)原始類型到一個(gè)數(shù)組, 自動(dòng)調(diào)整數(shù)組的大小. 對(duì)象類型可以用.
clone(xxx[]) 克隆一個(gè)基本類型或者對(duì)象數(shù)組.
contains(xxx[], xxx) 在一個(gè)基本類型或者對(duì)象類型的數(shù)組中查找一個(gè)基本類型或者對(duì)象類型.
getLength(Object) 返回一個(gè)數(shù)組的大小.如果參數(shù)不是一個(gè)數(shù)組,將會(huì)返回一個(gè)IllegalArgumentException異常。
- ?
hashCode(Object) , equals(Object, Object) , toString(Object) indexOf(xxx[], xxx) 和indexOf(xxx[], xxx, int) 是仿照String的相關(guān)方法,?但是他用來(lái)處理primitive/Object數(shù)組.?另外,?lastIndexOf?系列的方法也存在.
isEmpty(xxx[]) 判斷一個(gè)數(shù)組是否為null或者空.
isSameLength(xxx[], xxx[]) 判斷2個(gè)數(shù)組的大小是否相等.
- 除了添加的方法,?這里也提供了2類刪除的方法.?第一種是根據(jù)索引刪除:remove(xxx[], int),?第二種刪除數(shù)組中的第一個(gè)值:remove(xxx[], xxx).?
- ?
reverse(xxx[]) ?翻轉(zhuǎn)一個(gè)數(shù)組.
- The
subarray(xxx[], int, int) 取出一個(gè)大數(shù)組的一部分.
- 基本類型和基本類型的包裝類之間的轉(zhuǎn)換可以通過
toObject(xxx[]) 和toPrimitive(Xxx[]) 方法.
???ArrayUtils.toMap(Object[])用來(lái)將一個(gè)數(shù)組轉(zhuǎn)化為一個(gè)map,比如: ?????? Map colorMap = MapUtils.toMap(new String[][] {{ ?????????? {"RED", "#FF0000"}, ?????????? {"GREEN", "#00FF00"}, ?????????? {"BLUE", "#0000FF"} ?????? }); ???? BooleanUtils,對(duì)這個(gè)類,或許你有時(shí)候會(huì)對(duì)他的 BooleanUtils.toBoolean(String)方法感興趣。異常-IllegalClassException, IncompleteArgumentException, NotImplementedException, NullArgumentException, UnhandledException ?lang.builder.* ??提供了HashCodeBuilder,EqualsBuilder, CompareToBuilder, ToStringBuilder。筆者在項(xiàng)目中經(jīng)常用到HashCodeBuilder,具體用法參照文章前面給出的連接。 lang.enums.* (formerly lang.enum) ???他主要的功能就是為你的常量賦值,并且給定他們的順序. For example:
public final class ColorEnum extends Enum {
public static final ColorEnum RED = new ColorEnum("Red");
public static final ColorEnum GREEN = new ColorEnum("Green");
public static final ColorEnum BLUE = new ColorEnum("Blue");
private ColorEnum(String color) {
super(color);
}
public static ColorEnum getEnum(String color) {
return (ColorEnum) getEnum(ColorEnum.class, color);
}
public static Iterator iterator() {
return iterator(ColorEnum.class);
}
}
?
BeanUtils簡(jiǎn)介
|
|
這個(gè)組件的全稱是Bean Introspection Utilites。是屬于Jakarta Commons項(xiàng)目組的。主要是幫助構(gòu)建javabean的屬性操作的(getter,setter),已經(jīng)提供一種動(dòng)態(tài)定義和訪問bean的屬性。 接口摘要 Converter ?通用數(shù)據(jù)類型轉(zhuǎn)換器,可以被注冊(cè)、使用用來(lái)管理對(duì)象類型的轉(zhuǎn)換 DynaBean ?一個(gè)java對(duì)象,這個(gè)對(duì)象的屬性的名稱,數(shù)據(jù)類型和值都能被動(dòng)態(tài)改變 DynaClass ?java.lang.class的一個(gè)模擬,用來(lái)給其它類實(shí)現(xiàn)DynaBean接口(類似java.lang.Object和java.lang.Class的關(guān)系) MutableDynaClass ?一個(gè)DynaClass的專門的擴(kuò)展,允許屬性動(dòng)態(tài)的增加和減少。
類摘要
BasicDynaBean
? ??? DynaBean接口的最小實(shí)現(xiàn) BasicDynaClass? ??? ?DynaClass接口的最小實(shí)現(xiàn) BeanUtils? ??? 工具方法,通過反射組裝(populating)javabens的屬性。 BeanUtilsBean? ??? JavaBean屬性的總體方法 ConstructorUtils? ?? 提供反射工具方法,用于構(gòu)造函數(shù), MethodUtils與此相仿 ContextClassLoaderLocal? ?? ?A value that is provided per (thread) context classloader. 一個(gè)值,被提供了per (thread) context classloader. ConvertingWrapDynaBean? ?? DynaBean的一個(gè)實(shí)現(xiàn),包裝了標(biāo)準(zhǔn)的JavaBean實(shí)例,因此DynaBean APIs可以訪問他的屬性,盡管這些實(shí)現(xiàn)允許在屬性設(shè)值的時(shí)候發(fā)生類型轉(zhuǎn)換 ConvertUtils? 工具方法類,用于轉(zhuǎn)換String類型變量的值到特定的類型變量的值,String類型的數(shù)組到特定類型的數(shù)組。 ConvertUtilsBean?? 同上 DynaProperty? METADATA,描述了一個(gè)DynaBean的一個(gè)屬性 JDBCDynaClass? 提供常用的邏輯,用于JDBC實(shí)現(xiàn) DynaClass LazyDynaBean? 一種DynaBean,能夠自動(dòng)添加屬性到DynaClass,而且提供 Lazy List和Lazy Map的性質(zhì) LazyDynaClass? 一種DynaClass,實(shí)現(xiàn)了MutableDynaClass接口 LazyDynaMap? Provides a light weight DynaBean facade to a Map with lazy map/list processing. 為Map提供了輕量級(jí)的DynaBean facade ?MappedPropertyDescriptor?? 一個(gè)MappedPropertyDescriptor描述了一個(gè)map化的屬性 MethodUtils?? 工具映射方法類,應(yīng)用于一般方法而不是特定屬性。 ?MethodUtils.MethodDescriptor? Represents the key to looking up a Method by reflection. 代表了通過反射查找方法的KEY ? PropertyUtils?? 工具方法,用于利用Java Reflection APIs來(lái)幫助一般屬性getter and setter的操作在Java對(duì)象上。 ?PropertyUtilsBean?? 同上 ? ResultSetDynaClass?? DynaClass的實(shí)現(xiàn),用于 DynaBeans,DynaBeans包裝了java.sql.ResultSet的java.sql.Row對(duì)象 ? ResultSetIterator?? java.util.Iterator的實(shí)現(xiàn),用ResultSetDynaClass .的iterator()方法得到。 ? RowSetDynaClass?? DynaClass 的實(shí)現(xiàn),創(chuàng)建了一個(gè) 包含DynaBean的in-memory容器,代表了SQL查詢的結(jié)果。 ? WrapDynaBean?? DynaBean的實(shí)現(xiàn),他包裝了一個(gè)標(biāo)準(zhǔn)的JavaBean實(shí)例,因此DynaBean APIs可以被用來(lái)訪問它的屬性 ? WrapDynaClass?? DynaClass的實(shí)現(xiàn),用于包裝了標(biāo)準(zhǔn)的 JavaBean實(shí)例的DynaBeans ?
異常摘要
BeanAccessLanguageException
??? 用于指出Bean Access Language 不能再給出的bean上執(zhí)行查詢
ConversionException ????
用于指出對(duì)Converter.convert()的調(diào)用沒有成功
NestedNullException ??
用于指出Bean Access Language 不能再給出的bean上執(zhí)行查詢的原因是因?yàn)榍短椎腷ean引用為空
?
概要:?
背景:
JavaBeans 符合java api命名規(guī)范,它是它是java語(yǔ)言的組成體系之一。按照JavaBeans 設(shè)計(jì)模式可以帶來(lái)許多便利。
JavaBeans Specification描述了完整的一套特點(diǎn)用來(lái)把任意一個(gè)類變成JavaBeans ,你最好讀讀這個(gè)文檔,一些最基本的在此列出:
- ?? 類必須聲明為public,提供一個(gè)不帶參數(shù)的public構(gòu)造函數(shù)。這樣可以讓其他工具或者應(yīng)用程序動(dòng)態(tài)的創(chuàng)建這個(gè)類的實(shí)例,而不需要事先知道被使用的類的名字。比如:
String className = ...; ??????? Class beanClass = Class.forName(className); ??????? Object beanInstance = beanClass.newInstance();
- 作為不帶參數(shù)構(gòu)造函數(shù)的一個(gè)結(jié)果,類的初始化和bean的行為的配置必須完全分離。典型的做法是定義一套properties,用來(lái)修改它的行為和和這個(gè)bean代表的數(shù)據(jù)。屬性取名習(xí)慣做法是,以小寫字母開頭,由java合法字符組成。
- 典型的,每一個(gè)property都有一個(gè)public的getter和setter方法來(lái)分別設(shè)置和取回屬性的值 ,JavaBeans Specification 定義了這個(gè)規(guī)范。用get或者set作為前綴,并把屬性的第一個(gè)字母大寫緊跟其后。比如:
public class Employee { ??????????? public Employee();?? // Zero-arguments constructor ??????????? public String getFirstName(); ??????????? public void setFirstName(String firstName); ??????????? public String getLastName(); ??????????? public void setLastName(String lastName); ??????????? public Date getHireDate(); ??????????? public void setHireDate(Date hireDate); ??????????? public boolean isManager(); ??????????? public void setManager(boolean manager); ??????????? public String getFullName(); ??????? }
- 上面的例子,有個(gè)boolean值。boolean類型的屬性是以is為前綴的,這樣更容易理解。
- 如果你既有g(shù)etter又有setter,注意getter的返回值類型和setter的形參類型。另外,對(duì)同一個(gè)名字定義一個(gè)以上的類型不同的setter方法是和java規(guī)范不符的。
- 并不是每個(gè)屬性都需要get和set方法。由上面的例子我們就可以印證這一點(diǎn)。
- 創(chuàng)建一些get和set方法不符合上面的規(guī)范也是有可能的。具體的您可以參照完整的java規(guī)范。
- JavaBeans Specification 還定義了其他的一些規(guī)范。
用標(biāo)準(zhǔn)的java編碼技術(shù),在你事先知道調(diào)用的類,事先知道要關(guān)注的屬性的情況下處理javabeans 是十分方便的。
外部支持:
commons-beanutils 需要一下一些包來(lái)運(yùn)行:
Standard JavaBeans
背景:
如上所述,標(biāo)準(zhǔn)的寫法可以給你的使用帶來(lái)方便。但是當(dāng)你事先并不知道哪個(gè)類會(huì)被調(diào)用或者哪個(gè)屬性需要修改的時(shí)候怎么辦呢?java提供了一些類(比如java.beans.Introspector,他能夠在運(yùn)行時(shí)檢查類而且標(biāo)志出屬性的getter和setter方法),加上Reflection 機(jī)制來(lái)動(dòng)態(tài)調(diào)用方法。但是,這些方法很難使用,而且暴露了過多的程序使用者不需要了解的基本結(jié)構(gòu)的細(xì)節(jié),BeanUtils的APIs企圖簡(jiǎn)化動(dòng)態(tài)setter和getter的方法。
PropertyUtils很好的滿足我們的需求,這一章我們將深入介紹。
首先,這里來(lái)介紹一些深入的定義:
javabean提供的屬性可以分成三類,一些被標(biāo)準(zhǔn)的JavaBeans規(guī)范所支持,而一些只被BeanUtils所支持
- 簡(jiǎn)單類型(simple),最基本的屬性類型包括java最原始的數(shù)據(jù)類型(整形,字符串形),或者稍微復(fù)雜一點(diǎn)的對(duì)象。
- 索引類型(index),一個(gè)索引類型的屬性存儲(chǔ)了一個(gè)有序的對(duì)象(相同類型)容器,可以通過整型,非負(fù)索引值單獨(dú)訪問。或者,你可以干脆用一個(gè)數(shù)組來(lái)整體訪問這個(gè)屬性。作為JavaBeans specification擴(kuò)展,BeanUtils包認(rèn)為java.util.list類型的屬性也可以這樣來(lái)訪問。
- mapped,作為JavaBeans specification擴(kuò)展,BeanUtils包認(rèn)為java.util.map類型的屬性是map化,你可以設(shè)置和取回這個(gè)屬性通過String-valued鍵(key).
PropertyUtils
類中提共了get和set以上各種屬性類型的多種多樣的方法。在下面的代碼片斷中,假設(shè)這個(gè)類有兩個(gè)實(shí)例。
?public class Employee { ??????? public Address getAddress(String type); ??????? public void setAddress(String type, Address address); ??????? public Employee getSubordinate(int index); ??????? public void setSubordinate(int index, Employee subordinate); ??????? public String getFirstName(); ??????? public void setFirstName(String firstName); ??????? public String getLastName(); ??????? public void setLastName(String lastName); ??? } Basic Property Access(基本屬性訪問方式)
利用如下apis:
- PropertyUtils.getSimpleProperty(Object bean, String name)
- PropertyUtils.setSimpleProperty(Object bean, String name, Object value)
利用這些方法,你可以動(dòng)態(tài)操作這個(gè)對(duì)象,
Employee employee = ...; ??? String firstName = (String) ????? PropertyUtils.getSimpleProperty(employee, "firstName"); ??? String lastName = (String) ????? PropertyUtils.getSimpleProperty(employee, "lastName"); ??? ... manipulate the values ... ??? PropertyUtils.setSimpleProperty(employee, "firstName", firstName); ??? PropertyUtils.setSimpleProperty(employee, "lastName", lastName); For indexed properties, you have two choices,你有兩種選擇,可以參照下面的例子,要用到的APIS如下:
- PropertyUtils.getIndexedProperty(Object bean, String name)
- PropertyUtils.getIndexedProperty(Object bean, String name, int index)
- PropertyUtils.setIndexedProperty(Object bean, String name, Object value)
- PropertyUtils.setIndexedProperty(Object bean, String name, int index, Object value)
例子如下:
? Employee employee = ...; ??? int index = ...; ??? String name = "subordinate[" + index + "]"; ??? Employee subordinate = (Employee) ????? PropertyUtils.getIndexedProperty(employee, name);
??? Employee employee = ...; ??? int index = ...; ??? Employee subordinate = (Employee) ????? PropertyUtils.getIndexedProperty(employee, "subordinate", index); 對(duì)于mapped屬性,也有兩種方式。先參照apis
- PropertyUtils.getMappedProperty(Object bean, String name)
- PropertyUtils.getMappedProperty(Object bean, String name, String key)
- PropertyUtils.setMappedProperty(Object bean, String name, Object value)
- PropertyUtils.setMappedProperty(Object bean, String name, String key, Object value)
例子:
Employee employee = ...; ??? Address address = ...; ??? PropertyUtils.setMappedProperty(employee, "address(home)", address);
??? Employee employee = ...; ??? Address address = ...; ??? PropertyUtils.setMappedProperty(employee, "address", "home", address);
Nested Property Access(嵌套屬性訪問方式)
如果你的屬性也是一個(gè)對(duì)象,你想訪問屬性對(duì)象的屬性時(shí),該怎么訪問呢?
或許,用標(biāo)準(zhǔn)的java技術(shù)直接訪問這個(gè)屬性,會(huì)寫成這樣:
String city = employee.getAddress("home").getCity();
用PropertyUtils類的如下apis:
- PropertyUtils.getNestedProperty(Object bean, String name)
- PropertyUtils.setNestedProperty(Object bean, String name, Object value)
我們可以這樣啊來(lái)訪問:
String city = (String) ????? PropertyUtils.getNestedProperty(employee, "address(home).city");
為了方便,PropertyUtils提供了一般化的訪問方式,可以訪問任意嵌套,sample,indexed,mapped類型的屬性
- PropertyUtils.getProperty(Object bean, String name)
- PropertyUtils.setProperty(Object bean, String name, Object value)
例子:
Employee employee = ...; ??? String city = (String) PropertyUtils.getProperty(employee, ????? "subordinate[3].address(home).city");
Dynamic Beans (DynaBeans)
背景
PropertyUtils如前所述被設(shè)計(jì)用來(lái)訪問存在的class的屬性的訪問方式,而不是以任何方式修改他們。一個(gè)不同的動(dòng)態(tài)屬性訪問案例是,當(dāng)你有一套合適的動(dòng)態(tài)屬性,想用一個(gè)javabean來(lái)展示,但是你并不想真實(shí)的寫出一個(gè)類文件。除了不必保存和創(chuàng)建一個(gè)單獨(dú)的class文件,它的功能意味著你可以處理這樣一些情況,在這種情況下,你所關(guān)心的屬性值是動(dòng)態(tài)決定的。(比如sql語(yǔ)句查詢出來(lái)的結(jié)果)。
為了支持這種情況,BeanUtils提供了DynaBean接口。通過實(shí)現(xiàn)他的接口方法可以實(shí)現(xiàn)他。并且與DynaClass 接口相關(guān)聯(lián)。DynaClass 接口 定義了一個(gè)特定的DynaBean的組的屬性。就像java.lang.Class定義了所有的javabean實(shí)例的屬性一樣。
據(jù)個(gè)例子:
如果上面例子中的Employee是DynaBean的實(shí)現(xiàn)。那么我們可以這樣來(lái)訪問它的屬性。
DynaBean employee = ...; // Details depend on which ???????????????????????????? // DynaBean implementation you use ??? String firstName = (String) employee.get("firstName"); ??? Address homeAddress = (Address) employee.get("address", "home"); ??? Object subordinate = employee.get("subordinate", 2); 注意:PropertyUtils的屬性getter和setter方法知道如何訪問DynaBean的屬性。因此,你可以把你的應(yīng)用中的所有屬性訪問方式都用PropertyUtils APIs。這樣你就可以不用事先考慮某個(gè)特定bean到底是如何實(shí)現(xiàn)的。
因?yàn)?DynaBean?和 DynaClass都是接口,他們需要頻繁的,很多不同場(chǎng)合地被實(shí)現(xiàn)。下面的章節(jié)提供了一些標(biāo)準(zhǔn)的beanutils包,當(dāng)然,如果不符合您的要求,您也可以自己去實(shí)現(xiàn)他們。
BasicDynaBean and BasicDynaClass
? BasicDynaBean和BasicDynaClass提供了一套基本的動(dòng)態(tài)屬性性能,可以應(yīng)用在你需要?jiǎng)討B(tài)定義屬性(是DynaProperty的實(shí)例)的時(shí)候。你需要先創(chuàng)建DynaClass來(lái)保存你將要用的一套屬性。
例如:
DynaProperty[] props = new DynaProperty[]{ ??????? new DynaProperty("address", java.util.Map.class), ??????? new DynaProperty("subordinate", mypackage.Employee[].class), ??????? new DynaProperty("firstName", String.class), ??????? new DynaProperty("lastName",? String.class) ????? }; ??? BasicDynaClass dynaClass = new BasicDynaClass("employee", null, props);
注意,dynaBeanClass得引數(shù)(在BasicDynaClass的構(gòu)造函數(shù)中)可以為空。在這種情況下,dynaClass.getDynaBeanClass的值僅僅只是BasicDynaBean的類(In this case, the value of dynaClass.getDynaBeanClass will just be the Class for BasicDynaBean)。
另外,你用DynaClass的newInstance()方法來(lái)實(shí)例化一個(gè)符合DynaClass的DynaBean實(shí)例,然后給他的屬性賦初始值。(和你實(shí)例一個(gè)普通的javabean,然后賦值,是一樣的)。
DynaBean employee = dynaClass.newInstance(); ??? employee.set("address", new HashMap()); ??? employee.set("subordinate", new mypackage.Employee[0]); ??? employee.set("firstName", "Fred"); ??? employee.set("lastName", "Flintstone");
注意你可以這里的DynaBean類可以聲明為DynaBean取代了BasicDynaBean。一般的,如果你使用DynaBeans,你不會(huì)在意DynaBeans的具體的實(shí)際實(shí)現(xiàn)---你只是在乎它是一個(gè)DynaBeans,而且可以用DynaBeans的apis.
?如上面所講的,你可以傳遞一個(gè)DynaBean實(shí)例作為第一個(gè)引數(shù)給PropertyUtils訪問和設(shè)置屬性的方法,而且它會(huì)如你所愿的被解釋---DynaBean 的動(dòng)態(tài)屬性可以被取回和修改。
ResultSetDynaClass (Wraps ResultSet in DynaBeans)
? 一個(gè)很普通的DynaBean 的USER CASE就是用它來(lái)包裝其他原始集合,這些集合不是以JAVABEAN的形式展示的。最常見的情況就是當(dāng)你請(qǐng)求JDBC驅(qū)動(dòng)查詢SQL語(yǔ)句返回java.sql.ResultSet類型的記錄的時(shí)候,BeanUtils提供了標(biāo)準(zhǔn)的機(jī)制來(lái)把每一行resultset轉(zhuǎn)變?yōu)橐粋€(gè) DynaBean,參照下列:
Connection conn = ...; ? Statement stmt = conn.createStatement(); ? ResultSet rs = stmt.executeQuery ??? ("select account_id, name from customers"); ? Iterator rows = (new ResultSetDynaClass(rs)).iterator(); ? while (rows.hasNext()) { ??? DynaBean row = (DynaBean) rows.next(); ??? System.out.println("Account number is " + ?????????????????????? row.get("account_id") + ?????????????????????? " and name is " + row.get("name")); ? } ? rs.close(); ? stmt.close();
RowSetDynaClass (Disconnected ResultSet as DynaBeans)
盡管ResultSetDynaClass是一個(gè)用來(lái)展示sql查詢的很好的技術(shù)(當(dāng)成DynaBean),但是最大的問題就是在MVC的結(jié)構(gòu)之中,我們需要離線的取出查詢的所有數(shù)據(jù),而ResultSetDynaClass必須保持和數(shù)據(jù)庫(kù)相連。
RowSetDynaClass展示了解決這個(gè)問題的不同方法。當(dāng)你構(gòu)造這樣的實(shí)例,那些原始的數(shù)據(jù)被復(fù)制到一系列in-memory 的DynaBeans來(lái)代表這些結(jié)果。這個(gè)技術(shù)的優(yōu)勢(shì)是,理所當(dāng)然,你可以立即關(guān)閉ResultSet(和他相連的Statement),這些操作都可以在你處理被返回的數(shù)據(jù)之前。缺點(diǎn)就是,你需要為復(fù)制數(shù)據(jù)所需要的性能和內(nèi)存買單,而且數(shù)據(jù)的大小還得讓堆內(nèi)存可以適合。在許多情況下(特別是WEB APPS),這種折衷是有益處的。
? 額外的方便就是,RowSetDynaClass 被定義為java.io.Serializable的實(shí)現(xiàn),因此它可以被序列化和反序列化。因此RowSetDynaClass展示了一種十分便利的方法來(lái)傳輸SQL結(jié)果到遠(yuǎn)程Java-based 客戶端應(yīng)用程序(比如APPLET).
?基本的RowSetDynaClass使用模式如下所示:
Connection conn = ...;? // Acquire connection from pool ??? Statement stmt = conn.createStatement(); ??? ResultSet rs = stmt.executeQuery("SELECT ..."); ??? RowSetDynaClass rsdc = new RowSetDynaClass(rs); ??? rs.close(); ??? stmt.close(); ??? ...;??????????????????? // Return connection to pool ??? List rows = rsdc.getRows(); ??? ...;?????????????????? // Process the rows as desired
WrapDynaBean and WrapDynaClass
?下面的E文比較EASY,偶偷懶不翻了,
OK, you've tried the DynaBeans APIs and they are cool -- very simple get() and set() methods provide easy access to all of the dynamically defined simple, indexed, and mapped properties of your DynaBeans. You'd like to use the DynaBean APIs to access all of your beans, but you've got a bunch of existing standard JavaBeans classes to deal with as well. This is where the WrapDynaBean (and its associated WrapDynaClass) come into play. As the name implies, a WrapDynaBean is used to "wrap" the DynaBean APIs around an existing standard JavaBean class. To use it, simply create the wrapper like this: MyBean bean = ...; DynaBean wrapper = new WrapDynaBean(bean); String firstName = wrapper.get("firstName");
Note that, although appropriate WrapDynaClass instances are created internally, you never need to deal with them. Lazy DynaBeans(LazyDynaBean, LazyDynaMap and LazyDynaClass) ? 你鐘情于DynaBeans是因?yàn)橛辛怂悴槐貙?duì)每個(gè)pojo來(lái)編碼成一個(gè)class文件。這樣能夠?qū)崿F(xiàn)的原因是因?yàn)閘azy--延遲加載。是以下的一些特性使得DynaBeans可以lazy: - ? Lazy property addition (lazy屬性添加)---lazy beans 使用 實(shí)現(xiàn)了MutableDynaClass 接口的DynaClass,DynaClass提供了添加和刪除屬性的能力。當(dāng)set方法調(diào)用的時(shí)候,Lazy beans 利用這個(gè)特性來(lái)自動(dòng)添加DynaClass中沒有的屬性
- Lazy List/Array growth(lazy list/array 增長(zhǎng))---如果一個(gè)索引化的屬性沒有足夠的容量來(lái)容納要設(shè)置的屬性,那么List or Array 將會(huì)自動(dòng)增長(zhǎng)。
- Lazy List/Array instantiation(Lazy List/Array實(shí)例化) ---如果一個(gè)索引化的屬性并不存在,那么他將會(huì)調(diào)用 DynaBean的indexed property getter/setter methods(比如 get(name, index) or set(name, index, value))返回一個(gè)List 或者一個(gè)Array實(shí)例。如果一個(gè)索引化的屬性沒有在DynaClass中被定義,那么他將會(huì)被自動(dòng)添加而且生成一個(gè)默認(rèn)的list實(shí)現(xiàn)的實(shí)例。
- Lazy Map instantiation-------if a mapped property doesn't exist then calling the DynaBean's mapped property getter/setter methods (i.e. get(name, key) or set(name, key, value)) results in a new Map being instantiated. If the mapped property has not been defined in the DynaClass then it is automatically added and a default Map implementation instantiated.
- Lazy Bean instantiation -------如果一個(gè)DynaClass 中的屬性被定義成DynaBean 或者普通的bean,但是這個(gè)屬性并不在DynaBean中存在,那么LazyDynaBean將會(huì)采用默認(rèn)的empty constructor來(lái)實(shí)例化這個(gè) bean
LazyDynaBean 標(biāo)準(zhǔn)lazy bean 的實(shí)現(xiàn)。默認(rèn)和實(shí)現(xiàn)了MutableDynaClass接口的LazyDynaClass相關(guān)聯(lián)---盡管他可以和MutableDynaClass的任何實(shí)現(xiàn)一起使用。例子如下: ?DynaBean dynaBean = new LazyDynaBean();
??? dynaBean.set("foo", "bar");?????????????????? // simple
??? dynaBean.set("customer", "title", "Mr");????? // mapped ??? dynaBean.set("customer", "surname", "Smith"); // mapped
??? dynaBean.set("address", 0, addressLine1);???? // indexed ??? dynaBean.set("address", 1, addressLine2);???? // indexed ??? dynaBean.set("address", 2, addressLine3);???? // indexed LazyDynaMap light wieght (輕量級(jí))DynaBean facade to a Map with all the usual lazy features。之所以是輕量級(jí),是因?yàn)樗麤]有和一個(gè)包含所有屬性的DynaClass相關(guān)連。事實(shí)上,他親自實(shí)現(xiàn)了DynaClass。一個(gè)LazyDynaMap可以用來(lái)包裝一個(gè)存在的map,也可以自己去實(shí)例化一個(gè)Map實(shí)例 例如:? If you need a new Map then to use.... DynaBean dynaBean = new LazyDynaMap(); // create DynaBean dynaBean.set("foo", "bar"); // simple dynaBean.set("customer", "title", "Mr"); // mapped dynaBean.set("address", 0, addressLine1); // indexed Map myMap = dynaBean.getMap() // retrieve the Map
or to use with an existing Map .... Map myMap = .... // exisitng Map DynaBean dynaBean = new LazyDynaMap(myMap); // wrap Map in DynaBean dynaBean.set("foo", "bar");
LazyDynaClass 繼承BasicDynaClass并實(shí)現(xiàn)MutableDynaClass接口。 Either create a LazyDynaClass first... MutableDynaClass dynaClass = new LazyDynaClass(); // create DynaClass dynaClass.add("amount", java.lang.Integer.class); // add property dynaClass.add("orders", OrderBean[].class); // add indexed property dynaClass.add("orders", java.util.TreeMapp.class); // add mapped property DynaBean dynaBean = new LazyDynaBean(dynaClass); // Create DynaBean with associated DynaClass
or create a LazyDynaBean and get the DynaClass... DynaBean dynaBean = new LazyDynaBean(); // Create LazyDynaBean MutableDynaClass dynaClass = (MutableDynaClass)dynaBean.getDynaClass(); // get DynaClass dynaClass.add("amount", java.lang.Integer.class); // add property dynaClass.add("myBeans", myPackage.MyBean[].class); // add 'array' indexed property dynaClass.add("myMap", java.util.TreeMapp.class); // add mapped property
?注意: MutableDynaClass 有一種受限(Restricted)屬性。When the DynaClass is restricted ,no properties can be added or removed from the DynaClass. Neither the LazyDynaBean or LazyDynaMap will add properties automatically if the DynaClass is restricted.
關(guān)于Converters和Collections方面的知識(shí)本文不做翻譯。 |
|