基于Spring+Struts+Hibernate的迎评促建网

2008-07-14 10:05杨公义
电脑知识与技术 2008年18期

摘要:开发迎评促建网是高校为迎接教育部本科教学评估需要面对的现实问题。首先,本文给出了迎评促建网的系统分析和模块设计;其次,从总体上介绍基于Spring+Struts+hibernate的开发架构的原理和层次结构;其次,以用户管理模块为例介绍使用该开发架构的全部开发过程;其次,给出该开发架构的开发规范;最后,对该开发架构的核心配置文件的关键技术给予说明。

关键词:Spring;Struts;Hibernate;Web开发架构

中图分类号:TP393文献标识码:A 文章编号:1009-3044(2008)18-20000-00

A Website for Welcoming Evaluation & Promoting Development Basing on Spring+Struts+Hibernate

YANG Gong-yi

(New Technology Research & Development Office, Modern Education Technology Center, Peking University, Peking, 100871, China)

Abstract:Developing a website for welcoming evaluation & promoting development is currently a practical problem for universities. Firstly, the paper introduces the system analyze & pattern design for the website. Secondly, the paper introduces the frameworks principle and structure. Thirdly, the paper introduces the total developing process basing on the user management module. Fourthly, the paper introduces the developing criterion using the framework. Finally, the paper explains the key config files key technology.

Key words:Spring; Struts; Hibernate; Web Developing Framework

1 引言

迎评促建网在高校迎新教育部本科教学评估的过程中,起了重要的作用。一个优秀的技术架构能够规范开发者的行为,保证web系统开发的安全性、稳定性和成功率。目前Open Source社区的Spring项目、Struts项目、Hibernate项目以及其他开源项目提供了优秀的第三方开发工具包,笔者将这些开发工具包整合在一起形成一个优秀的web开发架构。笔者开发的迎评促建网就是基于Spring+Struts+Hibernate(以下简称SSH)的web开发架构。

2 迎评促建网系统分析与模块设计

2.1 迎评促建网系统分析

迎评促建网是为了迎接教育部本科教学评估工作而建设的集信息发布、成果展示、审核、管理、用户浏览、文件下载、特定资源授权访问等功能于一体的专业网站。要求信息的编辑支持html在线编辑器功能,能够网上实现类似word的排版、编辑功能、支持图文汇排、支持多媒体资源的上传和编辑。要求信息的上传要经过审核后才能正式发布。

2.2 迎评促建网模块设计

对迎评促建网的系统分析,可以得出该系统由两大模块组成:用户管理模块和信息管理模块。用户管理模块的作用主要是用户信息的增、删、改、查、用户类别的管理。通过用户类别管理实现给不同类别的用户赋予不同权限。信息管理模块的作用是信息的增、删、改、查、信息类别的管理。通过信息类别管理实现让不同类别的信息属于不同的栏目。北大的迎评促建网的栏目信息类别分为:评建机构、评建文件、评建动态、评建简报、评建知识、教学成果、院系特色、教学改革、教师楷模、燕园学子、北大课堂、社会实践、友情链接。

完成迎评促建网系统分析与模块设计之后,接下来将以用户管理模块为例介绍基于SSH的轻量级J2EE技术架构,模块名称为Demo。因篇幅所限本文不再给出信息管理模块的详细细节。

3 SSH架构介绍

3.1 概述

在SSH架构中,系统结构大致分为三层,即数据持久层、事务逻辑层和WEB表现层。(1)数据持久层主要负责业务数据的持久化存储服务,目前我们采用Hibernate O/R Mapping技术实现;(2)事务逻辑层主要负责业务对象的转换传递、业务逻辑的组织及事务的控制等服务,同时事务逻辑层也是WEB表现层和数据持久层衔接的桥梁,WEB表现层通过事务逻辑层向持久层请求数据持久服务,目前这一层我们采用Spring Framework实现业务beans的依赖关系管理和运行时注入以及事务的控制等功能;(3)WEB表现层是所有业务逻辑的最终展现层,充当事务逻辑层的客户端,实现人机交互,目前这一层我们采用Struts技术来实现。

