如果数据源是XML,我建议采用完全不同的方法:
XSL。Facelets基于XHTML。您可以轻松使用XSL从XML转换为XHTML。这可以通过一个相当不错的
Filter
实现,在JSF开始工作之前启动该过滤器即可。
以下是一个示例:
persons.xml
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person>
<name>one</name>
<age>1</age>
</person>
<person>
<name>two</name>
<age>2</age>
</person>
<person>
<name>three</name>
<age>3</age>
</person>
</persons>
persons.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
<xsl:template match="persons">
<html>
<f:view>
<head><title>Persons</title></head>
<body>
<h:panelGrid columns="2">
<xsl:for-each select="person">
<xsl:variable name="name"><xsl:value-of select="name" /></xsl:variable>
<xsl:variable name="age"><xsl:value-of select="age" /></xsl:variable>
<h:outputText value="{$name}" />
<h:outputText value="{$age}" />
</xsl:for-each>
</h:panelGrid>
</body>
</f:view>
</html>
</xsl:template>
</xsl:stylesheet>
JsfXmlFilter
被映射到FacesServlet
的<servlet-name>
,并假定FacesServlet
本身被映射到*.jsf
的<url-pattern>
上。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest r = (HttpServletRequest) request;
String rootPath = r.getSession().getServletContext().getRealPath("/");
String uri = r.getRequestURI();
String xhtmlFileName = uri.substring(uri.lastIndexOf("/")).replaceAll("jsf$", "xhtml");
File xhtmlFile = new File(rootPath, xhtmlFileName);
if (!xhtmlFile.exists()) {
String xmlFileName = xhtmlFileName.replaceAll("xhtml$", "xml");
String xslFileName = xhtmlFileName.replaceAll("xhtml$", "xsl");
File xmlFile = new File(rootPath, xmlFileName);
File xslFile = new File(rootPath, xslFileName);
Source xmlSource = new StreamSource(xmlFile);
Source xslSource = new StreamSource(xslFile);
Result xhtmlResult = new StreamResult(xhtmlFile);
try {
Transformer transformer = TransformerFactory.newInstance().newTransformer(xslSource);
transformer.transform(xmlSource, xhtmlResult);
} catch (TransformerException e) {
throw new RuntimeException("Transforming failed.", e);
}
}
chain.doFilter(request, response);
}
运行在 http://example.com/context/persons.jsf 上,该过滤器将会启动并使用 persons.xsl
将 persons.xml
转换成 persons.xhtml
,最终将 persons.xhtml
放置在 JSF 期望的位置。
确实,XSL 有一定的学习曲线,但我认为它是正确的工具,因为源是 XML,目的地也是基于 XML 的。
要在表单和托管 bean 之间进行映射,只需使用一个 Map<String, Object>
。如果你将输入字段命名为下面这样:
<h:inputText value="#{bean.map.field1}" />
<h:inputText value="#{bean.map.field2}" />
<h:inputText value="#{bean.map.field3}" />
...
提交的值将通过 field1
、field2
、field3
等键作为 Map
的可用值。