:
 
  目前 J2EE 应用中,普遍使用了多层架构。本文提出了基于 J2EE 的轻量级多层架构,即业界比较成熟的 Struts + Spring + Ibatis 框架: Struts 是实现 MVC 最为成熟的框架,在 J2EE 项目中应用广泛; Spring 可以实现对 Ibatis 的无缝链接,适用于业务处理层;在数据持久层中,采用了 Ibatis 这一新的功能强大的 ORM 映射工具。文中讨论了轻量级多层架构的应用,并对几种数据持久层解决方案进行了介绍。在具体的案例中,充分结合 Struts Ibatis J2EE 体系结构过程中的性能,利用了 java 语言的反射机制,并对其中重要组件进行了配置,又从软件层次结构的角度考虑了此种架构应该注意的问题,包括伸缩性以及可扩展性问题,在实际的项目中取得了很好的效果。

关键词 :      轻量级架构 ;  Struts 框架 ;  Spring ;  Ibatis ; 数据持久层; ORM 

1    J2EE多层应用分析

1.1          J2EE层次结构

J2EE的三层结构在业界是指表示层(Presentation),业务逻辑层(Business logic)以及基础架构层(Infrastructure)。这样的划分当然是经典的,但是在实际项目中,往往会对三层体系结构做一些扩展来满足项目的需要。一个最常用的扩展就是将三层体系扩展为五层体系,即表示层(Presentation)、控制/中介层(Controller/Mediator) 、领域层(Domain)、 数据持久层(Data Persistence) 和数据源层(Data Source)。它其实是在三层架构中增加了两个中间层。控制/中介层位于表示层和领域层之间,数据持久层位于领域层和基础架构层之间。而轻量级架构Struts + Spring + Ibatis可以实现J2EE多层结构,Struts 用于表示层、控制层,Spring 用于业务处理层,而Ibatis 用于数据持久层。

1.2          Struts 框架

Struts是一个基于Sun J2EE平台的MVC框架,主要是采用ServletJSP技术来实现的。是开发Web应用程序的开放源码的FrameworkStrutsServletJSP、自定义标签和信息资源(message resources)整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套MVC模式,极大的节省了时间,Struts包括如下的主要功能:

 包含一个controller servlet,能将用户的请求发送到相应的Action对象。

 JSP自由tag库,并且在controller servlet中提供关联支持,帮助开发员创建交互式表单应用。

 提供了一系列实用对象:XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息

1.3          Spring 框架

Spring是一个目前非常活跃的开源项目;它是一个基于IoCInversion of Control)和AOPAspect-Oriented Programming)的,轻量级的,多层j2ee系统的框架,但它不强迫你必须在每一层中必须使用Spring,它模块化的很好,允许你根据自己的需要选择使用它的某一个模块;它实现了很优雅的MVC,对不同的数据访问技术提供了统一的接口,采用IoC使得可以很容易的实现bean的装配,提供了简洁的AOP并据此实现Transcation Managment,等等[ 1 ]

Spring虽然提供了MVC Web框架的解决方案,但是也能与其他的web框架相结合使用,如strutsWebworkJFS等。Spring也可以与其他持久层结构相结合,如:jdbcHibernateIbatis等,能够使用AOP的技术提供事务处理等功能 

1.4          数据关系映射Ibatis

Ibatis 提供了ORM机制,对业务逻辑实现人员而言,面对的是纯粹的Java对象, 这一层与通过Hibernate 实现ORM 而言基本一致,而对于具体的数据操作,Hibernate 会自动生成SQL 语句,而Ibatis 则要求开发者编写具体的SQL 语句。相对Hibernate全自动”ORM机制而言,Ibatis SQL开发的工作量和数据库移植性上的让步,为系统设计提供了更大的自由空间。作为全自动”ORM 实现的一种有益补充,Ibatis 的出现显得别具意义[ 2 ]

 

2    J2EE轻量级架构

2.1          架构

 

             
                                                                                             
                                                                                                 图1  框架示意图

2.2          View

在视图层主要使用Struts结构的技术。

TagLib

jsp的前端页面中使用Struts提供的标签完成页面数据逻辑的组织与显示。如(htmlbeanlogic等)

国际化的消息处理功能

jsp页面中不出现特定语言的字符串描述,将这些统一的字符串信息统一的提取到文件中,通过StrutsBean标签提取。便于整个系统的语言变更与组织。

界面组合功能Tiles

页面中将使用Struts的技术,统一组织页面的结构,便于系统改版、维护。

2.3          Control

控制层中依然使用Struts结构。此层将接受、处理View发送的请求,在对信息初步的验证、处理后,将把此请求委派给后端的业务处理层去处理。等待业务处理完成之后,将把处理结果传递给View层进行表现。

