我正在使用Facelets上的Myfaces 2。
我需要在一个Facelet页面中包含一个JSP页面。
我尝试使用<ui:include>
,但它只能接受XHTML页面。
我还尝试使用<c:import>
和<f:subview>
,但都没有成功。
我搜索了很多,但没有得到确切的答案。
我该如何实现这个要求?
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>
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应用程序变得更加容易。
不行。JSP 和 facelets 不能一起评估 - 您只有一个视图处理程序,它处理 facelets 而不是 JSP。
<c:import>
如果 jsp 可通过 http 访问,则会起作用,因此将包含其输出,而不是代码。