[英]JSF 2.0 Custom Exception Handler
我正在努力完全理解在JSF 2.0中何時/如何引發異常。 我尋找解決方案的時間超出了我的意願。 最終,我要實現的目標是“處理”未處理的異常。 引發異常時,我希望能夠捕獲有關該異常的感興趣信息,並將其通過電子郵件發送給適當的站點管理員。 我通過在一個后備bean的構造函數中拋出新的FacesException()來強制執行錯誤。 在使用MyFaces實現的JSF 1.1中,我的工作非常出色。 我可以通過包裝默認生命周期並簡單地覆蓋execute()和render()方法來使其工作。 我跟隨Hanspeter撰寫的精彩文章來使該工作正常進行:
“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通過Custom ExceptionHandler為異常處理提供了一個很好的選擇。 我關注了Ed Burns的博客,在JSF2中優雅地處理ViewExpiredException:
“http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2”
正如Ed所指出的,總是通過定義標簽以及哪種類型的異常/服務器錯誤代碼以及該錯誤要發送到的頁面始終是web.xml方式。 只要我捕獲404錯誤,此方法就可以很好地工作。 關於這一點,需要注意的一件有趣的事是,如果我通過輸入不存在的URL(例如/ myApp / 9er)來強制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-會話timeout.html”
所有人和我都遇到了與上述相同的問題。 引發此異常時,響應已經處於提交階段,並且我無法將用戶重定向/轉發到標准錯誤頁面。
對於這么長的帖子,我深表歉意,我只是想提供盡可能多的信息,以幫助消除歧義。 任何人都有解決問題的想法/想法,我很好奇JSF 1.1和2.0之間可能會有什么不同,一旦我進入生命周期的render()階段,就會導致響應被提交。
非常感謝您對此提供的任何幫助!!!
因此,這個問題實際上不僅僅涉及自定義異常處理程序(JSF 2具有強大的ExceptionHandlerFactory
機制),而是更多關於在響應已提交時向用戶顯示自定義錯誤頁面的問題。
即使已經將最后一位寫入響應中,始終能夠重定向用戶的一種通用方法是使用HttpServletResponse
包裝器,該包裝器緩沖正在寫入的標頭和內容。
這確實帶來了不利影響,即用戶看不到正在逐步建立的頁面。
也許您可以使用此技術僅捕獲JSF 2.0似乎所做的非常早的響應提交。 渲染響應一開始,您就發出緩沖的標頭,直到現在為止,然后直接寫出響應內容。
這樣,如果在渲染響應之前發生異常,您仍然可以將用戶重定向到自定義錯誤頁面。
我已經如上所述使用響應包裝器成功實現了一個過濾器,該過濾器避免了響應的提交,並且即使在呈現頁面的中間發生異常,也允許重定向到自定義頁面。
響應包裝器在StringWriter上設置其自己的內部PrintWriter,該方法由getWriter方法返回,以便對faces輸出進行緩沖。 在快樂路徑中,過濾器隨后將內部StringWriter內容寫入實際響應。 在異常情況下,過濾器重定向到錯誤jsp,該錯誤寫入到(尚未提交的)響應中。
對我來說,避免提交響應的關鍵是攔截flushBuffer()方法(來自ServletResponse,而不是HttpServletResponse),並避免調用super.flushBuffer()。 我懷疑,視情況而定,如上所述,可能還需要重寫其他一些方法,例如設置標頭的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.