论坛首页 Java企业应用论坛

如何构建灵活可靠复用性高的软件-<struts+spring+hibernate的框架下构建低耦合高内聚的软件>读后有感

浏览 12932 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-06-22  
如何构建灵活可靠复用性高的软件的思路和实现
      
原文作者提出了以下几个问题,并作出了相应的回答。
1、    我们如何能设计出高 水平、高质量的软件出来。怎样是高水平、高质量的软件?它应当是易于维护、易于适应变更、可重用性好的一个系统。如何做到这一点呢?
 答案:低耦合、 高内聚。低耦合就是软件在构造的时候,各个模块、各个功能、各个类都不会过度依赖于它周围的环境。只有这样,才能使我们的模块(功能、类)在周围发生 变更时不受影响,做到易于维护和易于适应变更。正因为如此,也使它更易于重用到其它功能类似的环境中,提高了重用性。高内聚则使软件中的各个模块(功能、 类)能够各尽其能而又充分合作,也就是对于软件问题空间中需求的各个功能,系统可以合理地把它分配给各个模块(功能、类)来共同完成,而不是一个或几个八 面玲珑、包打天下的超级类一个人完成。而对于该系统中的某一个模块(功能、类),具有自己高度相关的职责,即该职责中的几个任务是高度相关的。每一个模块 (功能、类)都决不去完成与自己无关职责的任务。
2、    如何用struts+spring+hibernate来构造“低耦合、高内聚”的软件。
原则1:编写DAO的时候不要直接去使用hibernate或spring对hibernate的支持。
原则2:编写Action的时候不要直接使用spring和spring的继承类。
原则3:当BUS需要获取别的模块的数据的时候,不要直接去使用该模块的DAO。
针对以上3个原则,我基本认同。首先要从J2EE经典的分层和现在流行的轻量级和重量级的开发框架与开发模式分析。

J2EE经典的5层架构
1、    客户端
2、    表示层
3、    业务逻辑层
4、    数据持久层
5、    DB
针对以上几个层次有相应的解决方案:
1、    Jsp(struts)+javabean(servlet)
2、    Jsp(struts)+sessionbean+eneitybean
3、    Jsp(struts)+sessionbean+hibernate
4、    Jsp(struts)+spring+hibernate
…………………
Struts是表示层框架,另外还有tapestry,jsf等这些新的表示层框架。第一个解决方案针对一些小型的软件还可以应付,项目大的话运行效率和开发效率都会跟不上。第二个是经典的EJB架构,人称重量级的架构。EJB将企业级应用的事务安全都考虑在内了,但是这种框架配置文件复杂,调试困难,开发效率不行,运行效率也备受争议。尤其是entitybean是被批评最多的,所以在第三种架构当中将entity换成hibernate。第四种是人称轻量级的开发框架,也是时下最流行的一种框架。本文也是主要针对这个框架来说事的,该框架组合用struts实现表现层,用spring实现逻辑控制层,用hibernate实现数据持久层。以下提出我的若干想法:
1、    EJB也不是一无所是的, EJB中的无状态 session bean 和消息驱动bean是挺好用的,很多人都这么认为,包括我。Struts+spring+hibernate也有它的局限性。
2、    无论采用怎么样的框架都是对J2EE经典分层模型的一个实现,就看谁更快,更好。
3、    J2EE各个层次的解耦不是依赖于特定的框架的,将设计模式融入到项目中才能很好的将各个层次很好的分开来,并且要基于接口的编程。
4、    不同的情况下采用不同的框架。没有最好的框架,最好做到框架的可替换性。
5、    复用最好定在组件级别的复用,而不是代码级别的复用。

开发模式
现在公司采用的开发模式一般有2种:
1、    按功能垂直划分,每个开发人员负责某个功能点的包括表示层,业务逻辑层,数据持久层的开发,可能还要包括美工,DBA部分的工作。
2、    按J2EE分层来划分,表示层由某些开发人员开发,业务逻辑层由其它的开发人员开发,数据持久层又是另外一批人来开发。

