在大多数项目中,很多web开发人员能做的就是利用IDE自动为我们生成配置文件,但真正当我们自己想动手写个项目时,发现很多模块我们似懂非懂,无法入手。当然要学会这些项目中的每个模块以及如何集成它们,这还是需要平时的点滴的积累。
经常我们利用基于eclipse开发IDE来创建我们的页面,但实质上它在后台自动帮我们生成多很多配置文件,如spring,bb,tiles。
现在介绍的就如何复用我们的模版tiles.
它的方式很多种,多到每个语言都有各自的配置方式,但是万变不离其中,那就是复用一些常用的模版。
一.最原始的就是jsp:include方式:
<TABLE border="0"> <TBODY> <TR> <TD colspan="2"> <jsp:include page="/header.jsp" /> </TD> </TR> <TR> <TD colspan="2"> <jsp:include page="/body.jsp" /> </TD> </TR> <TR> <TD colspan="2"> <jsp:include page="/footer.jsp" /> </TD> </TR> </TBODY> </TABLE>
这是个简单的利用标签来复用
二.利用struts-tiles.tld
<TABLE border="0"> <TBODY> <TR> <TD colspan="2"> <tiles:insert page="/header.jsp" flush="true" /> </TD> </TR> <TR> <TD colspan="2"> <tiles:insert page="/body.jsp" flush="true" /> </TD> </TR> <TR> <TD colspan="2"> <tiles:insert page="/footer.jsp" flush="true" /> </TD> </TR> </TBODY> </TABLE>
这个标签是在基于 struts上的tld,所以你必须加入如下两个文件
1.struts-tiles.tld
2.struts.jar 包
3.struts-tiles.tld与JSF的集成
这种方式是比较常用的,它可以把相关页面利用tiles.xml集成起来,甚至利用模版和常用文件,你都可以不用新建你的JSP文件。下面就来感受一下它的妙处吧:
3.1首先是快速搞个jsf+spring+hibernate的工程(没有的可以参照这里
http://lygle.iteye.com/admin/blogs/616800),然后建立三个JSP文件
head.jsp
body.jsp
footer.jsp
再建立个模版文件
layout.jsp
<f:view> <table width="778" border="1" align="center" cellpadding="0" cellspacing="0"> <tr> <td> <f:subview id="header"> <t:insert attribute="header" flush="false"></t:insert> </f:subview> </td> </tr> <tr> <td> <f:subview id="body"> <t:insert attribute="body" flush="false"></t:insert> </f:subview> </td> </tr> <tr> <td> <f:subview id="footer"> <t:insert attribute="footer" flush="false"></t:insert> </f:subview> </td> </tr> </table> </f:view>
使它包含着上面的三个文件
3.2修改JSF配置文件
在配置文件加个导航规则
<navigation-case> <from-action>#{UserLoginBB.userLogin}</from-action> <from-outcome>ok</from-outcome> <to-view-id>/homePage.jsf</to-view-id> </navigation-case>
这个规则假设是我们登录的动作,如果成功返回ok,然后跳转到"homePage.jsf"
注意这里的homePage.jsf事实上不存在的,它是利用tiles动态配置出来的一个页面。怎么配呢,继续往下看吧。
3.3配置web.xml跟tiles.xml
确保web.xml里有引用到我们的tiles.xml
如:
<context-param> <param-name>tiles-definitions</param-name> <param-value>/WEB-INF/tiles.xml</param-value> </context-param>
关键的tiles.xml
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration//EN" "http://jakarta.apache.org/struts/dtds/tiles-config.dtd"> <tiles-definitions> <definition name="layout" path="/layout.jsp"> <put name="header" value="/header.jsp" /> <put name="body" value="/body.jsp" /> <put name="footer" value="/footer.jsp" /> </definition> <definition name="layout2" path="/layout.jsp"> <put name="footer" value="/header.jsp" /> <put name="body" value="/body.jsp" /> <put name="header" value="/footer.jsp" /> </definition> <definition name="layout3" path="/layout.jsp"> <put name="header" value="/header.jsp" /> <put name="body" value="/body.jsp" /> <put name="footer" value="/footer.jsp" /> </definition> <definition name="/homePage.tiles" extends="layout3"> </definition> </tiles-definitions>
这个配置文件里,我配置一个name为homePage",并且它的模版继承自layout3
那么请问,当你跳转到"/homePage.jsf",这个不存在的文件,它怎么跟tiles.xml关系上呢。当你有这个疑问时,说明你可以继续往下看了。
3.4.配置ViewHandle
在faces-config.xml里配置一个请求监听,当我们请求/homePage.jsf,它能够监听到并把它转到
/homePage.tiles从而调用layout3模版里的页面。
这个过程我们就引用apache里的一个文件,稍作修改,最重要的就是renderView接收请求,并把请求转为
/homePage.tiles这个过程
有兴趣的话,可以下来调试看下.
部分代码如下:
if (servletMapping.isExtensionMapping()) { if (!viewId.endsWith(suffix)) { int dot = viewId.lastIndexOf('.'); if (dot == -1) { //if (log.isTraceEnabled()) log.trace("Current viewId has no extension, appending default suffix " + suffix); viewId = viewId + suffix; } else { //if (log.isTraceEnabled()) log.trace("Replacing extension of current viewId by suffix " + suffix); viewId = viewId.substring(0, dot) + suffix; } facesContext.getViewRoot().setViewId(viewId); } } else if (!viewId.endsWith(suffix)) { // path-mapping used, but suffix is no default-suffix dispatch(externalContext, viewToRender, viewId); return; } String tilesId = viewId; int idx = tilesId.lastIndexOf('.'); if (idx > 0) { tilesId = tilesId.substring(0, idx) + tilesExtension; } else { tilesId = tilesId + tilesExtension; } ServletRequest request = (ServletRequest)externalContext.getRequest(); ServletContext servletContext = (ServletContext)externalContext.getContext(); ComponentDefinition definition = null; try { definition = getDefinitionsFactory().getDefinition(tilesId, request, servletContext); if (definition == null) { /** * Check for the definition without the leading '/' character. Allows user to specify Tiles definitions without a * leading '/' char. */ int slashIndex = tilesId.indexOf("/"); if (slashIndex == 0) { tilesId = tilesId.substring(1); definition = getDefinitionsFactory().getDefinition(tilesId, request, servletContext); } }