论坛首页 Java企业应用论坛

Tapestry 和 JSP/Taglib 的比较

浏览 29378 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-04-11  
Robbin的Tapestry帖子讨论很热烈, 我这边也开一个关于Tapestry 和 JSP/taglib比较的帖子, 谈一下我使用Tapestry的一点感受:

举一个常见的user 管理界面, 列出几个用户, 然后在用户旁边是delete和update的按钮, 先列出一个静态的html代码:
<table>
    <tr>
        <td>User Name</td>
        <td>Action</td>
    </tr>
    <tr>
        <td>Quake Wang</td>
        <td><a href="#">Delete</a> <a href="#">Update</a></td>
    </tr> 
</table>


如果是基于jsp, 那么可能的最后代码是这个样子:
<table>
    <tr>
        <td>User Name</td>
        <td>Action</td>
    </tr>
    <%while(users.hasNext(););{
      User user = (User); users.next();;%>
    <tr>
        <td><%=user.getName();%></td>
        <td><a href="deleteUser?id=<%=user.getId();%>">Delete</a> <a href="updateUser?id=<%=user.getId();%>">Update</a></td>
    </tr>
    <%}%>
</table>


如果是基于taglib, 和jsp差不多, 只是把hasNext(), next() 用foreach的标签替换掉, 把<%=%>, 用out标签替换掉.

<table> 
    <tr> 
        <td>User Name</td> 
        <td>Action</td> 
    </tr> 
    <c:forEach var="user" items="${users}">
    <tr> 
        <td><c:out value="${user.name}"/></td> 
        <td><a href="deleteUser?id=<c:out value="${user.id}"/>">Delete</a> <a href="updateUser?id=<c:out value="${user.id}"/>">Update</a></td> 
    </tr> 
    </c:forEach>
</table> 


先不谈页面代码的支离破碎对于后期维护照成的困难, 觉得最麻烦的是需要用id传来传去, jsp, servlet上的传递参数到处都是, 破坏了原本优雅的OO代码.

我们来看看Tapestry是怎么处理的:
<table>
    <tr>
        <td>User Name</td>
        <td>Action</td>
    </tr>
    <tr jwcid="@Foreach" source="ognl:users" element="tr" value="ognl:user">
        <td><span jwcid="@Insert" value="ognl:user.name">Quake Wang</span></td>
        <td><a href="#" jwcid="@ActionLink" listener="ognl:listeners.deleteUser">Delete</a> <a href="#" jwcid="@ActionLink" listener="ognl:listeners.updateUser">Update</a></td>
    </tr>
</table>


我们可以看到Tapestry不引入额外的语法, 它利用html的标签属性, 只要有jwcid(java web component id)属性和component需要的数据来源, 就能渲染出最终的html, 上面写好的模板可以直接在浏览器里面打开, 效果和最初的html代码是一样的, 这样就给后期维护页面带来了极大的方便.

在开发过程中, Tapestry带来最大的便利就是数据绑定, 我们看deleteUser的代码:
public void deleteUser(IRequestCycle cycle); {
  getUserService();.deleteUser(getUser(););;
}


getUserService() 和 getUser()都是abstract method, tapestry会自动帮你做运行期增强, 我在实际开发中采用的是spring做service factory, 那么给userService一个初始值, 让它从service locator里面获取: <property-specification name="userService" type="com.abc.ent.service.UserService" initial-value="global.serviceManager.userService"/> getUserService() 这个方法就会获得这个userService, 而getUser()则是Tapestry会自动获得绑定的user.

可以看到同jsp相比, 用Tapestry实现的代码非常的简单. 我最近在学习Tapestry的架构, 被它的先进的想法所深深吸引, 如果论坛上有谁对此有研究, 请多多交流.
   发表时间:2004-04-12  
提个建议,这个话题看看能不能扩展。大家就自己知道的表现层框架,给出同样这个问题的不同答案。好好的比较一下。
0 请登录后投票
   发表时间:2004-04-12  
在开发的过程中, Tapestry给我带来的最大方便就是可以换个角度写代码, 可以完全抛弃在原来page by page的MVC架构中需要使用id传来传去这种无趣的做法,every thing is Object, 至于页面上的整洁和易维护性只是它的天然优势之一。

它的缺点:文档太少,不看原代码的话, 只有它的example可以抄,但是我们知道example做demo还可以, 但是运用到真正的项目中, 就得考虑最佳实践 (best practice)了, 很多时候都得深入到代码, 才能发现, 哦,原来有这么方便的写法。 这点估计等到用的人多了,才会有所改善吧。
0 请登录后投票
   发表时间:2004-04-13  
Quake Wang 写道
在开发的过程中, Tapestry给我带来的最大方便就是可以换个角度写代码, 可以完全抛弃在原来page by page的MVC架构中需要使用id传来传去这种无趣的做法,every thing is Object, 至于页面上的整洁和易维护性只是它的天然优势之一。

它的缺点:文档太少,不看原代码的话, 只有它的example可以抄,但是我们知道example做demo还可以, 但是运用到真正的项目中, 就得考虑最佳实践 (best practice)了, 很多时候都得深入到代码, 才能发现, 哦,原来有这么方便的写法。 这点估计等到用的人多了,才会有所改善吧。

有同感,现在都熟悉Howard M. Lewis Ship的代码风格了
0 请登录后投票
   发表时间:2004-04-13  
确实资料文档比较少,
而且spindle这个插件做的不怎么好,没有做到拖拉组件的功能。
0 请登录后投票
   发表时间:2004-04-14  
