
2006年7月29日
1 基本介紹
可以說CSV格式的文件經常碰到,何為CSV格式,CVS全稱comma-separated values,就是典型的用逗號隔開的文件,比如下面這種文件格式
Name,company
zhangsan,ibm
lisi,oracle
這種就是典型的CSV格式文件。不過也可以擴展到其它符號隔開的字符,比如
Name#company
Zhangsan#ibm
Lisi#oracle
這種也算CSV格式
Java開源框架CVSReader提供了一個輕量級、簡單方便的統一操作接口可用,下面具體講解如何操作CVS格式
2 安裝和使用
2.1下載
目前CSV reader的最新發布版本是1.8。我們可以從
http://opencsv.sourceforge.net/
上面下載到最新的csvreader包。
2.2安裝
直接把jar包分別存放到開發工程的類路徑下面即可使用。
3 讀取CSV格式文件
3.1基本簡介
首先,讀取CSV格式的文件需要創建一個CSVReader,如下
CsvReader reader = new CsvReader(Reader r, char c);
其中第一個參數為讀取文件,第二個參數為分割符,比如“,”,或者“#”
另外,也有其它幾個參數,可以查閱API,比如
CsvReader reader = new CsvReader(InputStream r, char c, Charset charset);等等
其次,一般需要讀取頭信息,如下:
reader.readHeaders();
String[] headers = reader.getHeaders();
讀取了后,指針就會移動到下一行,也就是可以開始讀取文件內容
假如,有多行的話,可以用一個循環套入,例如下面:
while (reader.readRecord()) {
for (int i = 0; i < headers.length; i++) {
String value = reader.get(headers[i]);
System.out.print(value+" ");
}
System.out.println("");
}
3.2綜合例子
在C盤下創建一個測試文件test.cvs,內容如下:
a#b#c
1#2#3
4#5#6
下面是解析代碼:
public static void main(String[] args) throws Exception {
CsvReader reader = new CsvReader(new FileReader("c://csv.txt"), '#');
reader.readHeaders();
String[] headers = reader.getHeaders();
while (reader.readRecord()) {
for (int i = 0; i < headers.length; i++) {
String value = reader.get(headers[i]);
System.out.print(value+" ");
}
System.out.println("");
}
}
運行以上程序,可以看到輸出
1 2 3
4 5 6
4 寫CSV格式文件
寫CSV格式文件也比較簡單,寫每一列只要直接調用
csvWriter.write()即可
另外,寫完每行結束后,都要調用 csvWriter.endRecord();
表示結束一行
文件寫完畢后,要記得刷新一下并關掉,如下:
csvWriter.flush();
csvWriter.close();
代碼如下:
publicstaticvoid main(String[] args) throws Exception {
CsvWriter csvWriter = new CsvWriter(new FileWriter("c://test.text"), '#');
csvWriter.write("name");
csvWriter.write("company");
csvWriter.endRecord();
csvWriter.write("11");
csvWriter.write("12");
csvWriter.endRecord();
csvWriter.write("21");
csvWriter.write("22");
csvWriter.flush();
csvWriter.close();
}
}
運行以上程序,可以看到C盤下面創建了一個文件
test.text
內容如下:
name#company
11#12
21#22
posted @
2008-10-31 14:42 jspark 閱讀(11805) |
評論 (3) |
編輯 收藏
摘要: (本文檔的全篇可以到博客下面的文件列表下載,地址下面)
http://m.tkk7.com/jspark/admin/Files.aspx
為了讓盡快對jbossRules有一個感官的認識,下面先開發一個HelloWorld的程序。
建立一個java工程,目錄如下:
如上所示,建立一個com包,然后在下面分別建立一個Sa...
閱讀全文
posted @
2008-10-28 15:54 jspark 閱讀(1634) |
評論 (0) |
編輯 收藏
1 Java規則系統簡介
在大型商業系統中,業務規則、商業邏輯等等都會比較復雜。而且在很多大型系統當中,很多業務規則、商業邏輯并不是一成不變的。甚至當系統進入生產階段時,客戶的業務規則、商業邏輯也會改變。某些系統要求甚至更高,要求能24小時不停機,并且能夠實時修改商業規則。這就對商業系統提出了較大的挑戰。如果將這些可變的規則直接編寫到代碼里面的話,業務規則一旦改變,就要修改代碼。并由此帶來編譯、打包、發布等等問題。這對于生產系統來說是極不方便的。因此,如何考慮把一些可變的業務規則抽取到外面,使這些業務規則獨立于程序代碼。并最好是能夠實時的修改業務規則,這樣就可以做到不用打包編譯發布等等。
值得慶幸的是現在出現了一些Java規則引擎(Rule Engine),專門解決以上所述的問題。利用它,我們就可以在應用系統中分離客戶的商業決策邏輯和應用開發者的技術決策,并把這些商業規額則放在中心數據庫或其他統一的地方,讓它們能在運行時可以動態地管理和修改。
JbossRules是一個優秀的JAVA規則引擎,其前身是Drools3,后來被Jboss合并并改名為JbossRules
1.1基于規則的專家系統簡介
人工智能是一個新興的學科,它是想讓計算機模擬人腦的思維和推理模式。人工智能分成如下幾個主要的分學科:
知識表示
神經網絡
基因算法
決策樹
專家系統
等等幾個學科
知識表示是人工智能中的一個基礎領域,其目的是如何更好的在計算機當中描述已存在的事實。專家系統就是使用知識表示,來做規則推理,得出最后的結論來。
Java規則引擎起源于基于規則的專家系統,而基于規則的專家系統又是專家系統的其中一個分支。專家系統屬于人工智能的范疇,它模仿人類的推理方式,使用試探性的方法進行推理,并使用人類能理解的術語解釋和證明它的推理結論。為了更深入地了解Java規則引擎,下面簡要地介紹基于規則的專家系統。RBES包括三部分:Rule Base(knowledge base)、Working Memory(fact base)和Inference Engine。它們的結構如下系統所示:
如上圖所示,推理引擎包括三部分:模式匹配器(Pattern Matcher)、議程(Agenda)和執行引擎(Execution Engine)。推理引擎通過決定哪些規則滿足事實或目標,并授予規則優先級,滿足事實或目標的規則被加入議程。模式匹配器決定選擇執行哪個規則,何時執行規則;議程管理模式匹配器挑選出來的規則的執行次序;執行引擎負責執行規則和其他動作。
和人類的思維相對應,推理引擎存在兩者推理方式:演繹法(Forward-Chaining)和歸納法(Backward-Chaining)。演繹法從一個初始的事實出發,不斷地應用規則得出結論(或執行指定的動作)。而歸納法則是根據假設,不斷地尋找符合假設的事實。Rete算法是目前效率最高的一個Forward-Chaining推理算法,許多Java規則引擎都是基于Rete算法來進行推理計算的。
l 正向推理:
正向推理圖形如下:
正向推理引擎的推理步驟如下:
n 將初始數據(fact)輸入Working Memory。
n 使用Pattern Matcher比較規則庫(rule base)中的規則(rule)和數據(fact)。
n 如果執行規則存在沖突(conflict),即同時激活了多個規則,將沖突的規則放入沖突集合。
n 解決沖突,將激活的規則按順序放入Agenda。
n 使用執行引擎執行Agenda中的規則。重復步驟2至5,直到執行完畢所有Agenda中的規則。
n 直到得出最終的結果為止
l 反向推理:
反向推理是目標驅動的推理方式。從目標出發,找出所有能滿足該目
標的子目標。這樣一直推導下去,直到所有的子目標都已經滿足為止。
1.2Java規則引擎
Java規則引擎是一種嵌入在Java程序中的組件,它的任務是把當前提交給引擎的Java數據對象與加載在引擎中的業務規則進行測試和比對,激活那些符合當前數據狀態下的業務規則,根據業務規則中聲明的執行邏輯,觸發應用程序中對應的操作。
一般來說,一條規則的形式如下:
when
<conditions>
then
<actions>
也就是說,當conditions成立的話,就做下面的actions。其中actions可以為生成新的事實、或者做其他動作,比如,發送email通知、執行一些本地任務等等。
1.3 JAVA規則引擎的優點
n 聲明式編程
聲明式編程,規則引擎讓我們直到“做什么”,而不用直到“怎么做”。我們只要把一系列規則表示出來后。具體的推理動作就交給規則引擎來處理。
n 邏輯和數據分開
將可變的業務邏輯和數據分開。雖然,這違背了面向對象原則。面向對象強調數據和業務邏輯耦合。但是,對于一些易變而復雜的業務規則。如果散步在程序的各個地方、各個層次。那么一旦業務規則更改的話,就會出現“牽一發而動全身”的局面。因此,將可變的業務邏輯獨立出來管理,將有助于后面的業務變更。
n 性能
Rete算法的性能比較高。
n 知識集中表示
通過使用規則,我們把規則集中存放起來,從而使系統知識能夠集中表示。
n 可讀性
規則的可讀性比較高。對于熟悉業務規則。但不會程序開發的業務專家,只要熟悉規則的標示,也可以編寫和修改業務規則。
1.4 使用JAVA規則系統的場合
那么,在那些場合下適合應用JAVA規則系統呢?總而言之,可以用一句話來概括:當用傳統的程序開發,無法得到一種優雅的解決方法的時候,就可以考慮使用規則系統。如下的一些場合:
n 用傳統的代碼開發比較復雜、繁瑣
n 問題雖然不復雜,但是用傳統的代碼開發比較脆弱,也就是經常修改
n 沒有優雅的算法
n 業務規則頻繁改變
n 有很多業務專家、不懂技術開發
1.5 不適合使用JAVA規則系統場合
雖然規則系統看起來比較不錯,但是并不是任何地方都可以使用規則系統。很多簡單、固定的業務系統,可以不用使用規則系統。規則系統也不能用來作為標示重要的業務流程、不能用來作為工作流引擎。
有很多程序員把JAVA規則系統當成是一種動態修改配置。也就是把一部分代碼邏輯抽取到外面,統一存放起來。這樣,當一些配置修改的話,通過修改規則,就能修改代碼的一部分邏輯。如果把JAVA規則僅僅用在這個場合下的話,可以考慮采用腳本引擎。比如BeanShell、JEXL、Groovy等等。
posted @
2008-10-28 12:15 jspark 閱讀(1562) |
評論 (1) |
編輯 收藏
grant {
permission java.lang.RuntimePermission "loadLibrary.*";
permission java.lang.RuntimePermission "queuePrintJob";
permission java.lang.RuntimePermission "setContextClassLoader";
permission java.lang.RuntimePermission "getProtectionDomain";
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
grant {
permission java.util.PropertyPermission "*" , " read,write " ;
};
最近一個項目需要用到SUN ONE APPSERVER8.1,本人在WINDOWS SERVER 2003中安裝,碰到一些問題,不過比較幸運的是都解決了,下面大概描述一下個人碰到的問題,期望能給別人帶來幫助
一、DNS服務器問題
安裝SUN ONE APPSERVER8.1必須要在服務器上安裝,而且必須要將該服務器設置為DNS服務器。關于WINDOWS SERVER 2003
如何設置DNS服務器,網上很多資料,可以查閱
二、文件系統權限訪問問題
也許SUN ONE APPSERVER8.1服務器在文件訪問方面控制比較嚴格,如果按照默認安裝上去的系統。對于一些文件夾、文件讀取是會有一些控制的。比如說,當將應用部署上去,然后訪問應用,會拋出SecurityException。這是因為需要編譯jsp頁面,生成class文件,由于沒有寫權限,所以會出錯。解決的方法是為SUN ONE APPSERVER增加文件訪問權限。修改方法如下:
找到安裝路徑,下面以本人的安裝路徑為例子:
c\sunjes\ApplicationServer\domains\domain1\config
該目錄下面有一個文件叫server.policy,打開該頁面,可以看到里面是一些關于文件訪問權限的例子

// Core server classes get all permissions by default
grant codeBase " file:${com.sun.aas.installRoot}/lib/- " {
permission java.security.AllPermission;
};

下面為文件路徑增加訪問權限,個人把整個c盤設置為可讀可寫,如下
grant codeBase " file:c:/- " {
permission java.security.AllPermission;
};
grant {
permission java.io.FilePermission " c:/- " , " read,write,execute,delete " ;
};
編輯完畢,保存,重啟服務器,OK,該問題解決。 :)
三、其他幾個權限問題:
編輯以上問題后,重新自動,可能還會發現以下幾個異常,比如 permission java.util.PropertyPermission "*" , " read,write " ;
因此,分別加上如下幾個權限設置即可
四、ORACLE10.2.0.1驅動問題
本人部署的應用是spring+hb架構,里面用到blog/clob大字段處理,因此驅動程序用最新的驅動程序10g,版本為10.2.0.1。在部署到SUN ONE APPSERVER8.1時,也拋出類訪問異常,異常信息是:oracle.sql is sealed。沒辦法,上網搜索了一下,發現有很多人也遇過這個情況。主要是oracle10g.jar里面的Meta-inf定義,增加了sealed屬性。打開該文件MANIFEST.MF,內容如下:
Manifest - Version: 1.0
Specification - Title: Oracle JDBC driver classes for use with JDK14
Created - By: 1.4 .2_08 (Sun Microsystems Inc.)
sealed: true
Implementation - Title: ojdbc14.jar
Specification - Vendor: Oracle Corporation
Specification - Version: Oracle JDBC Driver version - " 10.2.0.1.0 "
Implementation - Version: Oracle JDBC Driver version - " 10.2.0.1.0 "
Implementation - Vendor: Oracle Corporation
Implementation - Time: Wed Jun 22 18 : 55 : 48 2005
關于sealed屬性網上也有
很多資料介紹,有興趣的網友可以參閱一下。網上同行的解決方法是下載10g,低點的版本。本人的解決方法是修改一下里面的MANIFEST.MF文件,把sealed:true去掉即可。
四、包版本不兼容。
解決完以上幾個問題后,重新啟動,本以為萬事大吉,很不幸運的是,再次拋出異常:
ClassNotFoundException: org.hibernate.hql.ast.HqlToken。同樣,上網搜索了一下,發現是hibernate的antlr.jar和SUN ONE APPSERVER的antlr.jar存在沖突。hibernate3.0版本用
的antlr.jar包版本是2.7.5,比SUN ONE APPSERVER的高。以前在weblogic部署應用時,也出現過類似的問題。由于這些服務器會優先裝載自己的類,因此會出現一些問題。解決方法是把hibernate下較高版本的antlr.jar放在classpath的前面。在SUN ONE APPSERVER
下最快捷的方式就是將antlr-2.7.5H3.jar拷貝到ApplicationServer\lib目錄下面即可
解決完以上幾個問題后,再次重啟,訪問,OK,一切正常!好有成就感 :)
posted @
2006-11-29 14:42 jspark 閱讀(1687) |
評論 (1) |
編輯 收藏
Sun HotSpot 1.4.1 JVM堆大小的調整
????
????Sun HotSpot 1.4.1使用分代收集器,它把堆分為三個主要的域:新域、舊域以及永久域。Jvm生成的所有新對象放在新域中。一旦對象經歷了一定數量的垃圾收集循環后,便獲得使用期并進入舊域。在永久域中jvm則存儲class和method對象。就配置而言,永久域是一個獨立域并且不認為是堆的一部分。
????下面介紹如何控制這些域的大小。可使用-Xms和-Xmx 控制整個堆的原始大小或最大值。
????下面的命令是把初始大小設置為128M:
????
java –Xms128m???? –Xmx256m為控制新域的大小,可使用-XX:NewRatio設置新域在堆中所占的比例。
?? 下面的命令把整個堆設置成128m,新域比率設置成3,即新域與舊域比例為1:3,新域為堆的1/4或32M:
??
java –Xms128m –Xmx128m????–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize設置新域的初始值和最大值。
?? 下面的命令把新域的初始值和最大值設置成64m:
????
java –Xms256m –Xmx256m –Xmn64m?? 永久域默認大小為4m。運行程序時,jvm會調整永久域的大小以滿足需要。每次調整時,jvm會對堆進行一次完全的垃圾收集。
?? 使用-XX:MaxPerSize標志來增加永久域搭大小。在WebLogic Server應用程序加載較多類時,經常需要增加永久域的最大值。當jvm加載類時,永久域中的對象急劇增加,從而使jvm不斷調整永久域大小。為了避免調整,可使用-XX:PerSize標志設置初始值。
?? 下面把永久域初始值設置成32m,最大值設置成64m。
????
java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m????默認狀態下,HotSpot在新域中使用復制收集器。該域一般分為三個部分。第一部分為Eden,用于生成新的對象。另兩部分稱為救助空間,當Eden充滿時,收集器停止應用程序,把所有可到達對象復制到當前的from救助空間,一旦當前的from救助空間充滿,收集器則把可到達對象復制到當前的to救助空間。From和to救助空間互換角色。維持活動的對象將在救助空間不斷復制,直到它們獲得使用期并轉入舊域。使用-XX:SurvivorRatio可控制新域子空間的大小。
????同NewRation一樣,SurvivorRation規定某救助域與Eden空間的比值。比如,以下命令把新域設置成64m,Eden占32m,每個救助域各占16m:
????
java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2????如前所述,默認狀態下HotSpot對新域使用復制收集器,對舊域使用標記-清除-壓縮收集器。在新域中使用復制收集器有很多意義,因為應用程序生成的大部分對象是短壽命的。理想狀態下,所有過渡對象在移出Eden空間時將被收集。如果能夠這樣的話,并且移出Eden空間的對象是長壽命的,那么理論上可以立即把它們移進舊域,避免在救助空間反復復制。但是,應用程序不能適合這種理想狀態,因為它們有一小部分中長壽命的對象。最好是保持這些中長壽命的對象并放在新域中,因為復制小部分的對象總比壓縮舊域廉價。為控制新域中對象的復制,可用-XX:TargetSurvivorRatio控制救助空間的比例(該值是設置救助空間的使用比例。如救助空間位1M,該值50表示可用500K)。該值是一個百分比,默認值是50。當較大的堆棧使用較低的sruvivorratio時,應增加該值到80至90,以更好利用救助空間。用-XX:maxtenuring threshold可控制上限。
?? 為放置所有的復制全部發生以及希望對象從eden擴展到舊域,可以把MaxTenuring Threshold設置成0。設置完成后,實際上就不再使用救助空間了,因此應把SurvivorRatio設成最大值以最大化Eden空間,設置如下:
??
java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …
posted @
2006-11-28 11:58 jspark 閱讀(654) |
評論 (0) |
編輯 收藏
Assigning the target property requires the name of a window not the window itself.
Wecould try something like
window.opener.name="opener728";
form.target="opener728";
however, I suspect the window.name property is read-only.
Alternatively, if We are certain that the opener already has a name then this might work
form.target=window.opener.name;
It's also possible that browsers assign unique names to otherwise unnamed windows, so the above would always work - I've never checked this.
posted @
2006-11-22 15:39 jspark 閱讀(472) |
評論 (0) |
編輯 收藏
今天從網上找了一個讀寫csv格式的開源程序,還挺好用的。
下面是一個讀取例子:
源文件格式:
?ProductID,ProductName,SupplierID,CategoryID,QuantityPerUnit,UnitPrice,UnitsInStock,UnitsOnOrder,ReorderLevel,Discontinued
?1,Chai,1,1,10 boxes x 20 bags,18,39,0,10,FALSE
?2,Chang,1,1,24 - 12 oz bottles,19,17,40,25,FALSE
?下面讀取程序
?
?CsvReader?reader?
=
?
new
?CsvReader(
"
products.csv
"
);

