dev2dev 首页 > 资源中心 > 技术文章
深入Beehive标签库系列教程(8) - 基于模版的页面组装技术
目前基于J2EE的企业应用开发都采用了以Servlet为核心的开发架构,选择使用JSP作为信息显示组件,因此企业应用中的业务数据、表单、企业应用整体设计风格等可视化元素都采用JSP来展示。同时企业应用的信息展示也基本都采用主题区的方式进行展示,比如大部分企业应用的用户界面上都包括了导航信息展示区、包含企业logo和banner的页眉区、包含企业版权信息和其他相关信息的页脚区、显示企业业务信息/表单等的主显示区等,通常我们都将这些显示区要显示的内容包含在不同的JSP文件中,如何将这些不同的JSP文件组合成一个显示给用户的最终页面就是页面组装。 NETUI提供了丰富的标签来协助我们完成页面组装,他的工作原理是定义一个模版文件,模版文件中定义了页面结构、布局和相关显示区的占位符,这些占位符还可以设定默认要显示的内容,方便开发者在模版文件中直接定义在每个页面都需要显示的公共内容。开发者还需要提供可供访问的内容页----一个或者多个JSP页面,内容页中确定这些占位符对应显示的JSP内容,用户访问内容页的时候,NETUI从模版文件中获取页面结构和布局信息,格式化输出内容页中的内容。我们可以使用下面这个图来显示NETUI完成页面组装的原理。

