﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-wy_71-文章分类-J2EE</title><link>http://www.blogjava.net/wy_71/category/4993.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:25:31 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:25:31 GMT</pubDate><ttl>60</ttl><item><title>文章标题 Tapestry Spring Hibernate整合工作小结(转 如果本文作者看到请留言)</title><link>http://www.blogjava.net/wy_71/articles/20405.html</link><dc:creator>wy_71</dc:creator><author>wy_71</author><pubDate>Fri, 18 Nov 2005 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/wy_71/articles/20405.html</guid><wfw:comment>http://www.blogjava.net/wy_71/comments/20405.html</wfw:comment><comments>http://www.blogjava.net/wy_71/articles/20405.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/wy_71/comments/commentRss/20405.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/wy_71/services/trackbacks/20405.html</trackback:ping><description><![CDATA[<font size="2">FrankSoo是我的项目经理。前段时间公司决定作个新的J2EE二次开发平台，以替换公司原有的开发平台。公司让FrankSoo和我组成平台开发项
目组，FrankSoo担任项目经理。现在这个平台整合开发阶段已经结束，进入项目应用阶段。下面是我们的整合工作小结，介绍一下我们在工作中遇到的问
题，以及我们选择的解决方案.<br>
<br>

1、架构的选择<br>
<br>

首先，我们都同意以我们现有的能力，没有足够的时间和资源自行开发一套完整的平台。在已有的众多开源项目中选择若干优秀的项目进行整合，才可能按时完成项目，达到项目目的。<br>

但是在平台项目开始前，我们对平台的技术架构有各自的构想。FrankSoo原来的构想是Struts+Spring+Hibernate，而我的构想是Tapestry+Hibernate。<br>

不过FrankSoo非常open，在我向他演示了Tapestry的经典范例workbench，介绍了Tapestry基于组件的编程方式之后，他同
意选用Tapestry作为实现Web展现层的框架。我想FrankSoo以前的Struts开发经验(painful)也是他做出这个决定的因素之一。
FrankSoo gave me a nice introduction of Spring Framework. Wow, what an
amazing framework! IOC, Declarative Transaction Support, Hibernate
Session Management, Hibernate DAO Support… These features are just what
we need for a middle tire container.<br>
<br>

至于Hibernate，这个最成功的开源ORM项目，我们都投了它一票^_^<br>

最后我们确定平台的技术架构是Tapestry+Spring+Hibernate.<br>
<br>

2、架构整合<br>
<br>

最初的平台架构借鉴了一篇介绍如何集成Tapestry与Spring的文章［1］中提到的架构：<br>
<br>

Web 层的Tapestry负责数据输入输出, 响应用户事件，及输入校验的工作,
通过访问预先加载的WebApplicationContext(由Spring提供, 包含着所有Service
bean)获得Service层的Service Bean, 把业务操作都委托给它们.<br>
<br>

Service层的bean则负责use case逻辑, domain相关的逻辑委托给domain model中的bean去实现.
Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate
Session的管理(通过Spring的声明式事务管理和与之集成的Hibernate Session管理).
Service层的另一项重要工作是权限和访问控制。<br>
<br>

Domain model负责表示问题域的数据和domain logic. DAO使用Hibernate持久化数据以及查询. 在实现DAO时,
我们使用了Spring的Hibernate DAO Support,极大地简化了代码, 很多方法都只用简单的一行完成. 有意思的是,
最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还多<br>
<br>

这样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开发, 结合mock和spring的IOC, unit
test也是非常容易的. 而且后台(Service, domain model and
DAO)的代码不依赖于Web容器或是EJB容器的API, 移植性非常好, 同样的代码可以在Web app中使用也可在普通的Java
app中使用, 只需更换UI层.<br>
<br>

按照这个整合的构架，我们实现一个简单的实例，实现了列表分页查询和显示，数据增删改，基于Hibernate Criteria
Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已经建好的数据库表结构自动生成Hibernate映射文
件，实体类和DAO，极大地减少了工作量。我们还对这个小例子进行了压力测试（测试时的数据量为10万条记录），确定平台不存在性能问题。<br>
<br>

通过这个实例我们把整个架构基本走通一遍，并总结了使用这套架构开发时适用的开发流程和需要做的工作。<br>
<br>

3、困扰我们的问题<br>
<br>

在实现例子和现在的项目应用过程中，我们发现了若干头疼的问题，有的解决了，有的还没有。<br>
<br>

问题1：要不要使用DTO？<br>
<br>

在上面的架构中我们并没有明确Service和Web层间的数据传输是如何进行的。我们讨论好久要不要使用DTO，最后的结论是不用。<br>
<br>

使用DTO有两个主要的理由：1、减少Web层和Service层间的方法调用，通过一个方法调用就将Web需要的数据都传给Web。2、隔离domain model和Web层。<br>
<br>

第一个理由在我们的架构下是不成立的。因为我们的架构是集中式的，Web和Service是在同一个JVM中，它们之间的方法调用是没有EJB远程访问的巨大消耗的。<br>
<br>

第二个理由还是需要考虑的。如果允许把domain model中的对象传给Web层，那么修改domain
model，就会影响到Web层。如果使用DTO，那么domain model实现上的变化就不会影响到Web。但是大量的变化不是domain
model实现上的变化，而是domain model接口的变化，比如一个domain
model的对象上添加了一个属性，而这个属性需要用户修改，那么这时候必须修改Web层，不管是不是用了DTO。而且使用DTO，就需要维护着一大堆对
象，或是它们的生成器，这是非常无聊、且容易出错的工作。<br>
<br>

基于这些考虑，我们没有使用DTO，而是选择把domain model直接传到Web层。下面是修改后的架构图（呵呵，修改了别人的图［2］）。<br>
<br>

问题2：Entity like domain model or rich domain model?<br>
<br>

我们使用Middlegen自动生成Hibernate映射文件，Entity类和DAO类,
但是生成的Entity只含有简单的属性和getter, setter方法。因此我们遇到了一个问题：我们的domain
model还要不要包含domain logic？如果包含，那么和自动生成工具如何结合？<br>
<br>

我们讨论后认为一个rich domain model还是非常有必要的，可以减少Service中的重复代码，提高复用性。<br>
<br>

如何同自动生成结合？使用&lt;meta&gt;标签，生成抽象基类，我们继承这些自动生成的基类，添加业务方法。<br>
<br>

问题3：Model driven or Data driven?<br>
<br>

采用Model driven还是Data driven的方式大家有过热烈的讨论。我们主要是受到Rod
Johnson［3］的影响，采用了Data
driven的方式。先作数据库设计，生成库表，然后用Middlegen反向生成Hibernate映射文件和Entity及DAO。但是我们在进入项
目应用之后发现这种方法有两个问题：<br>
<br>

a） 数据库设计仅说明了系统要管理的静态数据，我们还是得作面向对象分析，以反映系统的动态行为。特别是当系统的业务不仅仅是简单的CRUD操作时，这个问题更严重。<br>

b）数据库设计为了优化性能，可能会把好几个应该是单独实体的数据放入一个实体中。这样如果直接把这种极粗粒度实体映射成Entity类，那简直是不可接
受的。面向对象的分析设计模型得到的类都是相当细粒度的。这种情况还得作面向对象的分析，明确到底这个粗粒度的大表应该映射成那几个细粒度的对象。<br>
<br>

或许我们应该试试Model driven，用AndroMDA生成domain model，Hibernate DAO，Hibernate mapping，数据库表，简单的Service和前台的Tapestry页面。<br>
<br>

问题4：Hibernate Session生命周期如何管理？<br>
<br>

对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式，未采用Open Session
in View模式。 虽然Hibernate
team认为这种方法没什么不好，而且FreeRoller和Atlassian的confluence都使用了Open Session In
View这种模式，但是我们对它可能产生的影响还没有很好的把握，所以暂时弃置不用。 如果Web层要访问lazy load的数据,
需要先调用Service的业务方法, 以获得数据.<br>
<br>

问题5：Use case logic 和domain logic 如何区分？<br>
<br>

Service负责use case logic，domain model负责domain logic。这样的划分看起来很好，实现起来就很麻烦。如何确定什么是use case logic，什么是domain logic？TBD.<br>
<br>
<br>

问题6：Service粒度如何确定？<br>
<br>

这个问题真是很烦，原先考虑使用usecase controller的方式，每个usecase对应一个Service，但是发现这样复用性太低，而且好多地方必须复用相同的功能<br>
<br>

另一种方法是用package level service，每个package作个service，这样倒是可以重用，但是感觉太死了，不好。<br>
<br>

现在也没有什么很好的办法，只好在详细设计时根据具体情况确定需要多少个Service了。TBD.<br>
<br>

问题7：权限如何设定？如何检查？<br>
<br>

权限设定也是个头疼的问题。我们本想是按照use
case设定权限，每个用例一个权限。在角色设定的时候直接处理的都是业务意义非常明确的权限。但是在权限验证过程中发现了问题：如果在Service的
方法中验证权限，而且这个方法在多个用例中用到（复用Service），那么这个Service的方法就需要检查多个权限;
如果每个Service方法对应一个权限, 那么权限又太细了, 不像use case权限那样代表一个完整的业务. 真的是很麻烦阿！TBD.<br>
<br>

Quake wang:<br>
<br>

问题1：要不要使用DTO？<br>

No DTO, 直接把domain object传给Tapestry的web层，利用Tapestry提供强大的数据绑定和组件功能很方便<br>
<br>
<br>

问题2：Entity like domain model or rich domain model?<br>

domain model不包括复杂的domain logic, 只是作为一个data model bean, 再加上一些简单的logic, 比如addChild的同时，设置child的parent此类简单logic.<br>
<br>
<br>

问题3：Model driven or Data driven?<br>

这个对我来说不是什么大问题，个人习惯而已，我觉得无论是Model driven或者Data
driven，对于相同的需求，2者最终的设计应该都是很类似的。我是从2边同时考虑的，一边做Model，一边还要考虑数据库的结构，再进行相应的调
整，用下来也没有什么问题。没有用代码生成， 只是用Hibernate的Eclipse plugin (Hibernate
Synchronizer)来帮我做一些code assist.<br>
<br>
<br>

问题4：Hibernate Session生命周期如何管理？<br>

目前没有采用open session in view，也是和你们一样，在Service里面准备好所有需要的对象。<br>
<br>
<br>

问题5：Use case logic 和domain logic 如何区分？<br>

由于domain model里面没有什么domain logic，这个问题不存在.<br>
</font>
<pre><br></pre>
<font size="2"><br>

问题6：Service粒度如何确定？<br>

由于domain model里面没有什么domain logic，所以Service的功能就切得很细，尽量重用，一个package可能有多个service, 感觉还好，没有太死。<br>
<br>

问题7：权限如何设定？如何检查？<br>

这个也是我没有想好的问题， 因为不同的需求， 权限设定都不一样，很难用AOP来做一个通用的aspect.<br>
<br>

1. DAO的做法：<br>

我目前不是给每个domain object都做一个DAO, 而是整个系统就一个DAO (PersistenceManager),
里面只有create, update, delete entity这3个方法。另外写一个DAO, 专门做查询 (QueryManager),
用hibernate的named
query做常用的查询，用criteria来做基于用户输入的动态查询。不知道你们的做法是怎么样？另外criteria 和 named
query其实都是hardcode，object attribute name改变的时候，还得记得手工去修改这些代码，unit
test很难覆盖到所有的criteria search 和 named query里面的代码，这个是目前感觉不是很方便的地方。<br>
<br>

2. Spring 和 Tapestry的集成<br>

目前只是用Spring到service layer而已， Tapestry通过Global（扮演Service
Locator的角色）这个对象来调用，在domain Tapestry这一层还是有很多dirty code,
其实也可以用AOP来解决。如果能够像webwork2那样，所有的action都可以通过从Spring获得，即通过Spring获得page<br>

listeners, 那会方便很多，不过Tapestry也有自己的类增强功能，好像有一定的冲突，目前没有什么好的想法。<br>
<br>

顺便推荐3个我在项目中使用的工具 (都是eclipse plugin)：<br>

1. <a href="http://spindle.sourceforge.net/" target="_blank">http://spindle.sourceforge.net</a>  开发Tapestry的必备<br>

2. <a href="http://springui.sourceforge.net/" target="_blank">http://springui.sourceforge.net</a>  写Spring application context file的辅助好工具<br>

3. <a href="http://www.binamics.com/hibernatesynch/" target="_blank">http://www.binamics.com/hibernatesynch/</a>  Hibernate 开发的辅助好工具。<br>
<br>

from <a href="http://javamen.blogdriver.com/javamen/299858.html" target="_blank">http://javamen.blogdriver.com/javamen/299858.html</a></font>






































 
 











 


<img src ="http://www.blogjava.net/wy_71/aggbug/20405.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/wy_71/" target="_blank">wy_71</a> 2005-11-18 11:45 <a href="http://www.blogjava.net/wy_71/articles/20405.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>