作者: prakash malani
原文: http://www.javaworld.com/javaworld/jw-01-2002/jw-0104-tilestrut.html
译者: sunnyrainy
email: sunnyrainy5@hotmail.com
qq: 273771372
msn: yo13579@sohu.com
摘要
每个web应用开发者一定组织视图组件,例如 页首,正文体和页尾。 有许多技术可以组织这些组件, 但每个都有优缺点。这篇文章包括了7个可用的解决方案并让你了解 tiles框架和struts框架的灵活性。从一个简单的说明组织视图组件的例子开始,然后使用 jsp内建的机制,像include, 彻底地解决问题。继续看其他的使用tiles框架的替换方案,然后学会平衡tiles框架和struts框架的协作。 (2,000个字;2002 年1月 4 日)
在web应用软件开发中,一般用户界面负责站点的外观感觉,它可以让人产生真切的感受。通过界面的展现,来展示应用程序功能和导航。基于servlet和jsp技术实现用户界面时,当html页面被转换为servlets和jsps时,ui开发人员必须识别哪些是公共的普通html页面,哪些是jsp页面组件,如标题、页脚,主体,菜单和搜索等。这篇文章提供了多种有效的解决方案来组织html和jsp视图组件。每个方案都使用了特定的标准,像页数、编码重复和布局控制等。
为了探究模板和布局方案,我们使用tiles 框架.tiles 框架的视图组件叫做tiles。框架 使用xml配置文件来组织这些tiles.框架不仅能让你再次使用tiles,而且还可以对他们进行设计组织。
为了探寻更强大和灵活的方案,我们研究tiles框架和struts 框架之间的协作。struts是一个使用流行的mvc或者model 2结构模式的用于开发web 应用软件的开源框架.struts 有着强大标签库,tile框架的标签库加入使其更加完善。
评价标准
评价每个方案有如下标准。标准是兼容的。对于特定的情况和特殊的应用,必须经常均衡每个方案中这些因素的优势与缺陷。
页数(page number)
方案必须尽量使html and jsp的页数减到最小。因为页数增加,开发、管理、维护一个应用程序的复杂性将会急剧增加。
代码重复(code repetiton)
在大多数情况下,重复是不好的。html and jsp编码越是重复,开发和维护应用程序就越困难。一个简单变化可能在许多不同页面上导致一连串不可预期结果的改变。具体和实际的获得重新使用的方式应避免编码重复。
布局控制(layout comtrol)
尽管编码重复是不好的,但是布局逻辑和编码重复的会更糟。在几个jsps中的扩展视图组件结构的逻辑和行为可以是一个解决灾难的方法。获得模板的设计逻辑的重复使用是一种比仅仅重复使用视图组件更好的形式。因此,你可以通过有效的布局控制达到一个更高的重复使用的水平。
耦合(coupling)
耦合是个实体间的兼容性的一个度。软件工程师被重复教育要使不相干的类、包等等之间的耦合减到最小。我们可以对视图组件应用相同的原理。尽管从一个使用者角度讲视图组件之间是有区别的,但在jsp执行中,组建可能被杂乱的连接。一种解决方案使必须减少不相干视图组件之间的耦合.
复杂性(complexity)
复杂性导致了更多的开发和维护费用,也使得更多的复杂方案不合适。当你增加更多的部分时,复杂性同时也在增加,这将使原本看起来简单的和无害的东西很快转变为大混乱。
解决方案
我将使用基本的jsps例子。通过像header ,footer这样的普通的视图组件来评价一些方案。我将按增加复杂性的顺序给出这些方案,然后相对于评价标准详细的评价每一个。
方案1:基本的jsp
假如a.jsp如下:
<html>
<body>
header<p>
a's body...<p>
footer<p>
</body>
</html>
<html>
<body>
header<p>
b's body...<p>
footer<p>
</body>
</html>
<html>
<body>
<%-- include header --%>
<jsp:include page="/header.jsp" />
a's body...
<p>
<%-- include footer --%>
<jsp:include page="/footer.jsp" />
</body>
</html>
html>
<body>
<%-- include header --%>
<jsp:include page="/header.jsp" />
b's body...
<p>
<%-- include footer --%>
<jsp:include page="/footer.jsp" />
</body>
</html>
注意到普通的诸如header和footer这样的视图组件,使用jsp 的include结构使其分开来了。
假如 header.jsp如下:
header
<p>
假如footer.jsp如下:
footer
<p>
假如a.jsp如下:
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
a's body...
<p>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
假如b.jsp如下:
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
b's body...
<p>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
假如 a.jsp如下:
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
<%-- include body --%>
<tiles:insert page="abody.jsp" flush="true"/>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
假如b.jsp如下:
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert page="/header.jsp" flush="true"/>
<%-- include body --%>
<tiles:insert page="bbody.jsp" flush="true"/>
<%-- include footer --%>
<tiles:insert page="/footer.jsp" flush="true"/>
</body>
</html>
方案4与tiles insert方案有些小的不同。方案4将核心主体分隔成几个单独页面,如abody.jsp and abody.jsp.
假如 abody.jsp如下:
a's body...
<p>
假如bbody.jsp如下:
b's body...
<p>
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<html>
<body>
<%-- include header --%>
<tiles:insert attribute="header"/>
<%-- include body --%>
<tiles:insert attribute="body"/>
<%-- include footer --%>
<tiles:insert attribute="footer"/>
</body>
</html>
其它的内容页,像a.jsp and b.jsp使用如上布局来放置组件。在实际的页面里,使用tiles insert tag来插入布局。使用tiles put tag可以为布局中特定的标识符指定实际的视图组件。
假如a.jsp如下:
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<tiles:insert page="/layout.jsp" flush="true">
<tiles:put name="header" value="/header.jsp"/>
<tiles:put name="body" value="/abody.jsp"/>
<tiles:put name="footer" value="/footer.jsp"/>
</tiles:insert>
假如b.jsp如下:
<%@ taglib uri="/web-inf/tiles.tld" prefix="tiles" %>
<tiles:insert page="/layout.jsp" flush="true">
<tiles:put name="header" value="/header.jsp"/>
<tiles:put name="body" value="/bbody.jsp"/>
<tiles:put name="footer" value="/footer.jsp"/>
</tiles:insert>
<?xml version="1.0" encoding="iso-8859-1"?>
<component-definitions>
<definition name="adef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value="/abody.jsp"/>
</definition>
<definition name="bdef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value="/bbody.jsp"/>
</definition>
<definition name="cdef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value="/cbody.jsp"/>
</definition>
</component-definitions>
方案6把定义放置在xml文件中,消除了就像a.jsp and b.jsp一样的所有内容页。因像a.jsp and b.jsp这样的程序不再存在,我们怎样请求他?更重要的是,如何在tiledefinitions.xml文件中请求定义?
struts and tiles强大和协作的整体可被挽回。除了常规的配置参数以外,我们在web.xml文件中作为另一个参数指定配置文件的地址。如下所示。指定参数definitions_config使struts能找到并知道关于tiles 的定义。
<!-- standard action servlet configuration (with debugging) -->
<servlet>
<servlet-name>action</servlet-name>
<!--
<servlet-class>org.apache.struts.action.actionservlet</servlet-class>
-->
<servlet-class>org.apache.struts.tiles.actioncomponentservlet</servlet-class>
<init-param>
<param-name>definitions-config</param-name>
<param-value>/web-inf/tiledefinitions.xml</param-value>
</init-param>
...
</servlet>
我们现在定义一个struts action,他将返回一个成功的在配置文件中指定的定义。struts action dofirst 是一个不运行的行为,如下所示:
package com.malani.struts.action;
import org.apache.struts.action.*;
import javax.servlet.http.*;
public class dofirst extends action {
public actionforward perform(
actionmapping amapping,
actionform aform,
httpservletrequest arequest,
httpservletresponse aresponse
) {
return amapping.findforward("success");
}
}
你不能使用直接来自浏览器的定义,但是 你可以使用来自struts的就像实际程序一样的一个。在struts-config.xml的文件中定义struts actions如下:
<action path="/a"
type="com.malani.struts.action.dofirst"
>
<forward name="success" path="adef"/>
</action>
<action path="/b"
type="com.malani.struts.action.dofirst"
>
<forward name="success" path="bdef"/>
</action>
<action path="/c"
type="com.malani.struts.action.dofirst"
>
<forward name="success" path="cdef"/>
</action>
现在通过分别请求a.do and b.do actions来返回所需的程序。
<?xml version="1.0" encoding="iso-8859-1"?>
<component-definitions>
<definition name="basedef" path="/layout.jsp">
<put name="header" value="/header.jsp"/>
<put name="footer" value="/footer.jsp"/>
<put name="body" value=""/>
</definition>
<definition name="adef" extends="basedef">
<put name="body" value="/abody.jsp"/>
</definition>
<definition name="bdef" extends="basedef">
<put name="body" value="/bbody.jsp"/>
</definition>
<definition name="cdef" extends="basedef">
<put name="body" value="/cbody.jsp"/>
</definition>
</component-definitions>
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器