2.4          业务处理层

在该层中使用Service模式,提供给Control层必要的处理方法。

在接收到Control层的业务处理请求后,按照业务规范、算法对数据进行处理。将处理结果返回给Control层。

2.5          数据访问层

本层属于低级的数据处理层,将完成具体的数据处理工作,如数据的增加,更新,查询,删除等。

本层使用DAOData Access Object)的设计模式[ 3 ],屏蔽多数据库对上层应用的影响,并使用IbatisORMapping技术,降低数据操作的复杂程度。

3    数据持久层解决方案

3.1             数据持久层

将数据持久单独作为J2EE体系一个层提出来,表面上是因为数据持久性是企业实际开发中比较棘手的一个方面,数据持久层设计的成功与否往往对项目起着至关重要的影响,单独将其提出来以便在开发中能够避免它的设计草率。究其最深刻的内因,则是在对象范例和关系范例这两大领域之间“阻抗不匹配”。对象范例基于软件工程的一些原理,例如耦合、聚合和封装,而关系范例则基于数学原理,特别是集合论的原理。两种不同的理论基础导致各自有不同的优缺点。而且,对象范例侧重于从包含数据和行为的对象中构建应用程序,而关系范例则主要针对数据的存储。当为访问而寻找一种合适的方法时,“阻抗不匹配”就成了主要矛盾:使用对象范例,通过它们的关系来访问对象,而使用关系范例,则通过复制数据来连接表中的行。这种基本的差异导致两种范例的结合并不理想,于是有人提出对象数据库以希望解决这个问题。但是,关系数据库技术已经发展得相当成熟,占据了数据库市场90%以上的份额,对象数据库的普及尚需时日。数据持久层就是要在对象-关系数据库之间提供一个成功的企业级别的映射解决方案,尽最大可能弥补这两种范例之间的差异。

3.2             J2EE体系解决方案

3.2.1      EJB

CMP (容器管理持久)实体Bean,提供健壮的数据持久性。Bean 容器处理大部分的数据完整性、资源管理和并发性功能,从而使开发人员关注业务逻辑和数据处理,而不是这些低级细节。使用Bean 管理的持久性(Bean Managed PersistenceBMP)实体Bean 时,开发人员编写持久性代码而容器确定何时执行该代码。使用容器管理的持久性   ( Container Managed PersistenceCMP)实体Bean时,容器生成持久性代码并管理持久性逻辑[ 4 ]

3.2.2      JDO

Java 数据对象 (JDO) 是一个存储Java对象的规范[ 5 ]。它已经被JCP组织定义成JSR12规范。规范的两个主要目的是提供数据处理和访问机制的API以及允许规范的实现作为应用服务器的一部分。Java 数据对象是最新的持久性规范。JDO 提供了面向对象的持久数据存储。开发人员使用 POJO(无格式普通 Java 对象,Plain Ordinary Java Object)来装入和存储持久数据。

3.2.3      ORM

ORM 具有自我存储到关系数据库的能力,对对象的改变能够直接得以存储,而不考虑数据库存取代码。这样,把全部精力集中到对对象和类进行编程,解决业务问题。在整个系统中除了这一个层次,没有一句数据库存取代码。其中,HibernateIbatis作为 ORM中最好的开源工具,受到数量众多的程序员的拥护。

4    基于轻量级架构的应用案例分析

某大型水利信息系统需要使用J2EE 平台以满足分布式处理、事务管理和安全的要求,使整个软件呈现分层的体系结构,支持多种数据库的扩展,支持多语言界面的调整,支持页面整体布局的可扩展性调整。封装业务逻辑,使得在外部条件变化时,将影响尽可能的降低,即采用了基于J2EE的轻量级架构。图2是信息系统的体系结构,图3是系统包结构

 

                                   2  体系结构图

 

 

3  系统包结构

 

3中箭头表示软件包之间的依赖关系。独立的包会被SpringstrutsIbatis框架结构间接的与其他软件包关联。

4.1             系统剖析

4.1.1      包结构描述

com.water.query.dao:该包内的类将引入Ibatis的重要组件,使系统能够感知功能操作的接口与接口实现类的关系,这些信息是Ibatis自动映射的前提条件之一。

com.water.query.dao.sqlmapdao:该包是数据访问的核心,使用Spring结构的数据层功能引进对Ibatis的支持

com.water.query.dao.iface :该包规定了所有业务的访问接口,只有在此包的接口中定义的方法才会被用户使用。是本系同中所有原子数据操作的定义点。

Ibatis :该包是由Ibatis数据存储层结构定义。由支持机构提供支持。