整个架构的系统结构,如图1所示。系统各层的调用关系,如图2所示。

图1 系统结构

图2系统各层的调用关系

在本系统中,用到的工具类开源项目有:Apache commons-BeanUtil; Apache commons-Lang; Apache commons-Logging; Apache commons-FileUpload;Dom4j;Log4j。用到的框架类开源项目有:Hibernate;Spring Framework;Struts;Junit。关于这些项目的技术细节,不在本文的介绍范围之内。

3.2包层次结构

包层次结构,如图3所示。

图3 包层次结构

edu.pku.framework.common包:该包是架构提供的一些全局通用程序,例如字符集设定Filter、一些预加载的Listener以及一些全局异常等。edu.pku.framework.util包:该包是架构提供的一些和业务无关的工具类,例如xml的处理、文件加密、类型转换等。edu.pku.framework包:该包是架构的基础组件,存放的是数据持久管理器(PersistenceManager)和Action的基础抽象类(BaseAction),数据持久管理器是一个数据访问接口,目前提供了一个针对Hibernate的实现,可以实现基本的单表CRUD操作,同时对服务器端的数据分页访问提供了支持;BaseAction对Struts 的DispatchAction进行了扩展,对Web层的数据分页显示提供了支持。edu.pku.demo包:该包下存放的是用户管理模块的工程。

4开发过程

基于SSH的总体开发流程,如图4所示。 下面我们就逐步来实现用户管理模块(Demo)。数据表结构,如表1所示。以下我介绍的开发过程是按照从后台服务开发到页面展现的顺序来进行的,在实际的项目开发过程中,某些开发环节的顺序可以按照需要进行调整。

图4 基于SSH的总体开发流程

表1 Demo的数据表结构

4.1 准备工作环境

首先,先确认自己本地的JDK是否安装完毕,本架构要求的JDK版本为1.4以上。我们把我们的工程命名为Demo,如果我们本地的工作目录是E:workspace,首先在工作目录下,新建一个名为demo的文件夹作为我们工程的工作目录。

接着,在demo下准备我们的如下目录结构src/edu/pku/demo/entity;src/edu/pku/demo/

service/;src/edu/pku/demo/service/impl;src/edu/pku/demo/web/action;src/edu/pku/demo/web/model;src/edu/pku/demo/test/service;src/edu/pku/demo/test/web。

再次,准备web工程的目录结构:demo/jsp;demo/images;demo/css;demo/logs;demo/js;demo/WEB-INF。接着我们把架构中提供的公共css文件、图片、js文件、架构依赖的第三方jar复制到刚刚建立的相应工作目录中,到此为止,我们的工作环境已经准备就绪,下面就可以进行具体的开发了。我这里的介绍不依赖于任何IDE环境,所以调试、编译、打包的过程我就不具体进行介绍了,在开发过程中,可以选择任何自己熟悉的IDE工具进行开发,通常采用ant作为build工具。

4.2 生成Hibernate的PO和.hbm.xml

这一步我们可以用工具生成,这里我给出一些工具供参考:tanghan plugin for eclipse;middlegen+hbm2java;MyEclipse;Xdoclet这些工具具体的用法不在本文介绍范围之内,在这一步我们生成的文件是:User.java和User.hbm.xml 这两个文件位于src/edu/pku/demo/

entity下。某些工具可能处理不了BLOB类型的字段,如果实体中存在这样的属性,在文件生成后,需要手工稍作修改。有些开发人员可能喜欢先写.hbm.xml,然后通过Schema Export来生成数据库DDL,这可根据开发人员的习惯恰当调整。

4.3 分析业务逻辑,编写UserService接口

在这一步的工作中,我们的工作成果是生成UserService.java接口文件,放在edu.pku.demo.service下,在接口中,声明了以下几个业务方法:

public interface UserService {

public void save(User user) throws ServiceException; //保存用户信息

因篇幅所限,这里省略其他的接口方法,包括:remove(long userid) //删除单个用户, remove(Long[] userid) //删除多个用户, load(long userid) //获取单个用户数据, uploadPhoto(long userid,InputStream is) //上传用户照片, byte[] getPhoto(long userid) //获取用户照片数据, getUserList()//获取全部用户列表, getUserList(String sKeyWord) //按照关键字查找用户, getUserList(String sKeyWord,int iPageNo,int iPageSize) //按照关键字返回用户列表,并分页。}

4.4 编写UserService接口的实现类

到此我们就该编写UserService接口的实现类了,在这个实现类中,主要完成以下功能:(1)组织业务逻辑;(2)调用FrameWork中的PersistenceManager接口进行数据存储访问。在实际开发过程中,大部分的业务逻辑将在此实现,也是本架构中代码量比较集中的地方。这一步的工作成果是生成了UserServiceImpl.java文件,该文件位于edu.pku.demo.service.impl下。到此为止,后端服务部分的开发工作已经全部完成。

4.5 在Spring的applicationContext-*.xml中进行相关注册

完成了后台服务的编写后,我们就可以在Spring中对这些组件进行注册了。在这一步中,我们要完成以下工作:(1)注册Hibernate的.hbm.xml Mapping文件(2)注册PersistenceManager接口和实现类(3)注册UserService接口和实现类(4)组件的依赖关系注入(5)配置声明式事务。目前架构中有3个spring的配置文件,分别是:(1)/WEB-INF/config/applicationContext-resource.xml,(2)/WEB-INF/config/applicationConte

xt-service-demo.xml,(3)/WEB-INF/config/applicationContext-dao.xml。其中,一些基础公共资源配置在/WEB-INF/config/applicationContext-resource.xml中,例如,dataSource,sessionFactory等;service层的组件配置在/WEB-INF/config/applicationContext-service-demo.xml中,这里放demo模块的service和action;数据持久层的组件配置在/WEB-INF/config/applicationContext-dao.xml中,这里放PersistenceManager。

4.6 界面原型设计

这一步可以作为需求分析阶段的一个工作成果,在这一步里我们生成了以下的系统界面原型,如图5、图6、图7所示。

图5 用户列表、查询和删除

图6 编辑用户

图7新增用户

4.7 分析对象展现模型,编写VO

根据前面的分析,我们确定了用户VO对象有以下几个属性:

protected String userid; //用户ID;

protected String username;//用户名称;因篇幅所限,这里省略了其他的属性:包括password(密码), email(用户email),hasphoto(是否上传照片)。有了这些属性,就可以直接在IDE工具中生成getter和setter方法,我们这里的VO是一个纯粹的POJO,不需要从任何类继承,只需实现Serializable接口即可,这个VO对象的用途主要是作为web端的页面展现模型。在这一步我们的工作成果是生成了UserModel.java文件,该文件位于edu.pku.demo.web.mode下。

4.8Struts的Action类编写

在我们这个模块中,只有一个Action类,即UserAction.java文件,struts可以帮助我们优雅的实现command模式,透明的完成和页面表单的交互,此Action需要扩展framework中的BaseAction基础类,这个基础类扩展了struts的DispatchAction基类,实现了默认的execute方法,对客户端的数据分页显示也提供了必要的支持。在这一步我们的工作成果是生成了UserAction.java,该文件位于edu.pku.demo.web.action下。

4.9配置struts-config.xml

struts的请求转发机制是通过ServletDispatcher进行的,需要在struts的核心配置文件struts-config.xml进行相应的配置。为满足团队开发的需要,我们把配置文件分割成多个。在WEB-INF/CONFIG下能看到struts-config-common.xml和struts-config-demo.xml。在struts-config-demo.xml中可以看到:

<!--用户form的配置如下:-->

<form-bean name="userForm"

type="org.apache.struts.validator.DynaValidatorForm">

<form-property name="id" type="java.lang.String" />因篇幅所限,这里省略了一些form-bean的属性,包括userid, username, password, email

</form-bean>

<!--用户action的配置如下:-->

<action name="userForm" parameter="dispatch"

path="/userAction" scope="request" type="org.springframework.web.struts.DelegatingActionProxy"

validate="false">

<forward name="redirectList"

path="userAction.do?dispatch=getList" redirect="true"/>

这里省略了一些forward,包括editObjectSuccess, getListSuccess

</action>

这样,在浏览器中就可以通过userAction.do?dispatch=getList进行访问了,ServletDispatcher 接收到请求后,会根据配置文件转发到edu.pku.demo.web.action.UserAction的getList方法进行处理,处理结束后,返回到/jsp/userlist.jsp进行数据显示。Struts的view支持多种显示方式,例如jsp、xslt、velocity、freemarker等,在该架构中,我们采用jsp进行数据显示,其中在jsp中也包括两种转发机制,即dispatch和redirect,默认采用的是dispatch,这两种方式的区别同servlet的forward和sendRedirect。

4.10 单元测试代码的编写

单元测试代码的编写是穿插在整个代码编写过程中的,例如在这个demo中,我们可以针对UserServiceImpl.java, UserAction.java分别编写单元测试代码,单元测试代码的编写时机也是在实现代码编写完毕后紧接着进行的,并不是所有的代码编写完毕后才去写测试代码。单元测试我们可以基于junit进行编写,基于junit编写单元测试,需要注意以下几点:(1)测试类需要扩展junit的TestCase基类;(2)所有的测试方法以test开头;(3)资源的初试化写在setUp方法中;(4)资源的销毁写在tearDown方法中。

5 架构要求的开发规范

本架构要求:(1)代码中不允许出现System.out.println等字样,需要打印调试信息一定要通过common-logging接口进行;(2)Web层的代码不允许直接访问PersistenceManager接口进行数据持久化操作,所有需要对数据进行持久化操作的行为必须通过Service来代理;(3)原则上,不允许在jsp中直接对文字信息进行硬编码,所有的文字资源信息要放在properties资源文件中,如果项目对国际化要求程度不高,这一点可以不做硬性限制;(4)不允许直接将Hibernate的PO对象直接返回给JSP页面,PO和VO的转换通过FrameWork中的BeanUtil.copy方法在Action中进行。

6 架构中的配置文件说明

6.1 /WEB-INF/config/applicationContext-*.xml

在本架构中存在以下3个和spring相关的applicationContext配置文件,分别是:(1)/WEB-INF/config/applicationContext-resource.xml;(2)/WEB-INF/config/applicationContext-service-demo.xml;(3)/WEB-INF/config/applicationContext-dao.xml这三个配置文件的分工有所不同,其中applicationContext-resource.xml主要负责一些基础公共资源的配置,例如dataSource,transactionManager, sessionFactory等;applicationContext-service-demo.xml主要负责demo模块的service层组件和action层组件的配置;applicationContext-dao.xml主要负责持久层组件的配置和装配,目前只有一个PersistenceManager接口。

其中applicationContext-resource.xml中关于事务控制的配置文件片段如下:

<bean id="transactionManager" <!--事务管理器-->

class="org.springframework.orm.hibernate.HibernateTransactionManager">

<property name="sessionFactory">

<ref local="sessionFactory"/>

</property>

</bean>

<bean id="baseTxProxy" lazy-init="true" abstract="true" <!--事务管理器传播属性-->

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<property name="transactionManager"><ref bean="transactionManager"/></property>

<property name="transactionAttributes">

<props>

<prop key="save*">PROPAGATION_REQUIRED</prop>

<prop key="remove*">PROPAGATION_REQUIRED</prop>

<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>

<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>

</props>

</property>

</bean>

6.2 /WEB-INF/config/ jdbc.properties

数据库连接配置文件,Oracle 10g的配置文件示例:

hibernate.dialect=net.sf.hibernate.dialect.Oracle9Dialect

因篇幅所限,这里省略了一些属性,包括driverClassName, url,username,password,

maxActive,maxIdle,maxWait,fetch_size,batch_size,show_sql,hibernate.cglib.use_reflection_optimizer

6.3 /WEB-INF/web.xml

J2EE Servlet Spec的标准配置文件,其中本架构中要求的配置片段如下:

因篇幅所限,这里省略<!DOCTYPE 属性

<web-app>

<filter><!—配置中文编辑过滤器-->

<filter-name>EncodingFilter</filter-name><filter-class>edu.pku.framework.common.EncodingFilter</filter-class>

因篇幅所限,这里省略ignore, encoding的参数配置

</filter>

<filter-mapping>

<filter-name>EncodingFilter</filter-name>

<servlet-name>action</servlet-name>

</filter-mapping>

<servlet><!—配置struts的servlet-->

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet

</servlet-class>

<init-param><!—-配置struts的几个配置文件-->

<param-name>config</param-name> <param-value>/WEB-INF/config/struts-config-edumon.xml,/WEB-INF/config/struts-config-demo.xml</param-value>

</init-param>

篇幅所限,这里省略debug<init-param>参数配置, 省略<load-on-startup>的属性设置

</servlet>

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

<error-page><!—配置出错跳转页面-->

<error-code>500</error-code>

<location>/jsp/edumon/error.jsp</location>

</error-page>篇幅所限,这里省略403,404错误页面</error-page>

<error-page>

<taglib>

<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>

<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>

</taglib>

<taglib>篇幅所限,这里省略struts-html.tld, struts-logic.tld, struts-template.tld, struts-tiles.tld, struts-nested.tld

</taglib>

</web-app>

6.4 /WEB-INF/classes/ApplicationResources_zh.properties

该文件的配置片断如下:

ui.lable.username=用户名称

ui.lable.password=用户密码。因篇幅所限,这里省略其他的资源项目。struts的i18n资源配置文件,如果其中包含有中文字符,则需要用以下命令进行转码:native2ascii -encoding GBK ApplicationResources_zh.properties ApplicationResources_zh_CN.properties。

6.5 /WEB-INF/classes/log4j.properties

Log4j的配置文件,配置片段如下:

log4j.rootCategory=INFO, stdout, logfile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender因篇幅所限,这里省略其他的属性设置:包括log4j.appender.stdout.layout; log4j.appender.stdout.layout.ConversionPattern; log4j.appender.logfile; log4j.appender.logfile.MaxFileSize; log4j.appender.logfile.MaxBackupIndex; log4j.appender.logfile.layout; log4j.appender.logfile.layout.ConversionPattern。

6.6 /WEB-INF/classes/struts-config-common.xml

struts的核心配置文件,该文件是struts请求转发的基础,同时,在本架构中struts和Spring的集成也需要在该文件中做些必要的设置,文件片段如下:

因篇幅所限,这里省略<?xml属性和<!DOCTYPE属性

<struts-config>

<form-beans>

</form-beans>

<global-exceptions>

<exception type="java.lang.Exception" key="action.errors.exception" path="/jsp/edumon/error.jsp"/>

因篇幅所限,这里省略其他类型的exception配置

</global-exceptions>

<global-forwards>

<forward name="error" path="/jsp/edumon/error.jsp" />

</global-forwards>

<message-resources null="false" parameter="ApplicationResources" />

<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">

<set-property property="contextConfigLocation"

value="/WEB-INF/config/applicationContext-*.xml" />

</plug-in>

</struts-config>

7 结论

基于SSH的开发的迎评建网,充分体现了Structs的MVC设计模式,Spring的依赖注入和面向方面编程的思想,Hibernate数据持久化的中间件技术。

参考文献:

[1] Spring - Java/J2EE Application Framework.http://static.springframework.org/spring/

docs/1.1.5/reference/index.html. 2008-03-03.

[2] The Apache Struts Web Application Framework. http://struts.apache.org/1.2.4/index.html .2008-03-03.

[3] hibernate_org - Documentation Overview. http://www.hibernate.org/5.html. 2008-03-03.

[4] 杨公义.大学生创新能力培养的网络平台设计与开发[J].远程教育杂志,2008,(01):59-62.

收稿日期:2008-04-17

作者简介:杨公义,男,工程师,北京大学现代教育技术中心新技术研究开发室。