开发模式1的优缺点:
优点:功能模块划分清晰,责任明确。是你做的功能点就是你做的,逃不掉的。各个开发人员之间的交互较少。
缺点:各个方面都要做,对开发人员的要求比较高,项目大了可能就没有办法采用这种开发模式。
开发模式2的优缺点:
优点:适合大型软件开发,对开发人员要求低。每个开发人员都是一个螺丝钉,最终组装出一个优秀的软件。
缺点:开发人员之间的交流成本增大,系统架构和项目管理显得很关键。
举例子
我所在的项目组中有前台,后台,工作流,接口,安全这几个模块,并且跟公司内部的帐务系统和公司外部单位系统之间有数据交互。系统之间是频繁的交互的,系统内部各个模块都要相互配合来完成同一样事情。接口模块接受外部系统的请求,把请求丢给工作流去调度,工作流根据不同的流程调用后台不同的功能或者调用外部系统。这个情况下如果光采用struts+spring+hibernate架构是不能满足要求的。如果将所用的功能放在一个工程中,那项目各个模块的耦合性太高了,必然导致管理上的混乱。如果分开为各个项目,又要考虑各个模块的通信问题。Spring还是缺少一个比较好的远程调用的方法,这个时候就要用到web service来实现我们的SOA架构了。但是开发web service是需要成本的。项目跟外部系统的交互基本上是通过web service来进行,有些通过http方法来交互。接口多了,管理和开发的成本又变高了。
通过web service可以达到服务级别的复用,服务之间可以组合为一个新的服务。每个功能对外暴露为一个服务。然而这个web service也是有缺点的。1、对系统内部来说是增加了开发成本;2、调用效率不够高。
另外一种远程调用的方式是EJB的无状态sessionbean(简称slsb),系统内部各个模块间采用slsb进行沟通,使得模块之间到了组件复用的级别。例如安全模块,安全模块做好后部署在某台服务器上,同时好几个应用可以采用这个安全模型,而不用增加额外的编码工作。这样这个安全模块就复用了。另外一个例子是权限管理系统,可以将权限管理部分抽取出来公用。

要求
要制定一个适应2种开发模式的通用解决方案,就要结合EJB和Spring的强项。具体要求如下:
1、    要能将各个模块很好的解耦,J2EE的各个层次之间耦合性小,使得各个层次的框架可替换。
2、    能够快速开发和调试,应付常见的需求变更等。
3、    复用性高,并且能对各个功能点进行编排和组合。
4、    通用性好,可以不做修改或者修改很少就可以在不同的服务器上运行。

方案
1、    在表示层和业务逻辑层之间引入delegate和sessionfaçade模式,能很好的将表示层和业务逻辑层进行解耦,delegate对外提供一个接口供客户端使用,可以提供2种实现,一个是以POJO的形式实现,一个调用EJB来实现。客户端不用关心哪个实现来给他提供服务的。EJB作为一个façade,只是起到一个转发的作用,在系统中只需要1到2个slsb用于区分不同的功能点。
2、    在业务逻辑层和数据持久层之间引入dao模式,提供一个baseDao的接口,dao的实现类要实现这些基本的接口。对业务逻辑层来说,它不关心数据持久层是用hibernate来做的还是用ibatis来实现的。这个baseDao基本可以实现大部分数据库操作。
3、    构建一个灵活可靠的业务逻辑层,类似工作的思想,一个流程中的活动能相互编排和组合。
4、    企业应用的安全、事务和异常处理等要抽取为系统服务,各个层的代码只是关心各自的业务逻辑,各个层次的异常不会相互影响。
5、    引入Spring,运行是来决定各个bean的关系。来实现各个层次的解耦。前台的struts、后台的hibernate都可以被换掉。
6、    数据实现统一管理,业务逻辑层能为多个客户端(表示层)提供服务。只要涉及数据库操作的都要通过业务逻辑层来操纵数据持久层来实现。
                    
 整体架构图

实现
提供一个权限控制管理系统的实现。如果采用该模型,则可以作为其他应用系统的后台管理系统。
表结构:
1、t_user:用户基本信息表,并没有做用户的详细信息表,因为每个系统的用户信息都不一样。但是做好后可以很容易将用户详细信息表的操作跟基本信息表联系起来。
2、t_role:角色表,可以分析管理员,普通用户等,具体系统具体分析。
3、t_function:权限表,记录每个方法调用所需要的权限。
4、t_user_role:用户角色关系表,每个用户有1到多个角色,如果没有角色则不能登陆系统。
5、t_permission:角色权限关系表,记录每个角色有什么权限,一个角色有0到多个权限。
测试用户有(用户/密码)root/root,admin/admin,user/user,,每个用户有不同的权限,能看到和执行的内容也不一样。

运行环境:jboss4.0.5GA,mysql5.0.19,jdk1.4.2以上,IE6.0。

部署说明,本次提供jboss版本的权限管理系统,只要稍微改动spring的配置文件即可去掉ejb的调用,改用pojo方式来调用,就可以跑在tomcat等web服务器上。改动以下ejb的配置文件也可以运行在weblogic、websphere上,
1、    将权限管理系统解压并将app目录拷贝到jboss的default/deploy目录下。RightServerEAR.ear是后台的实现,managerWeb.war是前台的实现,前台是分散部署的,为了方便调试而已。前面的数字为了控制这2个包的部署顺序,jboss不像weblogic可以显式决定应用的部署顺序。Jboss部署ejb可以参考我blog上的另外一篇文章(http://onecan.iteye.com) 。eshore-destinations-service.xml是消息驱动bean的配置,打算用来做分布式的缓存更新通知,暂时没有实现。mysql-ds.xml是mysql的数据源配置,更改spring配置文件中的数据源配置也可以不用jboss的数据源。

2、    配置文件。拷贝整个etc目录到jboss的bin目录下。并在bin目录下建立JCFServerLog目录用于日志的输出。
etc下文件ServiceConfig.xml是用于定位ejb、log4j等服务的,log4j.properties文件是log4j的配置文件,按照各个层次会将日志打到不同的文件中,每天一个新文件。BusinessLog:业务逻辑层的日志,DAOLog持久层的日志,Weblog:表示层的日志。
etc下的artemis目录是业务逻辑层beans的配置文件,之所以拿出来是要达到不重新编译便可以改变系统的业务逻辑。

权限管理系统源代码.rar是源代码目录,包括前台和后台的代码,另外关于后台的代码生成工具可以参考本人blog的另外一篇文章。

mxidea.sql为数据库文件,数据库名字叫mxidea。这个文件包括数据表结构和数据记录,如何导入mysql?不用说了吧。
源代码和工程见附件,因为依赖的jar包太多了,在源代码中没有给出完成的结构,如果需要完整的源代码可以跟我沟通gmhwq@126.com,大家可以相互学习一下。另外编译后的文件将要在另外一篇文章中给出来。
  • 描述: 整体架构图
  • 大小: 709.8 KB
   发表时间:2007-06-23  
图片怎么搞的不见了
0 请登录后投票
   发表时间:2007-06-23  
感觉这样做,效率上不会高很多!
轻量级的表现也没有完全体现出来,特别是还使用了command这种模式来解决业务层耦合.
大部分框架已实现的服务,我们不应该自己重写.
既然框架已经提供了,就应该,想办法,集成进来!
当然,集成的方式是可以研究以下的.
0 请登录后投票
   发表时间:2007-06-24  
跟平常的struts+spring+hibernate不一样的地方是在业务逻辑层加入了更加多的控制能力,使用spring的依赖注入将各种业务逻辑按需组合,并可以用ejb的远程接口向外暴露业务接口,当然你也可以不用ejb暴露也可以的,转换很方便。引入command模式是为了将业务逻辑放在放在普通的javabean中,而不是放在ejb中。至于如何定位ejb,在ejb中如何访问spring的上下文,在spring中使用ejb都已经封装起来的,在开发中主要的任务就是业务逻辑的开发,主要是用hibernate来实现了,所以开发和测试都比较快。
  问题在于业务逻辑复杂的时候spring的bean就比较多了,配置文件拷贝的时候就要小心了,其实开发过程中基本上都是copy&paste,对新手的要求比较的低。
0 请登录后投票
   发表时间:2007-06-25  
"但是开发web service是需要成本的"
什么是不需要成本的呢?
btw:如果用xfire的话,成本很低的说

“另外一种远程调用的方式是EJB的无状态sessionbean(简称slsb),系统内部各个模块间采用slsb进行沟通,使得模块之间到了组件复用的级别。例如安全模块,安全模块做好后部署在某台服务器上,同时好几个应用可以采用这个安全模型,而不用增加额外的编码工作。这样这个安全模块就复用了。”
复用是对的,但没必要引入分布式架构啊,安全模块为什么要部署到另外的服务器上呢?
通常我们说的分层、组件化都是指的逻辑上的,不是物理上的!

0 请登录后投票
   发表时间:2007-06-25  
另外我觉得你在spring容器之上设计的这些代理、门面什么的也不是很必要,因为spring就可以做到
当然我不是很了解你这样做的出发点,或者有其他考虑?
0 请登录后投票
   发表时间:2007-06-26  
spring可以实现delegate和facade的功能?一个是设计模式,一个是实现工具。用spring可以很好的支持ejb啊,用不用分布式要根据需求而定,不能一棒子打死了,而且用不用分布式都是实现配置化。
0 请登录后投票
   发表时间:2007-06-26  
onecan 写道
spring可以实现delegate和facade的功能?一个是设计模式,一个是实现工具。用spring可以很好的支持ejb啊,用不用分布式要根据需求而定,不能一棒子打死了,而且用不用分布式都是实现配置化。

ioc也是设计模式阿,spring不也实现了么?
我的意思是:为什么要在spring之外自己设计一些delegate和facade,为什么不可以把他们也变成spring的bean(只是粒度稍大一些的bean)
0 请登录后投票
   发表时间:2007-06-26  
onecan 写道
spring可以实现delegate和facade的功能?一个是设计模式,一个是实现工具。用spring可以很好的支持ejb啊,用不用分布式要根据需求而定,不能一棒子打死了,而且用不用分布式都是实现配置化。

再正确不过了
可是你还是没说为什么要引入分布式
0 请登录后投票
   发表时间:2007-06-28  
哈哈,相信楼上那位已经研读了spring with out ejb这本经典的书。为什么要用分布式,在javaeye上面也有很多激烈的讨论。在这里用ejb纯属项目原因。不是每个项目都适合使用分布式架构,也不是每个项目都不适合分布式架构的。其实采用web service这些远程调用的机制也算是分布式了。
0 请登录后投票
论坛首页 Java企业应用版

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