信息化 频道

从二维到三维



【IT168 专稿】

整合Java 6脚本、Groovy实现动态 MVC模式(一)

四、使用FreeMarker实现视图

    到现在为止,我们已经实现了商业逻 辑,在这一节中让我们来向程序中加入视图。

   
作为首选, 我们来使用FreeMarker来实现这个视图,我们要做的第一件事就是下载 FreeMarker库,并将freemarker.jar放到 Test\WEB-INF\lib中。为了在FreeMarker中使用 XPath表达式来处理XML,我们使用一个 XSLT引擎:Jaxen,因此,我们需要下 载这个Jaxen,并将所有满足jaxen-*.jar的文件复制到 Test\WEB-INF\lib中。

   
然后,我们 需要编辑WebLEAF配置文件(Test\WEB-INF\Test.leaf.conf),这个配置很简单,只要在XMLOPERATION中加一个属性 即可(FM_TEMPLATE="item.ftl") ,WebLEAF配置文件的内容如下:

<?xml version="1.0" encoding="iso-8859- 1"?> <!DOCTYPE WADSET SYSTEM "http://www.uib.es/leaf/LEAFwad.dtd"> <WADSET> <WAD NAME="Test" INIT_MODE="INITS_ON_START_UP" XML_ALLOW_SHOW="TRUE" XSLT_NO_CACHE="TRUE" > <OPERATIONSET> <SUFFIX VALUE="fm"/> <XMLOPERATION NAME="showItems" DESCRIPTION="Shows all the items and the selected one" CLASSNAME="org.leaf.XMLOperation" FM_TEMPLATE="item.ftl" > <SOURCES GLOBAL_TAG="XML_APP" > <SOURCE XML_SOURCE="xml/Labels.xml"/> <SOURCE XML_SOURCE="script://scr/Item.groovy/show?w_"/> </SOURCES> </XMLOPERATION> </OPERATIONSET> </WAD> </WADSET>

    然后我们在 Test\WEB-INF在建立一个templates目录,并在其中 加入两个文件(item.ftlmain.ftl),item.ftl的内容如下:

main.ftl的内容如下:

<#-- Direct handle for the labels --> <#assign Labels = doc.XML_APP.LABELS[0]> <#-- Main reusable macro to create each page --> <#macro Main_Page> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>${Labels.@Title}${Title} (FREEMARKER)</title> <meta http-equiv="Expires" content="now"/> <meta http-equiv="Pragma" content="no-cache"/> <meta http-equiv="Cache-Control" content="private"/> </head> <body> <#nested> <a href="./">Back to index</a> </body> </html> </#macro>
    
     
下面我们来启动Servlet容器,并输入URL:http://localhost:8080/test/showitems.fm。然后我们会看到如图2的界面:



图2 由FreeMarker产生的演示项目列表的程序界面

如果我们选择其中一项,我们会看到它的数据,如图3所示:



 FreeMarker产生的显示项目细节的应用程序界面



五、通过XSLT实现视图层

    我们已经使用FreeMarker实现了视图层,但这并不唯一的选择,我们还可以有其他的实现方式,如我们可以使用XSLT来达到同样的效果。在开始这一节之前,我们必须将XSLT引擎Jaxen放到classpath中。

   
在这个使用XSLT的例子中,我们只需要加一个新的XMLOPERATION节点,它将使用和前面的介绍相同的数据,所不同的是在这里将使用XSLT来代替FreeMarker处理XML。如果我们想让两种方法并存的话,可以加入另一个OPERATIONSET块。我们的WebLEAF配置文件如下:

<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE WADSET SYSTEM "http://www.uib.es/leaf/LEAFwad.dtd"> <WADSET> <WAD NAME="Test" INIT_MODE="INITS_ON_START_UP" XML_ALLOW_SHOW="TRUE" XSLT_NO_CACHE="TRUE" > <OPERATIONSET> <SUFFIX VALUE="fm"/> <XMLOPERATION NAME="showItems" DESCRIPTION="Shows all the items and the selected one" CLASSNAME="org.leaf.XMLOperation" FM_TEMPLATE="item.ftl" > <SOURCES GLOBAL_TAG="XML_APP" > <SOURCE XML_SOURCE="xml/Labels.xml"/> <SOURCE XML_SOURCE="script://scr/Item.groovy/show?w_"/> </SOURCES> </XMLOPERATION> </OPERATIONSET> <OPERATIONSET> <SUFFIX VALUE="xsl"/> <XMLOPERATION NAME="showItems" DESCRIPTION="Shows all the items and the selected one" CLASSNAME="org.leaf.XMLOperation" XSLT_SOURCE="xsl/Item.xsl" > <SOURCES GLOBAL_TAG="XML_APP" > <SOURCE XML_SOURCE="xml/Labels.xml"/> <SOURCE XML_SOURCE="script://scr/Item.groovy/show?w_"/> </SOURCES> </XMLOPERATION> </OPERATIONSET> </WAD> </WADSET>

    为了处理这些新请求,我们需要再次编辑web.xml配置文件,在WebLEAF控制servlet中加入一个以".xls"的请求后缀。也就是在下面再加入一个<servlet-mapping/>标签,web.xml的内容如下:

<?xml version="1.0"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> <web-app> <!-- Autoconfiguration servlet --> <servlet> <servlet-name>AutoConfigurer</servlet-name> <servlet-class>org.leaf.util.AutoConfigurer</servlet-class> <load-on-startup>1</load-on-startup> <init-param> <param-name>FILE_NAME.1</param-name> <param-value>WEB-INF/classes/webapp.properties</param-value> </init-param> <init-param> <param-name>NODES_NAME.1</param-name> <param-value>db.location</param-value> </init-param> <init-param> <param-name>PATTERN.1</param-name> <param-value>(.*)/WEB-INF/(.*)</param-value> </init-param> <init-param> <param-name>FORMAT.1</param-name> <param-value>{0}WEB-INF/{1}</param-value> </init-param> <servlet> <servlet-name>WebLEAFController</servlet-name> <servlet-class>org.leaf.LEAFManager</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <!-- End controller servlet --> <servlet-mapping> <servlet-name>WebLEAFController</servlet-name> <url-pattern>*.fm</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>WebLEAFController</servlet-name> <url-pattern>*.xsl</url-pattern> </servlet-mapping> </web-app>
最后,我们通过在Test\WEB-INF\xsl中建立一个item.xsl,这是XSLT的实现,它的内容如下:

<?xml version="1.0" encoding="iso-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html" indent="yes" media-type="text/html" encoding="iso-8859-1" /> <xsl:variable name="labels" select="/XML_APP/LABELS" /> <xsl:template match="/"> <html> <head> <META HTTP-EQUIV="Expires" CONTENT="now"/> <META HTTP-EQUIV="Pragma" CONTENT="no-cache"/> <META HTTP-EQUIV="Cache-Control" CONTENT="private"/> <title><xsl:call-template name="TITLE"/>(XSLT)</title> </head> <body> <xsl:apply-templates/> <a href="./">Back to index</a> </body> </html> </xsl:template> <xsl:template name="TITLE"> <xsl:value-of select="$labels/@Title"/> <xsl:apply-templates mode="SUB_TITLE"/> </xsl:template> <xsl:template match="ITEM_QUERY[@Type='All']" mode="SUB_TITLE"> - <xsl:value-of select="$labels/ITEM/@Title"/> </xsl:template> <xsl:template match="ITEM_QUERY[@Type='All']"> <xsl:variable name="theItem" select="/XML_APP/ITEM_QUERY[@Type='Selected']/ITEM" /> <fieldset> <legend> <xsl:value-of select="$labels/ITEM/@FieldSetLegend"/> </legend> <form id="itemForm" name="itemForm" action=""> <select id="w_p_ite_code" name="w_p_ite_code" onchange="itemForm.submit();" > <option value=""> <xsl:value-of select="$labels/ITEM/@SelectDefault"/> </option> <xsl:for-each select="ITEM"> <option value="{@Code}"> <xsl:if test="$theItem/@Code = @Code"> <xsl:attribute name="selected"> selected </xsl:attribute> </xsl:if> <xsl:value-of select="@Name"/> </option> </xsl:for-each> </select> </form> <xsl:if test="$theItem"> <b><xsl:value-of select="$labels/ITEM/@Name"/></b>: <xsl:value-of select="$theItem/@Name"/> <br /> <b><xsl:value-of select="$labels/ITEM/@Description"/></b>: <xsl:value-of select="$theItem/@Description"/> </xsl:if> </fieldset> </xsl:template> </xsl:stylesheet>
    现在我们可以再次启动Servlet容器,并访问http://localhost:8080/test/showItems.xsl(注意现在的后缀是".xsl",而不是".fm")。我们看到的结果和前面的完全一样,只是实现的方法不同而已。




六、完成最后的工作

    现在我们几乎做完了所有的事情,接下来我们为程序加一个小的HTML文件,以便我们可以有一个总的界面来显示程序的如有的功能。这个文件是index.html,放到Test中,它的内容如下:

<html> <head> <title>Test application</title> </head> <body> Application to test the possibilities of WebLEAF 3.0b + Groovy + HSQLDB <br /> <ul>Test these urls: <li> <a href="showItems.fm?showXMLSource=true"> Listing items in the database as XML with Groovy </a> <ul><b>Notes</b> <li>The LABELS node comes from the file at <i>WEB-INF/xml/Labels.xml</i> </li> <li>The ITEM_QUERY node is generated using the Groovy script at <i>WEB-INF/scr/Item.groovy</i> </li> </ul> </li> <li><a href="showItems.fm"> Listing items in the database with Groovy + FreeMarker </a> </li> <li><a href="showItems.xsl"> Listing items in the database with Groovy + XSLT </a> </li> </ul> </body> </html>
 我们输入URL: http://localhost:8080/test/来访问程序,界面如图4所示:



 图4:应用程序的首页
 
 
七、结论

    现在我们已经做完了所有的工作,在我们的应用程序中,我们可以直接修改商业逻辑(Item.groovy),或更改视图的实现(Item.ft/Main.ftl或Item.xsl和Labels.xml)。而并不需要重新编译或重新启动Servlet容器。我们的变化会自动更新。

    也许我们应该感谢XML,通过它可以重用很多Java库,如动态地使用SVG和Batik,PDF报表(基于XMLDataSource的JasperReports)等。

    通过上述的例子我们可以得出一个结论,不同的视图技术并不互相排斥。如果你喜欢XLST,就可以生成一个纯文本的文档(象一个AJAX请求的JSON响应一样),你可以很容易地重用同样的商业逻辑、操作和实现,就象FreeMarker一样。

    最后,我们使用了Groovy作为脚本引擎,也许我们应该感谢Groovy工程,正因为有了它,我们才可以在Java中使用其他的脚本语言,而这一切只需要简单地变化文件的XML_SOURCE 即可。感兴趣的读者可以试试使用Jython或PHP来实现这个应用。
0
相关文章