2011-03-11 43 views
2

我很努力地完全理解何時/如何在JSF 2.0中拋出異常。我尋找的解決方案比我想承認的要長。最終,我想實現的目標是「處理」未處理的異常。當引發異常時,我希望能夠捕獲有關異常的感興趣的信息,並將其發送給相應的網站管理員。我通過在我的一個支持bean的構造函數中拋出一個新的FacesException()來強制引發錯誤。在JSF 1.1中,我使用MyFaces實現了這個工作。我能夠通過包裝默認生命週期並簡單地覆蓋execute()和render()方法來實現這個工作。我跟着這個由Hanspeter真棒發佈得到這個工作:JSF 2.0自定義異常處理程序

「http://insights2jsf.wordpress.com/2009/07/20/using-a-custom-lifecycle-implementation-to-handle-exceptions-in -jsf-1-2 /#comment-103「

我現在正在使用Mojarra的站點升級到JSF 2.0。只要在execute()方法中引發/捕獲異常,事情仍然很有用;在我輸入render()的那一刻,HttpServletResponse.isCommitted()等於true,階段是PhaseId RENDER_RESPONSE,這當然意味着我不能執行重定向或轉發。我不明白JSF 1.1和2.0之間在響應提交時間/方式方面發生了什麼變化。正如我所表明的那樣,我在1.1框架中完美地工作了。 經過多次搜索,我發現JSF 2.0爲通過自定義ExceptionHandler進行異常處理提供了一個很好的選擇。我遵循Ed Burns的博客,善於處理JSF2中的ViewExpiredException:

「http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2」

由於Ed通過定義標記以及異常/服務器錯誤代碼的類型以及發送給錯誤的頁面,始終存在web.xml方式。只要我遇到404錯誤,這種方法就很有用。然而,有一件有趣的事情要注意,如果我通過鍵入像/ myApp/9er這樣的非exsitant URL來強制404錯誤,那麼錯誤處理程序很好用,但只要添加「.xhtml」擴展名(即/ myApp/9er.xhtml),那麼web.xml定義不會處理它。

我注意到Ed的一件事是,我沒有嘗試過,而不是試圖做一個HttpServletRespone.sendRedirect(),他正在利用Navigationhandler.handleNavigation()將用戶轉發到自定義錯誤頁面。不幸的是,這種方法沒有做什麼不同於Faclets默認的錯誤。除此之外,由於與上述相同的問題,我無法執行HttpServletResponse.sendRedirect()。 response.isCommitted()等於true。

我知道這篇文章正在變長,所以我會做一個關於嘗試將PhaseListener用於相同目的的快速說明。我用以下帖子作爲指導,但此路線仍然不成功:

「http://ovaraksin.blogspot.com/2010/10/global-handling-of-all-unchecked.html」「http:/ /ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-session-timeout.html「

總而言之,我有和前面提到的一樣的問題。當引發此異常時,響應已經處於已落實階段,並且我無法將用戶重定向/轉發到標準錯誤頁面。

我對這麼長的帖子表示歉意,我只是儘可能地提供儘可能多的信息來消除歧義。任何人都有任何想法或想法來解決這個問題,我很好奇JSF 1.1和2.0之間可能會有什麼不同,這會在我進入生命週期的render()階段後立即提交響應。

非常感謝任何幫助!

回答

3

所以這個問題其實不只是一個自定義異常處理程序(其中JSF 2具有強大的ExceptionHandlerFactory機制),但更多的顯示用戶自定義錯誤頁時的響應已經提交。

即使最後一位已經寫入響應,始終能夠重定向用戶的一種通用方法是使用緩衝標題和寫入內容的包裝器。

這確實有該用戶不會看到頁是逐漸建立的不利影響。

也許你可以使用這種技術來只捕獲很早就響應承諾的是JSF 2.0似乎做。一旦渲染響應開始,你就發出緩衝的標題直到目前爲止,並直接寫出響應內容。

這樣,你可能仍然能夠將用戶重定向到自定義錯誤頁,如果呈現響應異常發生之前。

+0

非常感謝您的回覆!這聽起來很有趣,我如何讓Faces使用我的HttpServletResponseWrapper實現?我會採取什麼步驟來實現這一點? – Mickelback 2011-03-14 15:11:12

+0

對於響應包裝,只創建與含有doFilter方法標準Servlet過濾器:chain.doFilter(請求,新MyResponseWrapper(響應)); MyResponseWrapper是HttpServletResponseWrapper的子類。 – 2011-03-14 22:08:47

+0

謝謝你的幫助!然而,我能夠弄清楚你的建議。我堅持在哪裏實施緩衝標題和內容以防止響應被提交?再次感謝你的幫助! – Mickelback 2011-03-15 21:28:38

1

我已經成功實施使用響應包裝作爲如上所述這避免被COMMITED響應,並允許重定向到自定義頁面甚至在呈現頁面的中間一個異常的過濾器。

的響應包裝設置在StringWriter的,這是由的getWriter方法,使得面輸出進行緩衝返回其自身的內部的PrintWriter。在快樂路徑中,過濾器隨後將內部StringWriter內容寫入實際響應。在例外情況下,過濾器重定向到寫入(尚未提交)響應的錯誤jsp。

對我來說,避免響應提交的關鍵是攔截flushBuffer()方法(來自ServletResponse,而不是HttpServletResponse),並避免調用super.flushBuffer()。我懷疑,根據情況,如上所述,也可能需要重寫一些其他方法,例如設置標題的方法。