2011-07-29 51 views
5

我有一個問題來實現一個簡單的HTTP重定向。Liferay Portlet和JSF:在渲染階段重定向

我使用的Liferay 6.0.6,我們門戶的建立與JSF2.0/PortletFaces

我想調用一個重定向當視圖加載(而不是當一個動作被觸發時)。目前,我的功能由PreRenderView偵聽器調用。

<f:metadata> 
    <f:event listener="#{myControler.dispatch}" type="preRenderView" /> 
</f:metadata> 

在此功能,我可以檢查的權限,做其他的東西,而且在某些情況下,我想將用戶重定向到一個新的頁面(不是另一個視圖)。

我嘗試了幾種方法,失敗了。 具體來說,我認爲這種方法將工作:

getFacesContext().getExternalContext().redirect(url); 
getFacesContext().responseComplete() 
// => Can only redirect during ACTION_PHASE 

此錯誤是合乎邏輯的,但在那裏重定向的解決方案。

它可以在另一個函數來實現,否則叫,我只需要Hibernate的Session(設置在呈現階段的開始)

有你的想法來解決這個問題呢?
謝謝!

ps:<redirect />?faces-redirect不適用於portlet。

回答

9

您無法在設計的渲染階段執行此操作。原因:

  • 這可能是因爲,當您的portlet所呈現的portlet是異步呈現,所以可能已經顯示在頁面
  • 這有可能是網頁的部分已經交付給客戶,從而使HTTP標題已經發送 - 因此,按照設計,您無法在呈現階段訪問它們
  • 如果在同一頁面上呈現的兩個portlet將決定轉發到另一個頁面?誰會贏?

哈克解決方法是使一些JavaScript重定向,但是這是veeeery未類似門戶的和可以搞砸對方的預期(加時,部分頁面可能已經被渲染,使您的用戶填寫的表格只有通過你的JavaScript程序被重定向

請重新思考這個問題,並提出了不同的解決方案 - 它的真正價值在門戶環境中做這個

+1

謝謝你的解釋。我會考慮另一種解決方案,並在必要時重構我的portlet體系結構。 –

+0

另一個_hacky_解決方法是使用PortalUtil.getHttpServletResponse查找原始HTTP請求並在那裏使用sendRedirect。 –

+0

@TobiasLiefke * too * hacky恕我直言 - 響應可能已經在渲染期間提交。或者,portlet可能通過Ajax提供,甚至不是整個頁面的一部分。它可能工作,但它現在也可能工作,並在應用程序服務器的將來更新中斷... –

0

使用下面的方法,將工作

public static void redirect(final String url) throws IOException { 

      final javax.portlet.PortletResponse portletResponse 
      = getPortletResponse(); 

      if (portletResponse instanceof ActionResponse) { 

       final javax.portlet.ActionResponse actionResponse 
       = (javax.portlet.ActionResponse) portletResponse; 

       actionResponse.sendRedirect(url); 

      } else if (portletResponse instanceof ResourceResponse) { 

       final FacesContext ctx = FacesContext.getCurrentInstance(); 
       if (ctx.getPartialViewContext().isPartialRequest()) { 

        final ResourceResponse portletResResp 
        = (ResourceResponse) portletResponse; 
        PartialResponseWriter pwriter; 
        final ResponseWriter writer = ctx.getResponseWriter(); 
        if (writer instanceof PartialResponseWriter) { 
         pwriter = (PartialResponseWriter) writer; 
        } else { 
         pwriter = ctx.getPartialViewContext() 
         .getPartialResponseWriter(); 
        } 
        portletResResp.setContentType(Constants.CONTENT_TYPE); 
        portletResResp.setCharacterEncoding(Constants.ENCODING_TYPE); 
        // addResponseHeader("Cache-Control", "no-cache"); 
        pwriter.startDocument(); 
        pwriter.redirect(url); 
        pwriter.endDocument(); 
        ctx.responseComplete(); 
       } else { 
        throw new UnsupportedEncodingException(
          "Can only redirect during RESOURCE_PHASE " 
          + "if a Partial-(JSF AJAX)-Request has " 
          + "been triggered"); 
       } 
      } else { 
       throw new UnsupportedEncodingException(
         "Can not redirect during the current phase: " 
         + portletResponse.getClass().getSimpleName()); 
      } 
     } 
+0

對不起,但它不會工作,因爲我想在RenderPhase期間重定向(使用portletResponse istance of RenderResponse)。所以我會得到一個「無法在當前階段重定向」 –

0

我用這個,它適用於我:

public void preRenderView() throws IOException { 

     if (!checkUtente()) { 

       FacesContext fc = FacesContext.getCurrentInstance(); 

       NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler(); 

       navigationHandler.handleNavigation(fc, null, "errore.xhtml?faces-redirect=true"); 

       fc.renderResponse(); 
     } 

    }