从你的例子举的不好,不是taglib的用法.
最近用tapstrey的项目接近收尾了.自己的感觉是:它不是什么银弹,分离不了页面和程序.
1,就如你举的例子,做页面的mm是不会自己加jwcid="@Foreach",也不会自己加taglib.对于程序人员来讲,加jwcid和使用taglib是一样的工作量.
2,增加隐藏变量的问题,tapstrey同样的也有.我是没有避免,不知道你怎么做的.不使用的话,自动使用缺省值.
3,到处都是参数的问题,实际上是页面form参数和oo(tapstrey),formbean(struts)自动映射的问题.
4,数据绑定,tapstrey的oo,就如struts的formbean一样.
5,工具支持,没有一个好的ide,tapstrey难用的很,java,page,html之间有大量的对应关系.就和hibernate的配置文件一样,如果不能自动完成同步,在一个稍微大点的项目中就会带来巨大的工作量.
6,组件,在我看来tapstrey最大的好处就是组件库,这些组件大大简化了编程.但问题是组件的灵活性和数量.这和taglib也一样.

在我看来,tapstrey要想兴旺发达,1,一个快速的ide,2,丰富的组件库.
我的下一个项目估计是不会用tapstrey了.还是用struts,但struts最烦的是formbean的紧密结合,另,实际上dw早就有支持taglib的插件了,只不过因为页面mm从来不用.
但真正分离页面和程序,恐怕还有很远的路要走,但不会是现在的tapstrey.
0 请登录后投票
   发表时间:2004-04-14  
youcai 写道
实际上dw早就有支持taglib的插件了,只不过因为页面mm从


推荐一下好吗?
0 请登录后投票
   发表时间:2004-04-14  
ultradev4 plug in ?这个?
0 请登录后投票
   发表时间:2004-04-14  
youcai 写道

从你的例子举的不好,不是taglib的用法.

我把最初的帖子修改了一下, 加上了taglib的写法, 不知道你说的不是taglib的写法是什么意思?

youcai 写道

1,就如你举的例子,做页面的mm是不会自己加jwcid="@Foreach",也不会自己加taglib.对于程序人员来讲,加jwcid和使用taglib是一样的工作量.
2,增加隐藏变量的问题,tapstrey同样的也有.我是没有避免,不知道你怎么做的.不使用的话,自动使用缺省值.
3,到处都是参数的问题,实际上是页面form参数和oo(tapstrey),formbean(struts)自动映射的问题.
4,数据绑定,tapstrey的oo,就如struts的formbean一样.

关于Tapestry能否带来页面和代码的分离, 以及能否提供页面设计人员和维护人员的工作效率, 论坛里面已经讨论很多了, 我不想把这个帖子又转到这方面上. 我们来讨论一下对于程序开发以及维护人员的帮助:

你看一下我最上面的例子, Tapestry没有用id来传递, 而是把users这个source用Foreach组件生成的user对象绑定到ActionLink这个组件上, 当它被点击的时候, 触发listener, listener方法只用getUser(), 就可以获得绑定的user, 从而进行对应的操作.

从这个单个的传递id的例子, 我们可能还看不出来Object binding的威力. 再举一个常见的例子, 比如用户管理模块里面, 我们需要把某个user加入到一个group里面, 基于jsp, taglib的做法是需要传递userId和groupId (可能是通过link里面的parameter或者是hidden value), 而用户在这个页面上操作的时候, 必然已经是看到了group和user这些对象了,我们只用绑定这些对象到组件, 后台程序只用一句调用逻辑Service的代码就可以了:
public void addUserToGroup(IRequestCycle cycle); { 
    getUserService();.addUserToGroup(getUser();, getGroup(););;
}


getUserService() 通过page定义得初始值, 从Global Service Locator获取UserService的implement.
getUser()和getGroup() 通过Tapestry自动的类增强功能获取绑定在这个促发这个lisenter组件上的user和group对象.

这样不是很简洁吗? 至少目前我的项目中是没有出现传递id参数的代码. 如果你的项目当中有那么多的传递参数的话, 是没有好好用到Tapestry的数据绑定的特性吧? 我一开始接触Tapestry的时候, 也是用原有基于jsp/taglib那种page by page的思想在看, 学会Object Binding以后觉得Tapestry在这点上帮我少写了好多dirty code, .

youcai 写道

5,工具支持,没有一个好的ide,tapstrey难用的很,java,page,html之间有大量的对应关系.就和hibernate的配置文件一样,如果不能自动完成同步,在一个稍微大点的项目中就会带来巨大的工作量.
6,组件,在我看来tapstrey最大的好处就是组件库,这些组件大大简化了编程.但问题是组件的灵活性和数量.这和taglib也一样.

你有没有试过Spindle? 非常好用的Tapestry eclipse plugin. 写了一些UI组件和业务组件, 觉得Tapestry的组件比taglib要灵活, 主要是有它的Object Binding特性做支持, 组件重用性会很高.
0 请登录后投票
   发表时间:2004-04-14  
感觉TAPESTRY最大的优点就是组件化和OO,至于让美工MM改代码。。。从来没想过,现在公司里有N多程序员却只有一个美工。
以前做过一个XML+XSL的项目,美工在花费一定时间学习掌握XSL后,我们得到反馈非常好,尤其是做几个不同风格的页面不需要修改一行JAVA代码,只做XSL就OK了,这是我做过的页面与代码分离的最好的架构。可惜的是XML解析效率不高。。。我们的WEBMAIL不得不过一段时间重启一下
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics