2013-02-19 87 views
1

我使用omnifaces FullAjaxExceptionHandler重定向時發生任何異常與ajax請求,在我的情況下捕獲ViewExpiredException。重定向後的JSF Ajax(ViewRoot)更新

我會盡力解釋我的情況:?

1)我有一個命令按鈕(Ajax請求的index.xhtml頁)無效的會話,並返回一個動作像這樣「/登錄面臨重定向=真」。

2)在同一瀏覽器中打開index.xhtml兩次。

3)在第一個的index.xhtml中單擊按鈕(會話是無效,並重定向到login.xhtml)

在這一點上您考慮我有一個自定義的PhaseListener來檢查用戶是否成功地記錄,login.xhtml是向公衆開放,但的index.xhtml僅限於授權用戶,web.xml中的視圖過期,403錯誤是:

<error-page> 
    <exception-type>javax.faces.application.ViewExpiredException</exception-type> 
    <location>/index.xhtml</location> 
</error-page> 
<error-page> 
    <error-code>403</error-code> 
    <location>/403.xhtml</location> 
</error-page> 

4)轉到第二的index.xhtml(會話無效在這一刻),現在點擊按鈕啓動異常。

FullAjaxExceptionHandler捕獲ViewExpiredException並嘗試呈現index.xhtml,但同時我的phaselistener正在檢查用戶是否被授權,如會話失效,用戶未被授權,並且我的PhaseListener觸發responseSendError(403) ,但沒有顯示403.xhtml,因爲是ajax請求。

如何從我的PhaseListener發送403錯誤以顯示403.xhtml? responseSendError取消了FullAjaxExceptionHandler的正常處理,此時此異常發生時不發生重定向。

此外,爲了澄清視圖何時到期,我需要重定向到index.xhtml,因爲在生產中我使用CAS(中央身份驗證服務)。

回答

1

具體問題實質上與FullAjaxExceptionHandler無關。不使用它時,你仍然會遇到完全相同的問題。這是不可能的Ajax請求使用responseSendError()至少2個原因:

  1. Ajax響應必須在訂單狀態200被成功處理。
  2. ajax響應必須表示有效的JSF ajax XML結構,而不是純HTML頁面。

PhaseListener裏面,最好的選擇是使用ExternalContext#redirect()

ExternalContext ec = context.getExternalContext(); 

if (context.getPartialViewContext().isAjaxRequest()) { 
    ec.redirect(ec.getRequestContextPath() + "/403.xhtml"); 
} else { 
    ec.responseSendError(403, "Unauthorized"); 
} 

誠然,這結束了在HTTP 200響應,但是這是迄今爲止,當你要顯示的全部錯誤頁面在一個Ajax請求的情況下,你可以得到最好的。


無關的具體問題,如果ViewExpiredException被拋出了,那麼原因是在幾乎所有情況下,在會話過期。讓異常的錯誤頁面直接指向/login.xhtml而不是/index.xhtml會更有意義。或者,至少更多的用戶友好,一些/expired.xhtml頁面,其中有一個解釋爲什麼最終用戶最終在那裏,他的選擇,以及一些鏈接。

+0

在這種情況下,我需要讀取web.xml以獲取配置的錯誤頁面。我會改變我的代碼。謝謝Balus。 – Kab 2013-02-20 13:19:23