2011-07-29 55 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(); 
     } 

    }