com.water.query.dao.sqlmapdao.sql :该包定义了所有操作的SQLSequence Query Language)语句,以及SQL语句与具体值对象的映射关系。

com.water.query.form :该包定义了本系统中用于数据传输的类。这些类实例是Web界面层与业务逻辑实现层之间的桥梁,起着传输数据的功能。

com.water.query.service : 该包是本系统引入Spring结构的入口点。通过该入口,系统中其他成员可以通过IoC(依赖倒转)功能访问具体业务的Service对象。

com.water.query.condition :该包内定义了一系列简单JavaBean,这些JavaBean将携带SQL需要的参数穿行于软件的Control层与Model层之间。

com.water.log :该包中定义了本系统使用的log组件。

com.water.query.domain.baseinfo :该包定义了所有基本信息查询模块将要使用的数据传输类。

 

4.1.2      控制层

在视图层和控制层中采用了Struts框架,在传统的Struts用法中,我们一般都有几个Action Bean和相应的form bean ,但在此设计中并不拘泥于Struts的传统固定用法,这里只用了一个自定义Action类,并且在form bean类的定义上也是创新的。

非传统的Struts开发模式,关键就在Struts Action类和form bean类上。Struts Action类只有一个:BeanAction,这与传统的struts编程方式很不同。BeanAction类是一个通用类,利用反射原理[ 6 ],根据URL来决定调用form bean的哪个方法。BeanAction大大简化了struts的编程模式,降低了对struts的依赖。利用这种模式,我们会很容易的把它移植到新的框架如JSFSpring

这样重心就转移到form bean上了,它已经不是普通意义上的form bean了。它不仅仅有数据和校验/重置方法,而且已经具有了行为,从这个意义上来说,它更像一个BO(Business Object)Struts-config.xml的配置里有3种映射方式,来告诉BeanAction把控制转到哪个form bean对象的哪个方法来处理。form bean的这些方法的签名很简单,例如:

public String myActionMethod(){
                      //..work
                     return "success";

 }

方法的返回值直接就是字符串,对应的是forward的名称,而不再是ActionForward对象,创建ActionForward对象的任务已经由BeanAction类代劳了。

 

4.1.3      业务层

利用Spring Framework BeanFactory机制,采用自定义的工具类(bean工厂类)来加载spring的配置文件,从中可以看出Spring有多灵活,它提供了各种不同的方式来使用其不同的部分/层次,您只需要用你想用的,不需要的部分可以不用。

具体的来说,创建CustomBeanFactory类,Spring的配置文件applicationContext.xml。以下就是该类的全部代码,很简单:

public final class CustomBeanFactory {

static XmlBeanFactory factory = null;

static {

     Resource is = new

InputStreamResource( CustomBeanFactory.class.

getResourceAsStream("applicationContext.xml"));

     factory = new XmlBeanFactory(is);             

}

public static Object getBean(String beanName){

     return factory.getBean(beanName);

}

}

实际上就是封装了Spring XMLBeanFactory而已,并且Spring的配置文件只需要加载一次,以后就可以直接用CustomBeanFactory.getBean("someBean")来获得需要的对象了(例如someBean),而不需要知道具体的类。CustomBeanFactory类用于{耦合1}的解耦。CustomBeanFactory类用于表现层的form bean对象获得service类的对象。

4.1.4      数据持久层的配置

4.1.4.1       Spring 配置文件

Spring在设计时就充分考虑到了与Struts的协同工作,并且对Ibatis 有很好的支持,在此轻量级架构中,不需要对Ibatis单独进行配置,只需对 Spring 进行配置就以足够。以下就是Spring的配置文件applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"

"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="dataSource"

class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<property name="driverClassName"><value>net.sourceforge.jtds.jdbc.Driver</value>

</property>

<property name="url"><value>jdbc:jtds:sqlserver://127.0.0.1:1433/Sample</value>

</property>

<property name="username"><value>test</value></property>

<property name="password"><value>changeit</value></property>

</bean>

<bean id="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

<property name="configLocation"><value>SqlMapConfig.xml</value></property>

</bean>

<bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource"><ref local="dataSource"/></property>

</bean>

<bean id="userDAO" class="net.xiaxin.dao.UserDAO">

<property name="dataSource"><ref local="dataSource" /></property>

<property name="sqlMapClient"><ref local="sqlMapClient" /></property>

</bean>

</beans>

可以看到:

1sqlMapClient节点

sqlMapClient节点实际上配置了一个sqlMapClient的创建工厂类。

configLocation属性配置了ibatis映射文件的名称。

2transactionManager节点

transactionManager采用了Spring中的DataSourceTransactionManager

3userDAO节点

对应的,UserDAO需要配置两个属性,sqlMapClientDataSource