?reader.readHeaders();

?
while
?(reader.readRecord())

?
{
??String?productID?
=
?reader.get(
"
ProductID
"
);
??String?productName?
=
?reader.get(
"
ProductName
"
);
??String?supplierID?
=
?reader.get(
"
SupplierID
"
);
??String?categoryID?
=
?reader.get(
"
CategoryID
"
);
??String?quantityPerUnit?
=
?reader.get(
"
QuantityPerUnit
"
);
??String?unitPrice?
=
?reader.get(
"
UnitPrice
"
);
??String?unitsInStock?
=
?reader.get(
"
UnitsInStock
"
);
??String?unitsOnOrder?
=
?reader.get(
"
UnitsOnOrder
"
);
??String?reorderLevel?
=
?reader.get(
"
ReorderLevel
"
);
??String?discontinued?
=
?reader.get(
"
Discontinued
"
);
??
??
//
?perform?program?logic?here
?}
?reader.close();
寫CSV例子:
?CsvWriter writer = new CsvWriter(new FileWriter(new File("c:\\1.csv")),',');
??writer.write("aa");
??writer.write("bb");
??writer.write("cc");
??writer.endRecord();
??writer.write("1");
??writer.write("2");
??writer.write("3");
??writer.close();
posted @
2006-11-07 12:05 jspark 閱讀(6561) |
評論 (0) |
編輯 收藏
在spring中如何處理oracle大字段
在spring中采用OracleLobHandler來處理oracle大字段(包括clob和blob),則在程序中不需要引用oracle的特殊類,從而能夠保證支持我們的代碼支持多數據庫。
1、首先數據表中的clob類型對應java持久化類的String類型;而blob類型對應byte[]類型 2、定義hibernate標簽時,持久化類中對應clob類型的屬性的hibernate type應為org.springframework.orm.hibernate.support.ClobStringType;而對應blob類型的屬性的hibernate type應為org.springframework.orm.hibernate.support.BlobByteArrayType。 3、以后訪問這些對應clob和blob類型的屬性時,按普通屬性處理,不需要特別編碼。
java代碼:?
|
<
bean?
id
="mySessionFactory2"
?class
="org.springframework.orm.hibernate.LocalSessionFactoryBean"
>
?
????????
<
property?
name
="dataSource"
>
?
????????????????
<
ref?
bean
="myDataSource2"
/>
?
?????????
</
property
>
?
?????????
<
property?
name
="lobHandler"
>
?
????????
<
ref?
bean
="oracleLobHandle"
/>
?
?????????
</
property
>
??
</
bean
>
?
<
bean?
id
="nativeJdbcExtractor"
?class
="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"
/>
?

