(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

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定