`
ahuaxuan
  • 浏览: 633349 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

强强连手, 在模板中分页,看Freemarker和displaytag的结合

阅读更多
/**
*作者:张荣华(ahuaxuan)
*2007-07-09
*转载请注明出处及作者
*/

[size=11]强强连手, 看Freemarker和displaytag的结合

这个周末搬家,从金桥搬到了上南这边,然后又去买洗衣机空调之类,两天下来,把人整得叫一个累,还不如舒舒服服的坐在椅子上写代码呢。一切搞定之后脑海中有想起了现在手头上的做的事,如何尽可能的简化框架,目的只有一个,减少使代码量。

我比较推崇在view层使用模板技术,但是如果使用模板的话分页如果没有较好的封装将会给程序员带来很多bad small的代码,但是现在由于人力和物力的关系又没有时间去开发一个比较完善方便的分页的marco,所以想到把现有的比较完善的分页组件引入到freemarker中去,由于displaytag之前曾经用过,所以就选择了它,google了一下,发现网上没有类似的介绍,大家不写那就我来写吧。

首先简要介绍一下这两个技术吧:
Displaytag是一个很好的分页标签,它支持数据库端分页(在displaytag1.1的版本中也实现了数据库端分页,只要实现PaginatedList接口,然后把这个对象扔到页面上的display:table标签中就能实现数据库端分页。这里所说的数据库端分页就是displaytag文档中提到的partial list),排序,也支持导出各种文件,比如说pdf,excel等等,而且它还支持程序员使用decorator模式来包装和更改要输出的model的属性,等等。

而freemarker是一个很好的模板引擎,它被设计的目的就是被用在view层,通过模板来生成html页面,在动态页面中使用模板技术的目的就是分离页面设计者和程序员的职责,而且模板的速度更快,尤其是无需编译这种特性,模板的优缺点及freemarker和velocity的比较见http://www.iteye.com/topic/71430。(题外话:有人可能不同意我的观点,但我仍然相信术业有专攻,每个人都有自己强的一方面,以前在看robbin的一个就业ppt中,感觉有一句话说得特别好,什么叫成功:成功不是弥补自己的不足,而是把自己的优点发挥到及至,这样就能够成功。)

这两个都是口碑很好的开源项目,让我觉得放弃他们中的任何一个都是非常可惜的,在使用模板语言的时候,如果不用displaytag(或者其他分页的tag),那么必须得自己写marco来实现分页的功能,其实就是用freemarker或者velocity模板语言把分页的功能又写了一遍,可以也是可以的,只是要花一些人力物力,说白了就是实现同样的功能却要花更多的钱和时间,在做外包的时候这样尤其不可取了(当然个人学习研究就另当别论了),那么在企业应用开发中如果把两者结合起来应该是一个不错的选择,这样既拥有了模板语言的优势又能只用几行代码就搞定分页排序等功能,两全其美,一举两得,快哉。

那么让我们来看一下步骤:
1, 在web.xml导入FreemarkerServlet的配置
<servlet>
  <servlet-name>freemarker</servlet-name>
  <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
    
  <!-- FreemarkerServlet settings: -->
  <init-param>
    <param-name>TemplatePath</param-name>
    <param-value>/</param-value>
  </init-param>
  <init-param>
    <param-name>NoCache</param-name>
    <param-value>true</param-value>
  </init-param>
  <init-param>
    <param-name>ContentType</param-name>
    <param-value>text/html</param-value>
  </init-param>
    
  <!-- FreeMarker settings: -->
  <init-param>
    <param-name>template_update_delay</param-name>
    <param-value>0</param-value> <!-- 0 is for development only! Use higher value otherwise. -->
  </init-param>
  <init-param>
    <param-name>default_encoding</param-name>
    <param-value>UTF-8</param-value>
  </init-param>
  <init-param>
    <param-name>number_format</param-name>
    <param-value>0.##########</param-value>
  </init-param>

  <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
		<servlet-name>JspSupportServlet</servlet-name>
		<servlet-class>
			org.apache.struts2.views.JspSupportServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

<servlet-mapping>
  <servlet-name>freemarker</servlet-name>
  <url-pattern>*.ftl</url-pattern>
</servlet-mapping>  


2,在页面模板中导入jsptag的tld声明(这一步貌似和jsp中tag的声明一样)
<#assign display=JspTaglibs["/WEB-INF/tld/display.tld"]>


3, 接下来就是使用displaytag了,前面那两步freemarker的文档上有详细的说明,大家只要在文档的索引页面上查找”tag”就能找到了,但是在第三步就要注意点问题了,也就是把PaginatedList实现的对象实例扔到模板里时要注意的事项。

(1)在<@display.table的name属性中不要再使用${},直接写PaginatedList的对象引用就可以了,比如说直接写name=”customers”而不要写成name=”${customers}”

(2)不要导入displaytag-el.tld,直接导入displaytag.tld就可以了。

(3)<@display.table>和<@display.column>中的布尔类型不能使用字符串,我们在jsp中直接使用diplaytag的使用应该是使用字符串,但是在模板中就不能这样写了,而应该使用模板语言的写法,布尔值就直接写布尔值,比如说export=true,而不能写export=”true”,这样肯定会抛参数不匹配的异常。

(4)注意在<@display.column中使用html语句的使用记得把escapXml属性设置为false,否则displaytag会对其进行转义,freemarker貌似不会默认给其进行转义,除非使用freemarker的转义命令(velocity的html转义是要通过配置velocity.properties来实现,而且它直接调用了apache common包中的转义操作,这样会默认对2字节以上的字符串都进行转义,于是中文都变成了符号,浏览器能解析而人却不能直接阅读,而spring中的转义方法就没有这个问题)。
下面是一个例子:
<@display.table name="products" style="width:70%;" id="product" cellspacing="0" class="table"
	   			 export=false  cellpadding="0" requestURI="">
		    <@display.column title="${xtt}" escapeXml=false class="columnClass" sortable=true headerClass="headerClass">
				<input type="checkbox" name="entityIds" id="entityIds" value="${product.id}"/>
		    </@display.column>
		    <@display.column property="id" escapeXml=true sortable=true title="产品序号" paramId="entityIds" paramProperty="id"
		    						url="/product/prepareUpdateProduct.action"/>
		    <@display.column property="serialNumber" escapeXml=true sortable=true title="商品编号"/>
		    <@display.column property="name" escapeXml=true sortable=true  title="商品名称"/>
		        <@display.setProperty name="paging.banner.item_name" value="商品"/>
	   			   </@display.table>


依照上面这些步骤,我相信感兴趣的同学很快就能在freemarker中使用displaytag了,虽然我在freemarker中使用了displaytag,但是这并不意味着我支持在freemarker任意使用jsptag的观点,比如一些freemarker本身就带有的功能,判断,循环,日期格式化等等这些根本不需要导入tag,而且我也反对在页面中使用其他input的tag,虽然这样能够带来客户端验证的优点,但是事实上基于js验证的客户端框架现在也不少,没有必要为了这个理由把页面上弄得到处都是@ww,而且使用theme之后,页面布局更不容易控制,而且最重要的是这样使页面设计者更难介入了(这一观点是基于很多外包公司都有专门的页面团队,他们是专业的页面制作人员,当如果公司里没有这样一支团队,那么上面这个结论就不成立了)。

我知道不同的公司肯定都有自己做法,希望大家能多多发言,多多拍砖。


作者:张荣华,未经作者同意不得随意转载![/size]

分享到:
评论
6 楼 小卡kare 2013-05-07  
华哥威武霸气,时隔6年的6楼。。为我准备的
5 楼 ahuaxuan 2007-07-20  
Tin 写道
呵呵,displaytag可不是分页的工具,他是个table组件。
有了extremeComponent的extremeTable为什么还要displaytag呢?

2年前似乎还有人讨论displaytag由于使用遍历List的方式分页造成的性能影响,现在不知道怎么样了。反正ec老早就可以自定义查询分页了。

去看看fins的ecside那个项目如何?

神威如狱 写道
displaytag要是能数据库分页就好多了

displaytag从1.1版本也可以了啊(06年2月份),而且很简单就能实现

ahuaxuan 写道
在displaytag1.1的版本中也实现了数据库端分页,只要实现PaginatedList接口,然后把这个对象扔到页面上的display:table标签中就能实现数据库端分页。这里所说的数据库端分页就是displaytag文档中提到的partial list


当然不管是哪个组件,我想表达的其实是在模板中使用这个组件,不管是displaytag,extremeTable,或者是ec,应该都能整合到freemarker中,这样可以避免重新写很多marco等。



4 楼 Tin 2007-07-20  
呵呵,displaytag可不是分页的工具,他是个table组件。
有了extremeComponent的extremeTable为什么还要displaytag呢?

2年前似乎还有人讨论displaytag由于使用遍历List的方式分页造成的性能影响,现在不知道怎么样了。反正ec老早就可以自定义查询分页了。

去看看fins的ecside那个项目如何?
3 楼 神威如狱 2007-07-20  
displaytag要是能数据库分页就好多了
2 楼 xfli333 2007-07-19  
valuelist
1 楼 kajijiyani 2007-07-19  
display缺点太多
初看让人欣喜,仔细研究功能太过不完善!

相关推荐

Global site tag (gtag.js) - Google Analytics