<
bean?
id
="oracleLobHandle"
?class
="org.springframework.jdbc.support.lob.OracleLobHandler"
?Lazy-init
="true"
>
?
<
property?
name
="nativeJdbcExtractor"
>
?
????
<
ref?
local
="nativejdbcExtractor"
/>
?
</
property
>
?
</
bean
>
|
Spring為處理數據庫Lob字段,特別提供了LobHandler接口。在操作Oracle RDBMS過程中,由于Oracle JDBC Driver實現的問題,應用必須采用Oracle原生的數據庫連接(比如,oracle.jdbc.OracleConnection)、LOB原生實現(比如,oracle.sql.BLOB、oracle.sql.CLOB)。因此,LobHandler接口存在上述兩種實現。簡而言之,為操作Oracle數據庫,必須使用OracleLobHandler實現。如果操作其他RDBMS類型,則使用DefaultLobHandler。NativeJdbcExtractor是個接口,通過它能夠抽象各種連接池。另外Spring還提供兩個接口存取Blob,LobCreator及LobHandler
posted @
2006-08-28 11:58 jspark 閱讀(888) |
評論 (0) |
編輯 收藏
?? jdk提供的正則表達式是非常強大的,只要用過正則表達式的程序員應該是為其功能嘆為觀止。不過,正則表達式中的一個group概念相信應該不多人熟悉。
??? 正則表達式中的group,主要是用來區分子序列的,所謂子序列是用()之內的表達式。下面以一段程序為例
????????String?regex?=?"\\$\\{(I)(love)(java)\\}";
????????System.out.println(Pattern.compile(regex).matcher("${Ilovejava}P)").groupCount());
?運行上面的代碼段,結果為:3
?其中(I)為一個組, (love)為一個組,(java)為一個組。
??
? 也許有人覺得這只是一個小功能,但是正則表達式的group,還有一個更加強大的地方就是在String.replaceAll方法中。
? public
StringreplaceAll(
String?regex,
????????????????????????
String?replacement)
?其中第一個參數當然是政則表達式,第二個一般是普通的文本;但是第二個參數可以應用group的地方,這個功能用在一些場合是非常方便的。
??????比如,下面這個例子? <driverClass>${driverClass}</driverClass>,要將${}去掉,即將這個例子替換成<driverClass>driverClass</driverClass>,可以用下面的代碼來替換。例如
????????String?text?=?"<driverClass>${driverClass}</driverClass>";
????????String?result?=?replaceStr(text,"\\$\\{(driverClass)\\}","$1");
????????System.out.println("result?is:"+result);?? 運行結果:result is:<driverClass>driverClass</driverClass>
? 從上面可以看出,$1就是正則表達式中匹配的第一個序列,同樣$2...表示第幾個序列。如果$index中的index超出了表達式中子序列的個數的話,將拋出異常信息。 $0表示整個正則表達式。
posted @
2006-08-15 15:30 jspark 閱讀(495) |
評論 (0) |
編輯 收藏
在tomcat5.5版本以前,可以說jndi配置相對是比較復雜的,而且據網友說用tomcat5.0的控制臺配置數據庫連接池經常有問題,而且文檔寫得又不詳細。
tomcat5.5出來后,jndi的配置方法是大大地節省,而且很簡潔,個人覺得比以前的版本好很多。這里大概給出一個配置例子。tomcat數據庫連接池jndi配置有兩種,一種是全局的,一種是context的,下面主要是講全局的,并且以一個實例jdbc/byisdb為例子
???
一、tomcat5.0配置方法
1、首先在server.xml里面配置,找到下面的配置
? <!-- Global JNDI resources -->
? <GlobalNamingResources>
?</GlobalNamingResources>
2、在里面增加一個Resource
??????<Resource?name="jdbc/byisdb"
???????????????auth="Container"
???????????????type="javax.sql.DataSource"/>3、在下面增加屬性
??<ResourceParams?name="jdbc/byisdb">
????<parameter>
??????<name>factory</name>
??????<value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
????</parameter>

????<!--?Maximum?number?of?dB?connections?in?pool.?Make?sure?you
?????????configure?your?mysqld?max_connections?large?enough?to?handle
?????????all?of?your?db?connections.?Set?to?0?for?no?limit.
?????????-->
????<parameter>
??????<name>maxActive</name>
??????<value>100</value>
????</parameter>

????<!--?Maximum?number?of?idle?dB?connections?to?retain?in?pool.
?????????Set?to?-1?for?no?limit.??See?also?the?DBCP?documentation?on?this
?????????and?the?minEvictableIdleTimeMillis?configuration?parameter.
?????????-->
????<parameter>
??????<name>maxIdle</name>
??????<value>30</value>
????</parameter>

????<!--?Maximum?time?to?wait?for?a?dB?connection?to?become?available
?????????in?ms,?in?this?example?10?seconds.?An?Exception?is?thrown?if
?????????this?timeout?is?exceeded.??Set?to?-1?to?wait?indefinitely.
?????????-->
????<parameter>
??????<name>maxWait</name>
??????<value>10000</value>
????</parameter>

????<!--?MySQL?dB?username?and?password?for?dB?connections??-->
????<parameter>
?????<name>username</name>
?????<value>una_oa</value>
????</parameter>
????<parameter>
?????<name>password</name>
?????<value>una_oa</value>
????</parameter>

????<!--?Class?name?for?the?old?mm.mysql?JDBC?driver?-?uncomment?this?entry?and?comment?next
?????????if?you?want?to?use?this?driver?-?we?recommend?using?Connector/J?though
????<parameter>
???????<name>driverClassName</name>
???????<value>org.gjt.mm.mysql.Driver</value>
????</parameter>
?????-->
????
????<!--?Class?name?for?the?official?MySQL?Connector/J?driver?-->
????<parameter>
???????<name>driverClassName</name>
???????<value>oracle.jdbc.driver.OracleDriver</value>
????</parameter>
????
????<!--?The?JDBC?connection?url?for?connecting?to?your?MySQL?dB.
?????????The?autoReconnect=true?argument?to?the?url?makes?sure?that?the
?????????mm.mysql?JDBC?Driver?will?automatically?reconnect?if?mysqld?closed?the
?????????connection.??mysqld?by?default?closes?idle?connections?after?8?hours.
?????????-->
????<parameter>
??????<name>url</name>
??????<value>jdbc:oracle:thin:@192.168.1.210:1521:byisdb</value>
????</parameter>
??</ResourceParams>4、在你的應用的web.xml里面增加
<resource-ref>
?<description>postgreSQL?Datasource?example</description>
?<res-ref-name>jdbc/byisdb</res-ref-name>
?<res-type>javax.sql.DataSource</res-type>
?<res-auth>Container</res-auth>
</resource-ref>OK,到此配置完畢,可以用下面的幾段代碼進行測試
Context?initContext?=?new?InitialContext();
Context?envContext??=?(Context)initContext.lookup("java:/comp/env");
DataSource?ds?=?(DataSource)envContext.lookup("jdbc/byisdb");
Connection?conn?=?ds.getConnection();
out.println("conn?is:"+conn);二、tomcat5.5配置
1、打開conf/context.xml里面
? 添加下面的配置
????<Resource?name="jdbc/byisdb"?auth="Container"?type="javax.sql.DataSource"?driverClassName="oracle.jdbc.driver.OracleDriver"?url="jdbc:oracle:thin:@192.168.1.210:1521:byisdb"?username="una_oa"?password="una_oa"?maxActive="20"?maxIdle="10"?maxWait="10000"/>?
2在你的應用的web.xml里面增加
<resource-ref>
?<description>postgreSQL?Datasource?example</description>
?<res-ref-name>jdbc/byisdb</res-ref-name>
?<res-type>javax.sql.DataSource</res-type>
?<res-auth>Container</res-auth>
</resource-ref>同樣,可以用上面的代碼進行測試。
posted @
2006-08-11 14:03 jspark 閱讀(2949) |
評論 (1) |
編輯 收藏
?最近由于需要用到ThreadLocal,在網上搜索了一些相關資料,發現對ThreadLocal經常會有下面幾種誤解
?一、ThreadLocal是java線程的一個實現
????? ThreadLocal的確是和java線程有關,不過它并不是java線程的一個實現,它只是用來維護本地變量。針對每個線程,提供自己的變量版本,主要是為了避免線程沖突,每個線程維護自己的版本。彼此獨立,修改不會影響到對方。
?二、ThreadLocal是相對于每個session的
??????? ThreadLocal顧名思義,是針對線程。在java web編程上,每個用戶從開始到會話結束,都有自己的一個session標識。但是ThreadLocal并不是在會話層上。其實,Threadlocal是獨立于用戶session的。它是一種服務器端行為,當服務器每生成一個新的線程時,就會維護自己的ThreadLocal。對于這個誤解,個人認為應該是開發人員在本地基于一些應用服務器測試的結果。眾所周知,一般的應用服務器都會維護一套線程池,也就是說,對于每次訪問,并不一定就新生成一個線程。而是自己有一個線程緩存池。對于訪問,先從緩存池里面找到已有的線程,如果已經用光,才去新生成新的線程。所以,由于開發人員自己在測試時,一般只有他自己在測,這樣服務器的負擔很小,這樣導致每次訪問可能是共用同樣一個線程,導致會有這樣的誤解:每個session有一個ThreadLocal
?三、ThreadLocal是相對于每個線程的,用戶每次訪問會有新的ThreadLocal
??理論上來說,ThreadLocal是的確是相對于每個線程,每個線程會有自己的ThreadLocal。但是上面已經講到,一般的應用服務器都會維護一套線程池。因此,不同用戶訪問,可能會接受到同樣的線程。因此,在做基于TheadLocal時,需要謹慎,避免出現ThreadLocal變量的緩存,導致其他線程訪問到本線程變量
?四、對每個用戶訪問,ThreadLocal可以多用
??????? 可以說,ThreadLocal是一把雙刃劍,用得來的話可以起到非常好的效果。但是,ThreadLocal如果用得不好,就會跟全局變量一樣。代碼不能重用,不能獨立測試。因為,一些本來可以重用的類,現在依賴于ThreadLocal變量。如果在其他沒有ThreadLocal場合,這些類就變得不可用了。個人覺得ThreadLocal用得很好的幾個應用場合,值得參考
??1、存放當前session用戶:quake want的jert
??2、存放一些context變量,比如webwork的ActionContext
??3、存放session,比如Spring hibernate orm的session
posted @
2006-08-01 12:09 jspark 閱讀(30747) |
評論 (12) |
編輯 收藏
?????? 說真的,對于spring提供AOP的功能,個人實在不敢太過于恭維。主要是Spring的AOP功能沒那么強大,而且必須是對于spring容器管理的bean才能實施AOP功能,對于容器外的bean就無能為力了。而且spring沒有提供屬性的AOP功能。在這些方面,spring AOP真的不能和Aspectj相比。Aspectj的AOP功能才真的是真正意義的AOP框架,提供的功能非常強大,幾乎可以實現任何類型的AOP。不過Aspectj的學習曲線相對要比spring AOP稍微陡峭一點,主要是spring AOP可以當成普通javabean來處理,而Aspectj還要另外做編譯器,比較麻煩。不過,慶幸的是,eclipse下面有Aspectj插件,開發起來也是很方便。所以一般,復雜的AOP功能,還是推薦用Aspectj
???? 對于一般的J2EE開發來說,要實現一些比較常用的AOP,Spring 還是能滿足的。比如事務、異常、日志、權限等等,在這些方面,spring AOP還是比較方便的,特別是事務處理,spring提供了相當好的集成。如果事務處理用Aspectj來實現,不見得好多少。
??? 一直以來,覺得spring AOP最好用的一個地方就是提供了BeanNameAutoProxyCreator,這個類真的非常方便,以至于個人一旦遇到要實現AOP,首先就是求組于BeanNameAutoProxyCreator,如果BeanNameAutoProxyCreator實現不了,再考慮別的。不過,一般情況來說,BeanNameAutoProxyCreator的確能滿足需要了,除非你的需求真的千奇百怪。
???在應用spring AOP功能時,優先考慮用接口。因為如果用接口的話,那么spring會創建一個代理,并在代理里面實現AOP增強代碼,并調用真正的實例對象。不過,spring AOP功能不一定非要用接口,一些普通類也是可以的。對于普通類,spring會用CGLIB來動態生成一個新類。并且CGLIB會保持一個生成類的cache,因此它不會一直生成新類。spring使用ProxyCallbackFilter對象把其它對象放進map進行管理。如果沒有管理好cache,將會產生大量的java對象,直至出現OutOfMemoryErrors。因此使用spring的aop時,一定要正確實現equals and hashCode。
???不過,不管怎么樣,在應用spring AOP時,還是優先考慮接口方式,畢竟面向接口方式還是值得推薦的一個編程思想。
posted @
2006-07-31 19:37 jspark 閱讀(4110) |
評論 (11) |
編輯 收藏
???? 最近在負責一個大項目,項目組成員包括項目經理大概10個人左右。項目技術用struts+spring+hibernate實現。項目的規模相對來說是比較大的,總共有10大模塊,每個大模塊又分為有十幾個、甚至幾十個小模塊。開發工具用eclipse,由于在開發階段,項目開發成員需要頻繁重啟服務器。在啟動服務器的時候,每次啟動時間總是會超過1分鐘。記得以前在做另外一個項目時,啟動時間不到5秒鐘,相差了10倍,而且項目規模是差不多的。
??? 從初步分析來說,應該是hibernate解釋hbm.xml時花費時間,或者可能是spring容器啟動并解釋所有的bean配置文件。診斷了一下,發現1分鐘消耗的時間主要分布在hibernate解釋hbm.xml花費5秒;spring容器從啟動到解釋bean配置文件竟然花了58秒,真是太囂張了。當時非常懷疑spring的效率問題。企圖從網上搜索相關資料,看看有什么優化措施。
??? 首先是找到了hibernate的啟動優化
http://www.hibernate.org/194.html? 里面的主要思想是通過將xml序列花到本地的文件里,每次讀取的時候根據情況,從本地文件讀取并反序列化,節省了hibernate xml的解析時間。按照這個方式測試了一下,發現hibernate的啟動時間從5秒降低到3秒,但是這個優化對于整個啟動過程是杯水車薪的,毫無用處。
??? 沒辦法,又仔細查看了spring的資料,終于發現spring的容器是提供了lazy-load的,即默認的缺省設置是bean沒有lazy-load,該屬性處于false狀態,這樣導致spring在啟動過程導致在啟動時候,會默認加載整個對象實例圖,從初始化ACTION配置、到service配置到dao配置、乃至到數據庫連接、事務等等。這么龐大的規模,難怪spring的啟動時間要花將近1分鐘。嘗試了一下,把beans的default-lazy-init改為true就,再次啟動,速度從原來的55秒,降到8秒鐘!!Great!雖然是非常小一個改動,但是影響確實非常大。一個項目組10個人,假若每個人一天平均需要在eclipse下啟動測試服務器50次。那么一天項目組需要重啟500次,每次節省50秒的話,就是25000秒,將近幾個小時,差不多一個工作日,多么可觀的數字!
?? 不過在運行期間第一次點頁面的時候,由于spring做了lazy-load,現在就需要啟動一部分需要的beans,所以稍微慢2-3秒鐘,但是明顯比等幾十秒要快很多,值得一鑒。
??? 以上是針對開發階段的spring容器啟動優化,在部署到實際環境中,倒是沒必要設置為lazy-load。畢竟部署到實際環境中不是經常的事,每次啟動1分鐘倒不是大問題。
posted @
2006-07-29 13:27 jspark 閱讀(3271) |
評論 (2) |
編輯 收藏