如何在Facelets页面中包含一个JSP页面?

4

我正在使用Facelets上的Myfaces 2。 我需要在一个Facelet页面中包含一个JSP页面。 我尝试使用<ui:include>,但它只能接受XHTML页面。 我还尝试使用<c:import><f:subview>,但都没有成功。 我搜索了很多,但没有得到确切的答案。

我该如何实现这个要求?

2个回答

4
这可以通过自定义UIComponent来实现。我的同事在一年前写了一篇博客文章,讲述了这个过程:Facelets和遗留的JSP
虽然有一些代码,但原理很简单:组件使用一个自定义的HttpServletResponseWrapper执行RequestDispatcher#include(),捕获所写的输出,然后将其写入JSF组件的正文中。以下是相关部分的摘录:
创建类com.example.component.JspIncludeComponent
public class JSPIncludeComponent extends UIComponentBase {

    public String getFamily() {
       return "components.jsp.include";
    }

    public void encodeBegin(FacesContext context) throws IOException {
       try {
          ExternalContext externalContext = context.getExternalContext();
          HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
          HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();

          // Create dispatcher for the resource given by the componen's page attribute.
          RequestDispatcher requestDispatcher = request.getRequestDispatcher((String) getAttributes().get("page"));

          // Catch the resource's output.
          CharResponseWrapper responseWrapper = new CharResponseWrapper(response);
          requestDispatcher.include(request, responseWrapper);

          // Write the output from the resource to the JSF response writer.
          context.getResponseWriter().write(responseWrapper.toString());
       }
       catch (ServletException e) {
          throw new IOException();
       }
    }

}

创建类com.example.CharResponseWrapper
public class CharResponseWrapper extends HttpServletResponseWrapper {

   private CharArrayWriter output;

   @Override
   public String toString() {
      return output.toString();
   }

   public CharResponseWrapper(HttpServletResponse response) {
      super(response);
      output = new CharArrayWriter();
   }

   public CharArrayWriter getCharWriter() {
      return output;
   }

   @Override
   public PrintWriter getWriter() {
       return new PrintWriter(output);
  }

   @Override
   public ServletOutputStream getOutputStream() {
      return new CharOutputStream(output);
   }

   public InputStream getInputStream() {
      return new ByteArrayInputStream( toString().getBytes() );
   }
}

class CharOutputStream extends ServletOutputStream {

   private Writer output;

   public CharOutputStream( Writer writer ) {
      output = writer;
   }

   @Override
   public void write(int b) throws IOException {
      output.write(b);
   }
}

faces-config.xml中添加。
<component>
    <component-type>com.example.component.JSPIncludeComponent</component-type>
    <component-class>com.example.component.JSPIncludeComponent</component-class>
</component>

在WEB-INF文件夹中创建文件my.taglib.xml(Facelet标记库)。
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">

<facelet-taglib>
    <namespace>http://example.com/jsf</namespace> 

    <tag>
      <tag-name>include</tag-name>
      <component>
        <component-type>com.example.component.JSPIncludeComponent</component-type>
      </component>
    </tag>

</facelet-taglib>

按照http://docs.oracle.com/javaee/6/tutorial/doc/bnawn.html中的说明,将以下内容添加到web.xml文件中:

<context-param>
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name>
    <param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>

这样你就可以将它用作

<ui:component 
    xmlns:my="http://example.com/jsf"
    xmlns:ui="http://java.sun.com/jsf/facelets"
>
    <my:include page="page.jsp" />
</ui:composition>

最后但并非最不重要的,记录下他的遗言。

我不建议将此作为长期解决方案,但它可能会使从具有令人作呕的脚本片段的旧JSP迁移到更明智和现代化的Facelets应用程序变得更加容易。


这种方法对我似乎不起作用,http://stackoverflow.com/questions/10128023/unable-to-add-jsp-page-to-xhtml-page - Rachel
我确认这也适用于XHTML页面。这样做有什么缺点吗?比如不同FacesContexts使用的一些请求映射变量... - Abbas Gadhia
@Nerrve: 它共享相同的HTTP请求,因此JSP / Servlet有机会访问和操作所有请求/会话/应用程序属性,这些属性也被JSF使用。顺便说一句,这也可以作为OmniFaces中可重用组件提供(具有改进的“HttpServletResponseWrapper”,可以正确地考虑字符编码)。另请参阅https://showcase-omnifaces.rhcloud.com/showcase/components/resourceInclude.xhtml - BalusC

1

不行。JSP 和 facelets 不能一起评估 - 您只有一个视图处理程序,它处理 facelets 而不是 JSP。

<c:import> 如果 jsp 可通过 http 访问,则会起作用,因此将包含其输出,而不是代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接