sqlMapClient将从指定的DataSource中获取数据库连接。

4.1.4.2       Ibatis映射文件

sqlMapConfig.xml:

<sqlMapConfig>

<sqlMap resource="net/xiaxin/dao/entity/user.xml"/>

</sqlMapConfig>

user.xml为:

<sqlMap namespace="User">

<typeAlias alias="user" type="net.xiaxin.dao.entity.User" />

<insert id="insertUser" parameterClass="user">

INSERT INTO users ( username, password) VALUES ( #username#,

#password# )

</insert>

</sqlMap>

UserDAO.java

public class UserDAO extends SqlMapClientDaoSupport implements

IUserDAO {

public void insertUser(User user) {

getSqlMapClientTemplate().update("insertUser", user);

}

}

SqlMapClientDaoSupportSpring中面向ibatis的辅助类,它负责调度DataSource

SqlMapClientTemplate完成ibatis操作,而DAO则通过对此类进行扩展获得上述功能。上面配置文件中针对UserDAO的属性设置部分,其中的属性也是继承自于这个基类。SqlMapClientTemplate对传统SqlMapClient调用模式进行了封装,简化了上层访问代码。

5    总结

从软件层次结构的角度来说,软件的框架要具有较高的伸缩性和可扩展性,本文所讨论的J2EE轻量级架构,由于它采用了Struts框架,因而它的模块化设计得到了很好的应用,层次非常清晰,具有很好的可复用度,但是,同时,此架构存在可伸缩性问题,架构中明显存在可伸缩性问题的设计是Action。控制器ActionServlet 对每个Action 类只创建一个实例,所有对该Action 类的请求都用这个实例进行处理,因此,它是无状态的、多线程共享的。这意味着Action 实例的数量是一个常数,不能随工作量增加而增加。此外,反射的利用是对架构扩展的一个有益尝试,虽然提供了非常好的应用开发模式,但是它还非常新,一直在发展中。数据持久层中,Ibatis的应用给人一种耳目一新的感觉,但它也存在着一些不足之处,例如相对于Hibernate Ibatis不能直接生成sql语句,需要人工编写。

轻量级架构结合StrutsSpringIbatis ,充分发挥了三者的优点, 基于轻量级框架的J2EE 架构开发简洁、结构清晰,有很好的可扩展性和可维护性,非常适于面向对象的设计与开发。

 

参考文献(References

 [1]   Expert One-on-One J2EE Design and Development  (美)Rod ohnson,Juergen Hoeller

机械工业出版社 2005-8-1

[2]   What is iBATIS?  http://ibatis.apache.org/  2005

[3]  iBatis DAO  http://www.onjava.com/pub/a/onjava/2005/08/10/ibatisdao.html  2005

[4]  Roman E. Mastering EJB (2nd Edition). 北京: 机械工业出版社,  2003-01

[5]  JDO:SunJDOSpecification[EB/OL].

http://www.jcp.org/aboutJava/communityprocess/first/jsr012/index.html , 2003

[6] Java编程思想(第2版)(美)Bruce Eckel机械工业出版社2002-9-1

Feedback

# re: 基于J2EE轻量级架构的多层应用的研究  回复  更多评论   

2006-06-16 10:43 by
为什么不给个完整的简单的例子
学习一下

# re: 基于J2EE轻量级架构的多层应用的研究  回复  更多评论   

2006-06-16 11:42 by 寒晴天
哈哈,好文章

# re: 基于J2EE轻量级架构的多层应用的研究  回复  更多评论   

2006-06-16 13:24 by google
路过

# re: 基于J2EE轻量级架构的多层应用的研究  回复  更多评论   

2007-06-18 16:27 by ploow
FrameCountry是采用.Net的开发平台,专注于数据库访问层功能的架构系统,为用户提供便捷、规范、强大的功能,提升开发效率。

FrameCountry特点
1. 便捷开发:封装、整合数据库操作方式,让开发人员摆脱数据库的约束;
2. 规范开发:依据多层设计原理,明晰人员分工,提高程序可读性;
3. 记录运行情况:开发人员依据记录了解系统详情,方便调试排错;
4. 多样数据库连接:实现多种数据库连接方式,对开发人员透明化数据库连接,使其只关注上层程序,同时降低数据库转换、升级工作量,目前实现Access2000、SQLServer2000两种数据库,日后逐步增加关系型数据库连接配置;
5. 整合有效函数:对开发中其它的有用的、常用的函数进行整理,简单调用实现;

访问http://blog.csdn.net/lizheng82

只有注册用户登录后才能发表评论。


网站导航:
 

posts - 4, comments - 8, trackbacks - 0, articles - 0

Copyright © 曹青松