我在Facelets上使用Myfaces 2. 我必须在Facelet页面中包含一个JSP页面. 我尝试使用 ui:include但它只需要XHTML页面. 我也尝试过使用 c:import和 f:subview但没有任何效果. 谷歌搜索了很多,但没有
我必须在Facelet页面中包含一个JSP页面.
我尝试使用< ui:include>但它只需要XHTML页面.
我也尝试过使用< c:import>和< f:subview>但没有任何效果.
谷歌搜索了很多,但没有得到确切的答案.
我怎样才能达到要求?
使用自定义UIComponent可以实现这一点.我的同事一年前写了一篇博客文章: Facelets and legacy 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 taglib)
<!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>
添加到web.xml(如http://docs.oracle.com/javaee/6/tutorial/doc/bnawn.html中所述)
<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>
最后但并非最不重要的是,标记他的遗言
I wouldn’t recommend using this as a lasting solution, but it might ease a migration from legacy JSP with smelly scriptlets and all on them to a more sane and modern Facelets application.