图1 页面组装原理示意图
从上面的图中,我们可以看到NETUI中支持页面组装的主要标签有netui-template:attribute、netui-template:setAttribute、netui-template:includeSection、netui-template:template、netui-template:section,其中netui-template:attribute和netui-template:includeSection是适用于模版文件中的标签,另外三个标签用于在用户可访问的JSP页面中。
- netui-template:attribute
netui-template:attribute标签用于在模版页中定义变量,这些变量的内容将在内容页中提供。我们可以设置它的name属性为他提供唯一标识符,还可以设置它的default属性为它提供默认内容。如果内容页中为这个attribute提供了内容,模版页将使用内容页中提供的内容,否则使用默认值。一个模版文件中可以有多个netui-template:attribute标签。 比如在显示页面时,每个页面的title通常都不同,所以我们可以在模版页中用下面的代码来定义一个名为title的Attribute,它的内容将被作为显示给用户页面的title,默认值是“www.vivianj.org”。
- <title>
- <netui-template:attribute name=“title” default=“www.vivianj.org” />
- </title>
在内容页中,我们可以使用netui-template:setAttribute标签为模版文件中的属性赋值,比如我们需要将上面模版文件中的title内容修改为“VIVIANJ主页”,我们可以使用下面的代码。 <netui-template:setAttribute name=“title” value=”VIVIANJ主页” />
- netui-template:includeSection
netui-template:includeSection用于在模版中提供动态内容的占位符,通知模版该占位符所在的位置的内容将由其他内容页来提供,动态内容可以是一个独立的JSP页面,也可以是内容页中的一段代码。一个模版文件中可以有多个netui-template:includeSection标签。 我们可以设置它的name属性为他提供唯一标识符,还可以设置它的defaultPage属性为它提供默认内容。如果内容页中为该占位符提供了动态内容,模版将使用内容页中提供的内容,否则使用默认的内容填充占位符。提醒大家注意的是,defaultPage属性中指定文件路径时需要使用从应用根目录开始的路径,这样不会因为内容页所在目录的原因出现问题。 比如我们可以使用下面的代码在模版文件中提供一个占位符,它的默认内容是/pub/header.jsp。
- <netui-template:includeSection name=“header”
- defaultPage=“/pub/header.jsp” />
- netui-template:template
netui-template:template标签用于内容页中,设置该内容页对应的模版文件,标签的templatePage属性可用于设置模版文件的目标地址。一个内容页中只能有一个netui-template:attribute标签。指定模版文件路径时需要使用从应用根目录开始的路径,这样不会因为内容页所在目录的原因出现问题。 比如我们可以使用下面的代码来设置内容页使用/pub/pub-template.jsp作为模版文件。 <netui-template:template templatePage=“/pub/pub-template.jsp”>
- netui-template:setAttribute
netui-template:setAttribute标签用于内容页中,可以为模版页中定义的Attribute提供具体内容,它有两个属性:name和value,其中的name的内容是模版页中Attribute对应的name属性,而value属性用于为该Attribute提供具体内容。 比如我们可以在内容页中使用下面的代码为模版页中的名为”title”的Attribute提供动态内容。 <netui-template:setAttribute name=“title” value=”欢迎访问www.vivianj.org” />
- netui-template:section
netui-template:section标签用于内容页中,可以用来为模版页中的占位符提供动态内容,它使用属性name来对应模版页中的占位符。模版页中定义的占位符如果没有提供default参数,在内容页中就必须有一个对应的netui-template:section标签为该占位符提供动态内容。 我们可以使用下面的代码来为模版页中名为”content”的占位符动态内容。
- <netui-template:section name=“content”>
- <!—在这里加入要显示的动态内容-->
- </netui-template:section>
使用NETUI完成页面组装的完整例子
我们用一个简单的例子来演示如何使用NETUI完成页面组装,假设我们要完成下面这样一个页面的组装。 
图2 页面组装例子的效果图
页面的顶部固定显示header.jsp文件的内容,底部固定显示footer.jsp文件的内容,左边的导航区默认总是显示navi.jsp文件的内容,只有右边的灰色区域的内容是动态的。 根据页面结构和NETUI页面组装的定义,我们可以使用下面的代码来定义模版文件(参见清单1)和内容页文件(参见清单2)。
清单1 web\template\vivianj-template.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-databinding-1.0"
- prefix="netui-data"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-html-1.0"
- prefix="netui"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-template-1.0"
- prefix="netui-template"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <netui-data:declareBundle
- bundlePath="org.vivianj.beehive.examples.netui.resources" name="view" />
- <netui:html>
- <head>
- <title><%-- Set the title based on the title attribute --%>
- <netui-template:attribute name="title" /> - ${bundle.view.hellostring} </title>
- <link rel="stylesheet"
- href="${pageContext.request.contextPath}/css/vivianj.css"
- type="text/css" />
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- </head>
- <netui:body>
- <center>
- <%-- Always show the header --%>
- <%-- Include the template's "body" section --%>
- <netui-template:includeSection name="header"
- defaultPage="/pub/header.jsp" />
- <table cellpadding="0" cellspacing="0" border="0" width="767">
- <tr>
- <td valign="top" width="191" bgcolor="#F9C9F3">
- <%-- Include the template's "left" section --%>
- <netui-template:includeSection name="left" defaultPage="/pub/navi.jsp" />
- </td>
- <td valign="top" width="570" bgcolor="#FDE7FA">
- <%-- Include the template's "right" section --%>
- <netui-template:includeSection name="right" /></td>
- </tr>
- </table>
- <%-- Include the template's "bottom" section --%>
- <netui-template:includeSection
- name="bottom" defaultPage="/pub/footer.jsp" />
- </center>
- </netui:body>
- </netui:html>
清单2 web\templateExamples.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-databinding-1.0"
- prefix="netui-data"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-html-1.0"
- prefix="netui"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-template-1.0"
- prefix="netui-template"%>
- <!-- 声明本内容页使用/template/pub-template.jsp作为模版文件 -->
- <netui-template:template templatePage="/template/vivianj-template.jsp">
-
- <!-- 为名为right的占位符提供动态内容 -->
- <netui-template:section name="right">
- <table width="570" height="1" border="0" align="center"
- cellpadding="0" cellspacing="0" id="talbe0001" bgcolor="#FDE7FA">
- <tr>
- <td> </td>
- </tr>
- <tr>
- <td class="title" align="center">所有用户留言</td>
- </tr>
- <tr>
- <td><br> 1、考虑到法律、道德和其他方面的各种因素,本网站的
- 留言本中所有留言都需经过审核后才会被显示,敬请谅解!<br>
- 2、我们将以最快的速度为所有留言提供回复,争取不超过24小时。
- </td>
- </tr>
- </table>
- <table width="570" height="1" border="0" align="center" cellpadding="0"
- cellspacing="0" id="talbe0001" bgcolor="#FDE7FA">
- <tr>
- <td height="1" background="image/0004.gif"></td>
- </tr>
- </table>
-
- <TABLE cellSpacing=0 cellPadding=0 width=570 align=center border=0
- bgcolor="#FDE7FA">
- <TBODY>
- <TR>
- <TD width=10> </TD>
- <TD height=30><table width="100%" border="0" cellspacing="0"
- cellpadding="0">
- <tr>
- <td width="584">
- 帅哥
- :
- powerise
- 发表于:
- 2006-1-12 10:48:40
- </td>
- <td width="166"><A href="mailto:xj@jandar.com.cn"><IMG
- src="image/email.gif" alt=给powerise发邮件 width="16"
- height="16" border=0></A> <A
- href="http://www.vivianj.org" target=_blank><IMG
- src="image/home.gif" alt=访问powerise的主页 width="16"
- height="16" border=0></A> <A
- href="http://search.tencent.com/cgi-bin/friend/user_show_infoln=6810017"
- target=_blank><IMG
- src="image/oicq.gif" alt=给powerise发信息 width=16 height=16
- border=0></A> <IMG
- src="image/ip.gif" alt=IP:127.0.0.1 width=16 height=15
- border=0></td>
- </tr>
- </table></TD>
- <TD width=10> </TD>
- </TR>
- <TR>
- <TD width=10> </TD>
- <TD><TABLE cellSpacing=0 cellPadding=0 width=100% align=center
- border=0>
- <TBODY>
- <TR>
- <TD width=100 align="center" valign="top">
- <TABLE cellSpacing=0 cellPadding=0 width=100 align=center border=0>
- <TBODY>
- <TR>
- <TD vAlign=middle align=center height=130>
- <IMG src="image/pic1.gif" width=85
- height=90 class=mytext></TD>
- <TD align=middle width=10> </TD>
- </TR>
- </TBODY>
- </TABLE></TD>
- <TD vAlign=top>
- <table width="100%" border="0" align="center"
- cellpadding="0" cellspacing="0" style="word-break:break-all">
- <tr>
- <td width="80" class="rptext">
- <font color="#FF6600"><b>主 题:</b></font> </td>
- <td class="rptext">唯J族留言本通过测试,正式上线!</td>
- </tr>
- <tr>
- <td class="rptext"><font color="#FF6600">
- <b>留言内容:</b></font></td>
- <td class="rptext"> </td>
- </tr>
- <tr>
- <td class="rptext"> </td>
- <td class="rptext">经过紧张的测试,唯J族留言本随着网站的更新正式上线,欢迎朋友们给唯J族留言!</td>
- </tr>
- <tr>
- <td class="rptext"><font color="#006600">
- <b>站长回复:</b></font></td>
- <td class="rptext"> </td>
- </tr>
- <tr>
- <td class="rptext"> </td>
- <td class="rptext">暂时没有回复</td>
- </tr>
- </table></TD>
- </TR>
- </TBODY>
- </TABLE></TD>
- <TD width=10> </TD>
- </TR>
- <TR>
- <TD width=10 height=5></TD>
- <TD height=5></TD>
- <TD width=10 height=5></TD>
- </TR>
- </TBODY>
- </TABLE>
- <table width="570" height="1" border="0" align="center" cellpadding="0"
- cellspacing="0" id="talbe0001">
- <tr>
- <td height="1" background="image/0004.gif"></td>
- </tr>
- </table>
-
- <table width="570" height="25" border="0" cellpadding="0" cellspacing="0"
- bgcolor="#FDE7FA">
- <tr>
- <td align="center"><form name="form1" method="post"
- action="usernotes.asp" style="margin-bottom:0;margin-top:0">
-
- <font color="#b9b9b9" style="font-size: 9pt">首页 上一页</font>
-
- <font color="#b9b9b9" style=" font-size: 9pt">下一页 尾页</font>
-
- 共<b>1</b>条BLOG <b>6</b>条BLOG/页
- 转到:<input class="p5" type="text" name="page" size="2" maxlength="10" value="1">
- <input class="p5" type="hidden" name="userid" value="">
- <input type="submit" value="Go" name="cndok"></form>
- </td>
- </tr>
- </table>
-
- <table width="570" height="1" border="0" align="center" cellpadding="0"
- cellspacing="0" id="talbe0001">
- <tr>
- <td height="1" background="image/0004.gif"></td>
- </tr>
- </table>
- <table width="570" height="1" border="0" align="center" cellpadding="0"
- cellspacing="0" id="talbe0001">
- <tr>
- <td> </td>
- </tr>
- </table>
- </netui-template:section>
- </netui-template:template>
上面图片中header.jsp文件的全部内容见清单3,footer.jsp、navi.jsp文件的全部内容见清单4和清单5。
清单3 web\pub\header.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-databinding-1.0"
- prefix="netui-data"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-html-1.0"
- prefix="netui"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-template-1.0"
- prefix="netui-template"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <netui-data:declareBundle
- bundlePath="org.vivianj.beehive.examples.netui.resources" name="view" />
- <netui:html>
- <head>
- <title><%-- Set the title based on the title attribute --%>
- <netui-template:attribute name="title" /> - ${bundle.view.hellostring} </title>
- <link rel="stylesheet"
- href="${pageContext.request.contextPath}/css/default.css"
- type="text/css" />
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- </head>
- <netui:body>
- <center>
- <table width="767" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#FDE7FA">
- <tr>
- <td width="237" height="80" align="center"><img src="images/mylogo.gif" width="207" height="52"></td>
- <td width="530" align="center" valign="middle"></td>
- </tr>
- </table>
- <table width="767" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#FDE7FA">
- <tr>
- <td width="95" height="4" bgcolor="#E70000"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="#00CD00"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="15C0F9"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="FF9A08"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="CCFF33"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="F89DDB"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="B0BAFF"></td>
- <td width="1" rowspan="4"><img src="images/sep.gif" width="1" height="100"></td>
- <td width="95" bgcolor="F9E85D"></td>
- </tr>
- <tr>
- <td colspan="15" height="4"></td>
- </tr>
- <tr bgcolor="#FDE7FA">
- <td height="14" align="right">| <a href="/default.asp">首页</a> </td>
- <td align="right">| <a href="/articles/allarticles.asp">技术文章</a> </td>
- <td align="right">| <a href="/opensource/allopensources.asp">开源项目</a> </td>
- <td align="right">| <a href="/techsubject/subjects.asp">技术专题</a> </td>
- <td align="right">| <a href="/kodo_cn/index.html">中文Kodo</a> </td>
- <td align="right">| <a href="/vivianj/members.asp">组织成员</a> </td>
- <td align="right">| <a href="/blog/blogs.asp">BLOG</a> </td>
- <td align="right">| <a href="/usernote/usernotes.asp">留言</a> </td>
- </tr>
- <tr bgcolor="#FDE7FA">
- <td height="82" align="center" valign="middle"><img src="images/home.gif"></td>
- <td align="center" valign="middle"><img src="images/articles.gif" width="53" height="62"></td>
- <td align="center" valign="middle"><img src="images/opensources.gif" width="55" height="63"></td>
- <td align="center" valign="middle"><img src="images/tech.gif" width="59" height="63"></td>
- <td align="center" valign="middle"><img src="images/license.gif" width="62" height="61"></td>
- <td align="center" valign="middle"><img src="images/members.gif" width="68" height="56"></td>
- <td align="center" valign="middle"><img src="images/blogs.gif" width="62" height="63"></td>
- <td align="center" valign="middle"><img src="images/note.gif" width="60" height="60"></td>
- </tr>
- </table>
- <table width="767" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#FDE7FA">
- <tr bgcolor="#F9C9F3">
- <td height="22" align="left" bgcolor="#F9C9F3"> 当前位置: 留言本</td>
- <td align="right"><script language=JavaScript>
- var enable=0; today=new Date();
- var day; var date;
- var time_start = new Date();
- var clock_start = time_start.getTime();
- if(today.getDay()==0)day="星期日"
- if(today.getDay()==1)day="星期一"
- if(today.getDay()==2)day="星期二"
- if(today.getDay()==3)day="星期三"
- if(today.getDay()==4)day="星期四"
- if(today.getDay()==5)day="星期五"
- if(today.getDay()==6)day="星期六"
- yr = today.getYear();
- month=today.getMonth()+1;
- date=today.getDate();
- if (yr < 1000)
- yr+=1900;
- now="今天是:" + yr+"年"+month+"月"+date+"日"+" "+day;
- document.write(now);
- </script> </td>
- </tr>
- </table>
- </center>
- </netui:body>
- </netui:html>
清单4 web\pub\footer.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-databinding-1.0"
- prefix="netui-data"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-html-1.0"
- prefix="netui"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-template-1.0"
- prefix="netui-template"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <netui-data:declareBundle
- bundlePath="org.vivianj.beehive.examples.netui.resources" name="view" />
- <netui:html>
- <head>
- <title><%-- Set the title based on the title attribute --%>
- <netui-template:attribute name="title" /> - ${bundle.view.hellostring} </title>
- <link rel="stylesheet"
- href="${pageContext.request.contextPath}/css/default.css"
- type="text/css" />
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- </head>
- <netui:body>
- <center>
- <table width="767" border="0" align="center" cellpadding="0" cellspacing="0">
- <tr>
- <td align="center" bgcolor="#F9C9F3" height="4"></td>
- </tr>
- <tr>
- <td align="center" bgcolor="#FD4AE1" height="1"></td>
- </tr>
- <tr>
- <td align="center" bgcolor="#EEEEEE" height="1"></td>
- </tr>
- <tr>
- <td align="center" bgcolor="#FDE7FA"><a href="/default.asp">主页</a> | <a href="/superadmin/admin.asp">登录</a> | <a href="/vivianj/aboutvivianj.asp">关于唯J族</a> | <a href="/vivianj/joinvivianj.asp">加入唯J族</a> | <a href="mailto:king@vivianj.org">联系唯J族</a></td>
- </tr>
- <tr>
- <td align="center" bgcolor="#FDE7FA"> © 2001-2020 唯J族 All rights reserved </td>
- </tr>
- <tr>
- <td align="center" bgcolor="#FDE7FA"><a href="http://www.miibeian.gov.cn">备案序号:浙ICP备05072825号 </a></td>
- </tr>
- </table>
- </center>
- </netui:body>
- </netui:html>
清单5 web\pub\navi.jsp
- <%@ page language="java" contentType="text/html;charset=gb2312"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-databinding-1.0"
- prefix="netui-data"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-html-1.0"
- prefix="netui"%>
- <%@ taglib uri="http://beehive.apache.org/netui/tags-template-1.0"
- prefix="netui-template"%>
- <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
- <netui-data:declareBundle
- bundlePath="org.vivianj.beehive.examples.netui.resources" name="view" />
- <netui:html>
- <head>
- <title><%-- Set the title based on the title attribute --%>
- <netui-template:attribute name="title" /> - ${bundle.view.hellostring} </title>
- <link rel="stylesheet"
- href="${pageContext.request.contextPath}/css/default.css"
- type="text/css" />
- <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
- </head>
- <netui:body>
- <center>
- <table width="191" border="0" cellspacing="0" cellpadding="0">
- <tr>
- <td height="8"></td>
- </tr>
- <tr>
- <td width="191" height="22" background="images/lefttitle.gif"> 留言本 </td>
- </tr>
- <tr>
- <td height="22" bgcolor="#F8C4F2"><span class="style2"> <a href="usernotes.asp">查看所有留言</a></span></td>
- </tr>
- <tr>
- <td height="22" bgcolor="#F8C4F2"><span class="style2"> <a href="addload.asp">我来说两句</a></span></td>
- </tr>
- </table>
- </center>
- </netui:body>
- </netui:html>
如果在某个内容页中,我们需要覆盖footer.jsp的内容,我们可以在netui-template:template标签下面增加一个netui-template:section为footer占位符提供其他内容,完成这个工作的源代码如下。
- <!-- 声明本内容页使用/template/pub-template.jsp作为模版文件 -->
- <netui-template:template templatePage=“/template/pub-template.jsp”>
-
- <!-- 为其他占位符提供动态内容 -->
-
- <!-- 为名为footer的占位符提供动态内容 -->
- <netui-template:section name=“footer”>
- <!-- 此处增加要显示的动态内容的html代码,
- 也可以是其他NETUI标签显示的动态内容 -->
- </netui-template:section>
- </netui-template:template>
| 作者简介 |
 肖菁 |
肖菁 是唯J族(www.vivianj.org)创始人,BEA 杭州User Group负责人,自由撰稿人,开源项目BuildFileDesigner(buildfiledesign.sourceforge.net)和V-Security(v-security.sourceforge.net)创始人。 |
作者其它文章
|