XSLT是一种用于XML的转换语言,并作为一种在web应用中使用的view层技术广为人知。 如果你的应用本来就要处理XML,或者模型数据可以很容易转化为XML,那么XSLT是一个很好的选择。 下面的内容展示了在一个Spring MVC 应用中如何生成XML格式的模型数据,并用XSLT进行转换。
这是一个很小的Spring应用的例子,它只是在Controller中创建一个词语列表,并将它们加至模型数据(model map)。
模型数据和我们的XSLT视图名一块儿返回。
请参考 第 13.3 节 “控制器” 中关于Spring MVC Controller接口的细节。
XSLT视图把词语列表转化为一段简单XML,等待后续转换。
这是一个简单的Spring应用的标准配置。dispatcher servlet配置文件包含一个指向
ViewResolver的引用、URL映射和一个简单的实现了我们的词语生成逻辑的controller bean:
<bean id="homeController"class="xslt.HomeController"/>
它实现了我们的词语生成“逻辑”。
控制器逻辑封装在一个AbstractController的子类,它的handler方法定义如下:
protected ModelAndView handleRequestInternal(
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map map = new HashMap();
List wordList = new ArrayList();
wordList.add("hello");
wordList.add("world");
map.put("wordList", wordList);
return new ModelAndView("home", map);
}
到目前为止,我们还没有做什么特定于XSLT的事情。在任何一种Spring MVC应用中,模型数据都以同样的方式被创建。
现在根据应用的配置,词语列表可以作为请求属性加入从而被JSP/JSTL渲染,或者通过加入VelocityContext来被Velocity处理。
为了使用XSLT渲染它们,应该以某种方式把它们转化为XML文档。有些软件包能自动完成对象图到XML文档对象模型的转化。
但在Spring中,你有完全的自由度,能以任何方式完成从模型数据到XML的转化。
这可以防止XML转化部分在你的模型结构中占据太大的比重,使用额外工具来管理转化过程是一种风险。
为了从词语列表或任何其他模型数据创建XML文档,我们必须创建一个 org.springframework.web.servlet.view.xslt.AbstractXsltView 的子类,
通常我们也必须实现抽象方法 createXsltSource(..)s。其第一个参数即model Map。
下面是我们这个小应用中HomePage类的完整代码:
package xslt;
// imports omitted for brevity
public class HomePage extends AbstractXsltView {
protected Source createXsltSource(Map model, String rootName, HttpServletRequest
request, HttpServletResponse response) throws Exception {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = document.createElement(rootName);
List words = (List) model.get("wordList");
for (Iterator it = words.iterator(); it.hasNext();) {
String nextWord = (String) it.next();
Element wordNode = document.createElement("word");
Text textNode = document.createTextNode(nextWord);
wordNode.appendChild(textNode);
root.appendChild(wordNode);
}
return new DOMSource(root);
}
}
你可以在上述子类中定义一些传给转化对象的参数,它们由健值对(name/value pairs)构成,
其中参数名必须与XSLT模板中定义的 <xsl:param name="myParam">defaultValue</xsl:param> 一致。
为了指定这些参数,你需要覆写继承自AbstractXsltView 的 getParameters() 方法并返回一个包含健值对的Map。
如果你需要从当前请求中获取信息,你可以选择覆写 getParameters(HttpServletRequest request) 方法。(这个方法只有Spring 1.1以后的版本才支持。)
比起JSTL和Velocity,XSLT对本地货币和日期格式的支持相对较弱。
基于这点,Spring提供了一个辅助类,你可以在 createXsltSource(..) 方法中调用它来获得这样的支持。
请参考 org.springframework.web.servlet.view.xslt.FormatHelper 类的Javadoc。
对于“写在段首”中的只有一个视图的情况来说,views.properties文件(或者等价的xml文件,如果你用一种基于XML的视图解析器的话,就像在上面的Velocity例子中)看起来是这样的:
home.class=xslt.HomePage home.stylesheetLocation=/WEB-INF/xsl/home.xslt home.root=words
这里你可以看到,第一个属性'.class'指定了视图类,即我们的HomePage,其中完成从模型数据到XML文档的转化。
第二个属性'stylesheetLocation'指定了XSLT文件的位置,它用于完成从XML到HTML的转化。
最后一个属性'.root'指定了用作XML文档根元素的名字,它被作为 createXsltSource(..) 方法的第二个参数传给HomePage类。
最后,我们有一段转换上述文档的XSLT代码。
正如在'views.properties'中看到的,它被命名为 'home.xslt',存放在war文件中的 'WEB-INF/xsl'目录下。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head><title>Hello!</title></head>
<body>
<h1>My First Words</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="word">
<xsl:value-of select="."/><br/>
</xsl:template>
</xsl:stylesheet>
下面是一个简化的WAR目录结构,其中总结了上面提到的文件和它们在WAR中的位置:
ProjectRoot
|
+- WebContent
|
+- WEB-INF
|
+- classes
| |
| +- xslt
| | |
| | +- HomePageController.class
| | +- HomePage.class
| |
| +- views.properties
|
+- lib
| |
| +- spring.jar
|
+- xsl
| |
| +- home.xslt
|
+- frontcontroller-servlet.xml
你要确保classpath下存在XML解析器和XSLT引擎。JDK1.4默认已提供了这些,多数J2EE容器也提供了,但还是要警惕,它可能是一些错误的根源。