(USEFUL)Tapestry+Spring+Hibernate整合工作小结

2024-02-14 16:58

本文主要是介绍(USEFUL)Tapestry+Spring+Hibernate整合工作小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Tapestry+Spring+Hibernate整合工作小结
ucgygah 转贴   更新:2005-04-16 22:16:49  版本: 1.0   


Cyberwing 


FrankSoo是我的项目经理。前段时间公司决定作个新的J2EE二次开发平台,以替换公司原有的开发平台。公司让FrankSoo和我组成平台开发项目组,FrankSoo担任项目经理。现在这个平台整合开发阶段已经结束,进入项目应用阶段。下面是我们的整合工作小结,介绍一下我们在工作中遇到的问题,以及我们选择的解决方案. 


1、架构的选择 

首先,我们都同意以我们现有的能力,没有足够的时间和资源自行开发一套完整的平台。在已有的众多开源项目中选择若干优秀的项目进行整合,才可能按时完成项目,达到项目目的。 

但是在平台项目开始前,我们对平台的技术架构有各自的构想。FrankSoo原来的构想是Struts+Spring+Hibernate,而我的构想是Tapestry+Hibernate。 

不过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. 

至于Hibernate,这个最成功的开源ORM项目,我们都投了它一票^_^ 

最后我们确定平台的技术架构是Tapestry+Spring+Hibernate. 

2、架构整合 

最初的平台架构借鉴了一篇介绍如何集成Tapestry与Spring的文章[1]中提到的架构: 

图1 
 

Web层的Tapestry负责数据输入输出, 响应用户事件,及输入校验的工作, 通过访问预先加载的WebApplicationContext(由Spring提供, 包含着所有Service bean)获得Service层的Service Bean, 把业务操作都委托给它们. 

Service层的bean则负责use case逻辑, domain相关的逻辑委托给domain model中的bean去实现. Service通过DAO完成对domain model的持久化工作. Service负责数据库事务和Hibernate Session的管理(通过Spring的声明式事务管理和与之集成的Hibernate Session管理). Service层的另一项重要工作是权限和访问控制。 

Domain model负责表示问题域的数据和domain logic. DAO使用Hibernate持久化数据以及查询. 在实现DAO时, 我们使用了Spring的Hibernate DAO Support,极大地简化了代码, 很多方法都只用简单的一行完成. 有意思的是, 最后完成的HibernateDAO的代码量居然比我写的MockDAO的代码少了一半还多 

这样的架构优点很明显, 层次清晰, 各层的职责也明确, 便于分层设计与开发, 结合mock和spring的IOC, unit test也是非常容易的. 而且后台(Service, domain model and DAO)的代码不依赖于Web容器或是EJB容器的API, 移植性非常好, 同样的代码可以在Web app中使用也可在普通的Java app中使用, 只需更换UI层. 

按照这个整合的构架,我们实现一个简单的实例,实现了列表分页查询和显示,数据增删改,基于Hibernate Criteria Query提供了一个比较通用的查询机制。利用Middlegen和Velocity我们可以从已经建好的数据库表结构自动生成Hibernate映射文件,实体类和DAO,极大地减少了工作量。我们还对这个小例子进行了压力测试(测试时的数据量为10万条记录),确定平台不存在性能问题。 

通过这个实例我们把整个架构基本走通一遍,并总结了使用这套架构开发时适用的开发流程和需要做的工作。 

3、困扰我们的问题 

在实现例子和现在的项目应用过程中,我们发现了若干头疼的问题,有的解决了,有的还没有。 

问题1:要不要使用DTO? 

在上面的架构中我们并没有明确Service和Web层间的数据传输是如何进行的。我们讨论好久要不要使用DTO,最后的结论是不用。 

使用DTO有两个主要的理由:1、减少Web层和Service层间的方法调用,通过一个方法调用就将Web需要的数据都传给Web。2、隔离domain model和Web层。 

第一个理由在我们的架构下是不成立的。因为我们的架构是集中式的,Web和Service是在同一个JVM中,它们之间的方法调用是没有EJB远程访问的巨大消耗的。 

第二个理由还是需要考虑的。如果允许把domain model中的对象传给Web层,那么修改domain model,就会影响到Web层。如果使用DTO,那么domain model实现上的变化就不会影响到Web。但是大量的变化不是domain model实现上的变化,而是domain model接口的变化,比如一个domain model的对象上添加了一个属性,而这个属性需要用户修改,那么这时候必须修改Web层,不管是不是用了DTO。而且使用DTO,就需要维护着一大堆对象,或是它们的生成器,这是非常无聊、且容易出错的工作。 

