commons.fileupload實現文件的上傳,代碼如下:
<%!
//服務器端保存上傳文件的路徑
String saveDirectory = "g:\\upload\\";
// 臨時路徑 一旦文件大小超過getSizeThreshold()的值時數據存放在硬盤的目錄
String tmpDirectory = "g:\\upload\\tmp\\";
// 最多只允許在內存中存儲的數據大小,單位:字節
int maxPostSize = 1024 * 1024;
%>
<%
// 文件內容
String FileDescription = null;
// 文件名(包括路徑)
String FileName = null;
// 文件大小
long FileSize = 0;
// 文件類型
String ContentType = null;
%>
<%
DiskFileUpload fu = new DiskFileUpload();
// 設置允許用戶上傳文件大小,單位:字節
fu.setSizeMax(200*1024*1024);
// 設置最多只允許在內存中存儲的數據,單位:字節
fu.setSizeThreshold(maxPostSize);
// 設置一旦文件大小超過getSizeThreshold()的值時數據存放在硬盤的目錄
fu.setRepositoryPath("g:\\upload\\tmp\\");
//開始讀取上傳信息 得到所有文件
try{
List fileItems = fu.parseRequest(request);
}catch(FileUploadException e){
//這里異常產生的原因可能是用戶上傳文件超過限制、不明類型的文件等
//自己處理的代碼
}
%>
<%
// 依次處理每個上傳的文件
Iterator iter = fileItems.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
//忽略其他不是文件域的所有表單信息
if (!item.isFormField()) {
String name = item.getName();
long size = item.getSize();
String contentType = item.getContentType();
if((name==null||name.equals("")) && size==0)
continue;
%>
<%
//保存上傳的文件到指定的目錄
String[] names=StringUtils.split(name,"\\"); //對原來帶路徑的文件名進行分割
name = names[names.length-1];
item.write(new File(saveDirectory+ name));
}
}
%>
下面是其簡單的使用場景:
A、上傳項目只要足夠小,就應該保留在內存里。
B、較大的項目應該被寫在硬盤的臨時文件上。
C、非常大的上傳請求應該避免。
D、限制項目在內存中所占的空間,限制最大的上傳請求,并且設定臨時文件的位置。
可以根據具體使用用servlet來重寫,具體參數配置可以統一放置到一配置文件
文件的下載用servlet實現 public void doGet(HttpServletRequest request,
HttpServletResponse response)
{
String aFilePath = null; //要下載的文件路徑
String aFileName = null; //要下載的文件名
FileInputStream in = null; //輸入流
ServletOutputStream out = null; //輸出流
try
{
aFilePath = getFilePath(request);
aFileName = getFileName(request);
response.setContentType(getContentType(aFileName) + "; charset=UTF-8");
response.setHeader("Content-disposition", "attachment; filename=" + aFileName);
in = new FileInputStream(aFilePath + aFileName); //讀入文件
out = response.getOutputStream();
out.flush();
int aRead = 0;
while((aRead = in.read()) != -1 & in != null)
{
out.write(aRead);
}
out.flush();
}
catch(Throwable e)
{
log.error("FileDownload doGet() IO error!",e);
}
finally
{
try
{
in.close();
out.close();
}
catch(Throwable e)
{
log.error("FileDownload doGet() IO close error!",e);
}
}
}
posted @
2005-12-16 10:46 ronghao 閱讀(6243) |
評論 (1) |
編輯 收藏
檢查字符串是否為空或null或僅僅包含空格
String test = "";
String test1=" ";
String test2 = "\n\n\t";
String test3 = null;
System.out.println( "test blank? " + StringUtils.isBlank( test ) );
System.out.println( "test1 blank? " + StringUtils.isBlank( test1 ) );
System.out.println( "test2 blank? " + StringUtils.isBlank( test2 ) );
System.out.println( "test3 blank? " + StringUtils.isBlank( test3 ) );
運行結果:
test blank? true
test1 blank? true
test2 blank? true
test3 blank? true
相對應的還有一個StringUtils.isNotBlank(String str)
StringUtils.isEmpty(String str)則檢查字符串是否為空或null(不檢查是否僅僅包含空格)
分解字符串
StringUtils.split(null, *, *) = null
StringUtils.split("", *, *) = []
StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
StringUtils.split("ab de fg", null, 0) = ["ab", "cd", "ef"]
StringUtils.split("ab:cd:ef", ":", 0) = ["ab", "cd", "ef"]
StringUtils.split("ab:cd:ef", ":", 1) = ["ab:cd:ef"]
StringUtils.split("ab:cd:ef", ":", 2) = ["ab", "cd:ef"]
StringUtils.split(String str,String separatorChars,int max) str為null時返回null
separatorChars為null時默認為按空格分解,max為0或負數時分解沒有限制,max為1時返回整個字符串,max為分解成的個數(大于實際則無效)
去除字符串前后指定的字符
StringUtils.strip(null, *) = null
StringUtils.strip("", *) = ""
StringUtils.strip("abc", null) = "abc"
StringUtils.strip(" abc ", null) = "abc"
StringUtils.strip(" abcyx", "xyz") = " abc"
StringUtils.strip(String str,String stripChars) str為null時返回null,stripChars為null時默認為空格
創建醒目的Header(調試時用)
public String createHeader( String title ) {
int width = 30;
String stars = StringUtils.repeat( "*", width);
String centered = StringUtils.center( title, width, "*" );
String heading = StringUtils.join(new Object[]{stars, centered, stars}, "\n");
return heading;
}
調用createHeader("TEST")的輸出結果:
******************************
************ TEST ************
******************************
字符的全部反轉及以單個詞為單位的反轉
String original = "In time, I grew tired of his babbling nonsense.";
StringUtils.reverse( original ) = ".esnesnon gnilbbab sih fo derit werg I ,emit nI"
以單個詞為單位的反轉
public Sentence reverseSentence(String sentence) {
String reversed = StringUtils.chomp( sentence, "." );
reversed = StringUtils.reverseDelimited( reversed, ' ' );
reversed = reversed + ".";
return reversed;
}
String sentence = "I am Susan."
reverseSentence( sentence ) ) = "Susan am I."
檢查字符串是否僅僅包含數字、字母或數字和字母的混合
String test1 = "ORANGE";
String test2 = "ICE9";
String test3 = "ICE CREAM";
String test4 = "820B Judson Avenue";
String test5 = "1976";
結果:
boolean t1val = StringUtils.isAlpha( test1 ); // returns true
boolean t2val = StringUtils.isAlphanumeric( test2 ); // returns true
boolean t3val = StringUtils.isAlphaSpace( test3 ); // returns true
boolean t4val = StringUtils.isAlphanumericSpace( test4 ); // returns true
boolean t5val = StringUtils.isNumeric( test5 ); // returns true
posted @
2005-12-14 12:47 ronghao 閱讀(2593) |
評論 (1) |
編輯 收藏
primitive 數組克隆及反轉排序
long[] array = { 1, 3, 2, 3, 5, 6 };
long[] reversed = ArrayUtils.clone( array );
ArrayUtils.reverse( reversed );
System.out.println( "Original: " + ArrayUtils.toString( array ) ); //打印
System.out.println( "Reversed: " + ArrayUtils.toString( reversed ) );
對象數組克隆及反轉排序
Long[] array = new Long[] { new Long(3), new Long(56), new Long(233) };
Long[] reversed = ArrayUtils.clone( array );
ArrayUtils.reverse( reversed );
primitive 數組與對象數組之間的轉換
long[] primitiveArray = new long[] { 12, 100, 2929, 3323 };
Long[] objectArray = ArrayUtils.toObject( primitiveArray );
Double[] doubleObjects = new Double[] { new Double( 3.22, 5.222, 3.221 ) };
double[] doublePrimitives = ArrayUtils.toPrimitive( doubleObject );
注意:對象數組可以含有null元素,primitive 數組則不容許含有null元素,所以對象數組轉換為primitive 數組時,可以添入第二個參數,當碰到為null的元素時用其代替(如下,Double.NaN)。如果不添入第二個參數,當碰到為null的元素時,則會拋出NullPointerException 。
double[] result = ArrayUtils.toPrimitive( resultObjArray, Double.NaN );
查找一個數組中是否含有特定的元素(查找對象數組時,比較的是對象的equals()方法),及特定元素的第一次出現位置和最后一次出現位置
String[] stringArray = { "Red", "Orange", "Blue", "Brown", "Red" };
boolean containsBlue = ArrayUtils.contains( stringArray, "Blue" );
int indexOfRed = ArrayUtils.indexOf( stringArray, "Red");
int lastIndexOfRed = ArrayUtils.lastIndexOf( string, "Red" );
由二維對象數組創建一個 Map
Object[] weightArray =
new Object[][] { {"H" , new Double( 1.007)},
{"He", new Double( 4.002)},
{"Li", new Double( 6.941)},
{"Be", new Double( 9.012)},
{"B", new Double(10.811)},
{"C", new Double(12.010)},
{"N", new Double(14.007)},
{"O", new Double(15.999)},
{"F", new Double(18.998)},
{"Ne", new Double(20.180)} };
Map weights = ArrayUtils.toMap( weightArray );
Double hydrogenWeight = (Double)weights.get( "H" );
注意:當二維對象數組"key"值重復時,創建的Map,后面的鍵-值對會把前面的覆蓋掉
posted @
2005-12-13 18:48 ronghao 閱讀(1367) |
評論 (4) |
編輯 收藏
DisplayTag是一個非常好用的表格顯示標簽,適合MVC模式,其主頁在http://displaytag.sourceforge.net
一、最簡單的情況,未使用<display:column/>標簽
<%request.setAttribute( "test", new ReportList(6) );%>
<display:table name="test" />
標簽遍歷List里的每一個對象,并將對象里的所有屬性顯示出來。一般用于開發的時候檢查對象數據的完整性。
二、使用<display:column/>標簽的情況
<display:table name="test">
<display:column property="id" title="ID" />
<display:column property="name" />
<display:column property="email" />
<display:column property="status" />
<display:column property="description" title="Comments"/>
</display:table>
property對應List里對象的屬性(用getXXX()方法取得),title則對應表格表頭里的列名。定義列有兩種方式:
A、<display:column property="email" />
使用<display:column/>標簽里的property屬性來定義
B、<display:column title="email">email@it.com</display:column>
在<display:column/>標簽體里增加內容,可以是常量,也可以用其他標簽等等
兩種方式比較,用property屬性來定義更加快速和利于排序。
三、表格顯示樣式的定義
A、在<display:table/>和<display:column/>標簽里指定標準的html屬性,煩瑣
B、修改樣式表
<display:table name="test" class="mars">
<display:column property="id" title="ID" class="idcol"/>
<display:column property="name" />
<display:column property="email" />
<display:column property="status" class="tableCellError" />
<display:column property="description" title="Comments"/>
</display:table>
通過class屬性來指定所要應用的樣式??梢栽谄淠J樣式表里(./css/screen.css)直接修改
四、標簽取得數據的數據源
有四種范圍
pageScope
requestScope (默認) <display:table name="test2" >
sessionScope <display:table name="sessionScope.holder.list" > 注意,這里要指定范圍,非默認
applicationScope
五、通過增加id屬性創建隱含的對象
<display:table name="test" id="testit">
<display:column property="id" title="ID" />
<display:column property="name" />
<display:column title="static value">static</display:column>
<display:column title="row number (testit_rowNum)"><%=pageContext.getAttribute("testit_rowNum")%></display:column>
<display:column title="((ListObject)testit).getMoney()"><%=((ListObject)pageContext.getAttribute("testit")).getMoney()%></display:column>
</display:table>
注意到在<display:table/>里增加了id屬性,這時就在page context里創建了一個隱含對象,指向List里的當前對象,
可以通過(ListObject)pageContext.getAttribute("id")來捕獲這個對象。同時還創建了一個id_rowNum對象,同樣,可
通過pageContext.getAttribute("testit_rowNum")來捕獲,它僅僅代表當前行的行數。
有了這兩個隱含對象,就可以通過其他標簽來訪問,例如Jstl:
<display:table id="row" name="mylist">
<display:column title="row number" >
<c:out value="${row_rowNum}"/>
</display:column>
<display:column title="name" >
<c:out value="${row.first_name}"/>
<c:out value="${row.last_name}"/>
</display:column>
</display:table>
六、顯示部分數據
顯示開始五條數據:通過設定length屬性
<display:table name="test" length="5">
<display:column property="id" title="ID" />
<display:column property="email" />
<display:column property="status" />
</display:table>
顯示第三到第八條數據:通過設定offset和length屬性
<display:table name="test" offset="3" length="5">
<display:column property="id" title="ID" />
<display:column property="email" />
<display:column property="status" />
</display:table>
七、對email和url地址的直接連接
<display:table name="test" >
<display:column property="id" title="ID" />
<display:column property="email" autolink="true" />
<display:column property="url" autolink="true" />
</display:table>
如果要顯示的對象里包含email和url地址,則可以在display:column里直接設定autolink="true"來直接連接
八、使用裝飾模式轉換數據顯示(寫自己的 decorator )
A、對整個表格應用decorator
<display:table name="test" decorator="org.displaytag.sample.Wrapper" >
<display:column property="id" title="ID" />
<display:column property="email" />
<display:column property="status" />
<display:column property="date" />
<display:column property="money" />
</display:table>
org.displaytag.sample.Wrapper即自己寫的decorator,它要繼承TableDecorator類,看看它的一個方法:
public String getMoney()
{
return this.moneyFormat.format(((ListObject) this.getCurrentRowObject()).getMoney());
}
很明顯,它通過父類的getCurrentRowObject()方法獲得當前對象,然后對其getMoney()方法進行‘油漆’
B、對單獨的column應用decorator
<display:table name="test">
<display:column property="id" title="ID" />
<display:column property="email" />
<display:column property="status" />
<display:column property="date" decorator="org.displaytag.sample.LongDateWrapper" />
</display:table>
org.displaytag.sample.LongDateWrapper要實現ColumnDecorator接口,它的方法:
public final String decorate(Object columnValue)
{
Date date = (Date) columnValue;
return this.dateFormat.format(date);
}
顯然,它獲得不了當前對象(因為它實現的是接口),僅僅是獲得該對象的columnValue,然后‘油漆’
九、創建動態連接
有兩種方法創建動態連接:
A、在<display:column/>里通過增加href、paramId、paramName、paramScope、paramProperty屬性
href 基本的URL 地址
paramId 加在URL 地址后的參數名稱
paramName 數據bean的名稱,一般為null(即使用當前List里的對象)
paramScope 數據bean的范圍,一般為null
paramProperty 數據bean的屬性名稱,用來填充URL 地址后的參數值
<display:table name="sessionScope.details">
<display:column property="id" title="ID" href="details.jsp" paramId="id" />
<display:column property="email" href="details.jsp" paramId="action" paramName="testparam" paramScope="request" />
<display:column property="status" href="details.jsp" paramId="id" paramProperty="id" />
</display:table>
這種方法簡便直接,但缺點是無法產生類似details.jsp?id=xx&action=xx的復合URL
B、應用decorator 創建動態連接:
<display:table name="sessionScope.details" decorator="org.displaytag.sample.Wrapper" >
<display:column property="link1" title="ID" />
<display:column property="email" />
<display:column property="link2" title="Actions" />
</display:table>
org.displaytag.sample.Wrapper里的方法:
public String getLink1()
{
ListObject lObject= (ListObject)getCurrentRowObject();
int lIndex= getListIndex();
return "<a href=\"details.jsp?index=" + lIndex + "\">" + lObject.getId() + "</a>";
}
public String getLink2()
{
ListObject lObject= (ListObject)getCurrentRowObject();
int lId= lObject.getId();
return "<a href=\"details.jsp?id=" + lId
+ "&action=view\">View</a> | "
+ "<a href=\"details.jsp?id=" + lId
+ "&action=edit\">Edit</a> | "
+ "<a href=\"details.jsp?id=" + lId
+ "&action=delete\">Delete</a>";
}
十、分頁
實現分頁非常的簡單,增加一個pagesize屬性指定一次想顯示的行數即可
<display:table name="sessionScope.test" pagesize="10">
<display:column property="id" title="ID" />
<display:column property="name" />
<display:column property="email" />
<display:column property="status" />
</display:table>
十一、排序
排序實現也是很簡單,在需要排序的column里增加sortable="true"屬性,headerClass="sortable"僅僅是
指定顯示的樣式。column里的屬性對象要實現Comparable接口,如果沒有的話可以應用decorator
defaultsort="1" 默認第一個column排序
defaultorder="descending" 默認遞減排序
<display:table name="sessionScope.stest" defaultsort="1" defaultorder="descending">
<display:column property="id" title="ID" sortable="true" headerClass="sortable" />
<display:column property="name" sortable="true" headerClass="sortable"/>
<display:column property="email" />
<display:column property="status" sortable="true" headerClass="sortable"/>
</display:table>
注意的是,當同時存在分頁時排序僅僅針對的是當前頁面,而不是整個List都進行排序
十二、column 分組
分組只是需要在column里增加group屬性
<display:table name="test" class="simple">
<display:column property="city" title="CITY" group="1"/>
<display:column property="project" title="PROJECT" group="2"/>
<display:column property="amount" title="HOURS"/>
<display:column property="task" title="TASK"/>
</display:table>
十三、導出數據到其他格式(頁面溢出filter??)
在<display:table/>里設定export="true"
在<display:column/>里設定media="csv excel xml pdf" 決定該字段在導出到其他格式時被包不包含,不設定則都包含
<display:setProperty name="export.csv" value="false" />
決定該種格式能不能在頁面中導出
<display:table name="test" export="true" id="currentRowObject">
<display:column property="id" title="ID"/>
<display:column property="email" />
<display:column property="status" />
<display:column property="longDescription" media="csv excel xml pdf" title="Not On HTML"/>
<display:column media="csv excel" title="URL" property="url"/>
<display:setProperty name="export.pdf" value="true" />
<display:setProperty name="export.csv" value="false" />
</display:table>
十四、配置屬性,覆蓋默認
兩種方法:
A、在程序classpath下新建displaytag.properties文件
B、對于單個表格,應用<display:setProperty>標簽
具體可配置的屬性:http://displaytag.sourceforge.net/configuration.html
十五、一個完整的例子
<display:table name="test" export="true" sort="list" pagesize="8">
<display:column property="city" title="CITY" group="1" sortable="true" headerClass="sortable"/>
<display:column property="project" title="PROJECT" group="2" sortable="true" headerClass="sortable"/>
<display:column property="amount" title="HOURS"/>
<display:column property="task" title="TASK"/>
</display:table>
sort="list" 對整個list進行排序
導出數據到其他格式時,group無效
posted @
2005-12-08 16:10 ronghao 閱讀(6618) |
評論 (25) |
編輯 收藏
看到你的博客,感觸很多.我也有群程序員朋友,特別是做了幾年后也在考慮自己以后的職業發展方向與規劃問題.理論大家都知道,可是實際操作中,卻不是那么單純與容易的.
我想到了下面的一個故事及一篇對程序員職業生涯規劃的一文章,與你分享:
偶然在網上看到這樣一個故事:John和Bill一起到山中探險,忽然他們發現一只老虎正深情的望著他們,John撒腿就要跑,Bill卻迅速的從背包里拿出一雙跑鞋穿在腳上,John看到后氣急敗壞的對說Bill“你穿什么鞋也跑不過老虎的”Bill同情的看了他一眼,回答說“我干嗎要和老虎比,我只要跑過你就夠了?!?
大笑以后不免想起John的境遇是不是有點象中國的程序員呢?我個人習慣把軟件從業人員分為初級程序員、高級程序員、系統分析員和項目經理四大類的方法,我把優秀程序員的標準分為職業習慣和個人能力兩方面,職業習慣包括文檔編寫習慣,規范化、標準化的編碼習慣、軟件測試習慣、模塊化開發習慣等,個人能力包括團隊協作能力、需求理解能力、學習和創新能力等。我接觸過的幾百個程序員后的感覺,除非那種天生適合編程的人才能成為行業的頂尖高手,按照以上標準絕大多數程序員只能歸入“平庸”之列,所以我們這里的討論主要是基于大多數“平庸”的程序員的。
故事中的John能不能活命跟三個問題有關:老虎、Bill、自己,中國程序員的困境也來自三個方面。
困境之一:老虎的威脅。程序員要面對的餓老虎實在不少,比如說老板,好象老板就是程序員的天敵(當然自己當老板的程序員除外,呵呵),什么“不懂技術卻指手畫腳”、什么“得到與付出不相當”似乎是程序員最常見的牢騷,這個問題不可能得到真正的解決,在這里就不詳細討論了。
困境之二:Bill的競爭。一般說來中國的程序員大都是吃“青春飯”的,大部分程序員的黃金時代是24~28歲。到了30歲左右,一批又一批年輕程序員會給你帶來巨大的競爭壓力。首先由于軟件行業的飛速發展,很多自己以前學的東西逐漸升級換代,而許多程序員由于長期于工作,學習新知識的效率必然下降。其次自己干了幾年,薪水要求自然就高了,而年輕程序員工資又低、干活又快,當然會成為老板的首選;第三,30歲基本都已經成家了,要支撐家庭的生活負擔,你幾乎連從頭在來的勇氣都不會有了。中國的老話說“長江后浪催前浪、一代新人換舊人”,這個歷史的規律在軟件開發行業體現的尤其明顯和殘酷,很多程序員必然要面對的結果就是降薪乃至失業。
困境之三:自我的實力。我們都知道人最難戰勝的是自己,所以自我也就是程序員需要超越的最大障礙。大多程序員都把系統分析員和項目經理作為自己的職業目標,但這些目標的達成,需要個人素質、市場機遇等多個方面的條件,太多的程序員就是在高不成、低不就的狀態中蹉跎了歲月。對于系統分析員,特別需要以下幾方面的素質:客戶需求分析能力、系統架構與設計能力、模塊分解設計能力、項目流程控制能力、項目風險評估能力等,而對于項目經理則更注重項目管理方面的能力如團隊組織能力、溝通協調能力、分析問題解決問題的能力以及良好的職業道德等,而這些素質和能力往往只能依靠程序員個人的學習和努力??吹皆絹碓蕉嗟某绦騿T開始學習項目管理的課程,真的有點為他們擔心,因為現在的項目管理培訓只能停留在理論和考證的程度,既沒有素質方面的訓練,又缺少實際軟件開發項目的案例,學習的結果遠遠不能達到預期的效果。
posted @
2005-12-06 18:37 ronghao 閱讀(508) |
評論 (1) |
編輯 收藏