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容器也提供了,但还是要警惕,它可能是一些错误的根源。