基于这些考虑,我们没有使用DTO,而是选择把domain model直接传到Web层。下面是修改后的架构图(呵呵,修改了别人的图[2])。 

图2: 
 


问题2:Entity like domain model or rich domain model? 

我们使用Middlegen自动生成Hibernate映射文件,Entity类和DAO类, 但是生成的Entity只含有简单的属性和getter, setter方法。因此我们遇到了一个问题:我们的domain model还要不要包含domain logic?如果包含,那么和自动生成工具如何结合? 

我们讨论后认为一个rich domain model还是非常有必要的,可以减少Service中的重复代码,提高复用性。 

如何同自动生成结合?使用<meta>标签,生成抽象基类,我们继承这些自动生成的基类,添加业务方法。 

问题3:Model driven or Data driven? 

采用Model driven还是Data driven的方式大家有过热烈的讨论。我们主要是受到Rod Johnson[3]的影响,采用了Data driven的方式。先作数据库设计,生成库表,然后用Middlegen反向生成Hibernate映射文件和Entity及DAO。但是我们在进入项目应用之后发现这种方法有两个问题: 

a) 数据库设计仅说明了系统要管理的静态数据,我们还是得作面向对象分析,以反映系统的动态行为。特别是当系统的业务不仅仅是简单的CRUD操作时,这个问题更严重。 
b) 数据库设计为了优化性能,可能会把好几个应该是单独实体的数据放入一个实体中。这样如果直接把这种极粗粒度实体映射成Entity类,那简直是不可接受的。面向对象的分析设计模型得到的类都是相当细粒度的。这种情况还得作面向对象的分析,明确到底这个粗粒度的大表应该映射成那几个细粒度的对象。 

或许我们应该试试Model driven,用AndroMDA生成domain model,Hibernate DAO,Hibernate mapping,数据库表,简单的Service和前台的Tapestry页面。 

问题4:Hibernate Session生命周期如何管理? 

对于Hibernate Session的生命周期我们采用的是Session-per-Transaction模式,未采用Open Session in View模式。 虽然Hibernate team认为这种方法没什么不好,而且FreeRoller和Atlassian的confluence都使用了Open Session In View这种模式,但是我们对它可能产生的影响还没有很好的把握,所以暂时弃置不用。 如果Web层要访问lazy load的数据, 需要先调用Service的业务方法, 以获得数据. 

问题5:Use case logic 和domain logic 如何区分? 

Service负责use case logic,domain model负责domain logic。这样的划分看起来很好,实现起来就很麻烦。如何确定什么是use case logic,什么是domain logic?TBD. 


问题6:Service粒度如何确定? 

这个问题真是很烦,原先考虑使用usecase controller的方式,每个usecase对应一个Service,但是发现这样复用性太低,而且好多地方必须复用相同的功能 

另一种方法是用package level service,每个package作个service,这样倒是可以重用,但是感觉太死了,不好。 

现在也没有什么很好的办法,只好在详细设计时根据具体情况确定需要多少个Service了。TBD. 

问题7:权限如何设定?如何检查? 

权限设定也是个头疼的问题。我们本想是按照use case设定权限,每个用例一个权限。在角色设定的时候直接处理的都是业务意义非常明确的权限。但是在权限验证过程中发现了问题:如果在Service的方法中验证权限,而且这个方法在多个用例中用到(复用Service),那么这个Service的方法就需要检查多个权限; 如果每个Service方法对应一个权限, 那么权限又太细了, 不像use case权限那样代表一个完整的业务. 真的是很麻烦阿!TBD. 



Ok, 这些就是我们这段工作的结果。希望能给大家一些启发,也希望能得到大家的帮助,帮我们出出主意,谢谢大家。 

<script type="text/javascript"> </script> <script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript"> </script>
 

这篇关于(USEFUL)Tapestry+Spring+Hibernate整合工作小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/709084

相关文章

SpringBoot简单整合ElasticSearch实践

《SpringBoot简单整合ElasticSearch实践》Elasticsearch支持结构化和非结构化数据检索,通过索引创建和倒排索引文档,提高搜索效率,它基于Lucene封装,分为索引库、类型... 目录一:ElasticSearch支持对结构化和非结构化的数据进行检索二:ES的核心概念Index:

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

Spring配置扩展之JavaConfig的使用小结

《Spring配置扩展之JavaConfig的使用小结》JavaConfig是Spring框架中基于纯Java代码的配置方式,用于替代传统的XML配置,通过注解(如@Bean)定义Spring容器的组... 目录JavaConfig 的概念什么是JavaConfig?为什么使用 JavaConfig?Jav

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位