2011-07-29 41 views
5

Tôi gặp sự cố khi triển khai chuyển hướng HTTP đơn giản.Porter Liferay và JSF: Chuyển hướng trong giai đoạn Render

tôi sử dụng Liferay 6.0.6, chúng tôi portlet được xây dựng với JSF2.0/PortletFaces.

Tôi muốn gọi chuyển hướng khi lượt xem được tải (chứ không phải khi một hành động được kích hoạt). Hiện tại, chức năng của tôi được gọi bởi trình nghe PreRenderView.

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

Trong chức năng này, tôi có thể kiểm tra quyền, làm công cụ khác và trong một số trường hợp tôi muốn chuyển hướng người dùng đến trang mới (không phải một chế độ xem khác).

Tôi đã thử một số phương pháp, không thành công. Cụ thể, tôi nghĩ rằng phương pháp này sẽ làm việc:

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

Lỗi này là hợp lý, nhưng là có một giải pháp cho lực chuyển hướng.

Nó có thể được thực hiện trong chức năng khác, được gọi bằng cách khác, tôi chỉ cần Hibernate Session (bộ vào đầu Render Phase)

Có bạn những ý tưởng để giải quyết vấn đề này?
Cảm ơn!

ps: <redirect /> hoặc ?faces-redirect không hoạt động với các portlet.

Trả lời

9

Bạn không thể thực hiện việc này trong giai đoạn kết xuất theo thiết kế. Lý do:

  • Có thể là portlet được trả lại không đồng bộ, do đó trang đã có thể được hiển thị khi portlet của bạn đang được trả lại
  • Có thể là một phần của trang đã được phân phối cho khách hàng, do đó HTTP Tiêu đề đã được gửi - vì lý do này, theo thiết kế, bạn không có quyền truy cập vào chúng trong giai đoạn hiển thị
  • Kết quả mong đợi là gì nếu hai portlet được hiển thị trên cùng một trang sẽ quyết định rằng chúng muốn chuyển tiếp đến trang khác? Ai sẽ thắng?

Giải pháp khắc phục là thực hiện một số chuyển hướng javascript, nhưng điều này không giống như cổng thông tin và có thể làm hỏng các kỳ vọng của người khác (cộng thêm, các phần của trang có thể đã được hiển thị, khiến người dùng của bạn điền vào biểu mẫu chỉ được chuyển hướng bởi thói quen javascript của bạn

Hãy suy nghĩ lại vấn đề và đưa ra một giải pháp khác nhau -. nó thực sự đáng để làm điều này trong một môi trường cổng

+1

Cảm ơn bạn đã giải thích.Tôi sẽ nghĩ đến một giải pháp khác, và cấu trúc lại kiến ​​trúc portlet của tôi nếu cần thiết. –

+0

Một giải pháp khác của _hacky_ là sử dụng PortalUtil.getHttpServletResponse để tìm yêu cầu HTTP ban đầu và sử dụng sendRedirect tại đó. –

+0

@TobiasLiefke * quá * hack IMHO - phản hồi có thể đã được cam kết trong thời gian hiển thị. Hoặc portlet có thể được gửi qua Ajax, thậm chí không phải là một phần của toàn bộ trang. Nó có thể hoạt động, nhưng nó cũng có thể hoạt động ngay bây giờ và phá vỡ một số bản cập nhật trong tương lai của máy chủ ứng dụng ... –

0

Sử dụng phương pháp dưới đây nó sẽ làm việc

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

Xin lỗi nhưng nó sẽ không hoạt động, bởi vì tôi muốn chuyển hướng trong một RenderPhase (với portletResponse istanceof RenderResponse). Vì vậy, tôi sẽ nhận được một "Không thể chuyển hướng trong giai đoạn hiện tại" –

0

Tôi sử dụng tính năng này và nó hoạt động cho tôi:

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(); 
     } 

    } 
Các vấn đề liên quan