部落客廣告聯播

2007年7月24日 星期二

為何要避免在JSP中處理二元串流?

故事起源於我要使用POI輸出報表,原有的報表乃是用JSP+ jsp custom tag來產生的。

當然用POI輸出XLS檔,使用Servlet當然是首選,這在網路上許多前輩也常提,但總不是很深切的了解為何?

由於許多報表運算邏輯都放在custom tag裡,故愚笨的我選擇為了能共用tag所以在JSP中配合custom tag和script let來產生XLS檔,但前前後後遇到了不少問題。

在單純的JSP(不包含EL及custom tag狀況)中,來處理要輸出的Stream若遇到狀況,似乎還不難解決,但若JSP中包含了custom tag就複雜多了,況且有些問題再script let強加補強就算能用,移到了別的container還是有不能跑的可能,這涉及到各個container將JSP轉譯java servlet的實做程式不同。

首先是JSP buffer的問題,我們知道當JSP寫到Response的資料到達buffer值時即會flush到客戶端去(假設autoFlush=true),每個container預設的JSP buffer size不同。
然而在JSP裡要將二元資料寫到串流前,通常都要將先前JSP轉譯成java後裡頭的out.print(" \t\n");之類的東西清掉,才不會在資料頭出現奇奇怪怪的東西,所需要使用out.clear() 之類的做清除的動作,但如果在執行out.clear()之前buffer就已經被flush過了,那麼就會IOException,不要的out.print(" \t\n");也早就被輸出了,為了這個問題,可以透過JSP的Directive來將buffer設大點,暫時解決。

第二,在我的JSP最後段是workbook.write(response.getOutputStream); response.flush(); 但在Tomcat中執行,出現了錯誤,由於Tomcat算是廣為使用,到處有人可問,所以不用一天的時間我就早到了解決方法,在我的JSP最後再加上 out=response.pushBody( );就解決了。打開java檔查看乃是Tomcat的實作在jsp頁面後會再對out做處理,但我們提前將整個response給flush掉了,所以只要再push一個新的JspWriter給out就能解決了。

第三,當程式移植到了Resin時,問題就來的,輸出的Excel檔會是一堆空白,然後再活頁簿往下拉發現許多亂碼。同樣的我們將該JSP頁面經由Resin轉譯成的servlet來觀察問題所在,發現Resin實做會將每個TagSupport的endTag()後方加上out.flush( );[相對Tomcat沒有],故會在之前就輸出許多的空白和escape character,為了解決這個問題,於是將custom tag由TagSupport改用BodyTagSupport來實做,並且在JSP頁面上每一個custom tag結尾加上pageContext.clear( );
,恩,又是暫時解決!!

第四,程式到了另一個或許你也沒聽過的container - Novell Silver Stream,好玩,輸出的XLS完全空白,同樣觀察java檔,然而,到現在對於這問題還是一無所獲!! 無法解決......


上面寫了這麼大串,或許那都不重要,但我卻真正體會不要再JSP中處理Stream的意義了!!
恩... 好樣,最後還是要用servlet寫...........................
( 哭 ) 浪費我好多時間阿...................................................

沒有留言: