王欢
[摘要] 当今开发Web应用的语言有很多种,如J2EE, ASP.NET, PHP等, 各种语言都有各自的优势和不同的应用场合。但企业级应用大都采用J2EE,使用它的框架技术SSH (Struts, Spring, Hibernate) 可以简化开发流程,加快开发速度,同时便于今后的运行和维护。
[关键词] J2EE; SSH集成框架; Struts; Spring; Hibernate; MVC
doi : 10 . 3969 / j . issn . 1673 - 0194 . 2012 . 02. 030
[中图分类号]TP311.5[文献标识码]A[文章编号]1673 - 0194(2012)02- 0053- 03
J2EE领域针对不同的层(Model,View,Controller)有很多框架,如何选择适合的框架是个关键问题。本文通过分析模型层、视图层和控制层的不同功能,最终选择SSH的集成。
1MVC模型
当用户向Web容器发送一个请求后,Web容器会根据请求和地址去调用一个Servlet进行处理,当Servlet处理完成以后,它需要将结果页面回送给Web容器。这时我们可以在Servlet内部编写Java类来生成HTML代码,Servlet直接把这些内容返回给Web容器的Response对象。此时Web容器收到这些内容并将其全部转化为HTML,再返回给浏览器。这种编程思想有一定的缺陷,它将Java代码也就是Servlet里面的代码和HTML代码混杂在一起,如果我们在之后对先前开发的代码进行维护,这时需要修改Servlet代码里那些用于生成HTML代码的字符串,这样非常麻烦,不便于开发和维护。于是人们开始思考采用其他方法来解决这一不便,于是MVC模式应运而生,用来实现Java代码和HTML代码的分离。
在MVC模式中,当Servlet处理完请求后,会产生一些数据,这些数据都会被装在对象中,这个对象具有不同的属性,我们将这个对象叫做JavaBean。这时我们再写一个JSP页面,这个页面从JavaBean中读取数据并嵌入在HTML代码中。以后当需要修改HTML代码的时候,我们就不需要修改Servlet,而是可以直接去修改JSP页面,这样就实现了Java代码和HTML代码的分离。
2SSH集成框架的设计
2.1视图层(View)
视图层的主要任务就是提供一个接口,接收用户提交的数据并将服务器处理的结果显示给用户,一般采用JSP页面实现。在没有采用框架技术前,会面临以下问题:首先,普通的HTML组件和JSP 标签提供的功能非常有限;其次,为了实现复杂的界面,不可避免地会在JSP页面中混入大量的Java代码,这样无法真正实现页面逻辑与处理逻辑的分离。最后,对页面的国际化处理要求越来越高。针对以上问题,在视图层采用Struts来实现。Struts提供了功能强大的自定义标签,不仅实现传统HTML页面组件的所有功能,还封装了大量Java代码,如逻辑判断、循环显示等功能。同时针对页面的国际化和数据校验要求,Struts也提供了相应的处理机制。
2.2控制层(Controller)
控制层的主要功能是接受客户端的请求,并调用相应的组件进行处理,最后采用不同的视图显示结果,在控制层采用Struts,Spring框架。Struts拥有一个结构清晰、功能全面、配置灵活的控制层结构,通过配置文件对客户请求进行分发和处理,实现视图层和控制层的衔接。对于模块间的紧耦合问题,采用Spring的IoC容器实现的依赖注入功能。另外,Spring的AOP很好地实现了事务管理功能。
2.3模型层(Model)
模型层的功能包括业务逻辑操作(JavaBean类)和数据库(DAO类)的操作,Spring的依赖注入功能解决了由于控制层通过硬编码调用这些类产生的紧耦合问题。另外,Hibernate以面向对象的方式实现了对数据的持久化工作,简化数据操作。
3Struts框架
3.1Struts概述
Struts是一个严格按照MVC模式设计的框架,重点在控制层和视图层上,即主要提供一个ActionServlet控制器和一套自定义标签库。View层主要通过JSP页面来显示,其提供的自定义标签库可以大大简化开发的过程。Controller主要采用Servlet实现,由ActionServlet和Action组成。Model主要采用Java/EJB实现。
3.2Struts的工作原理
如图3所示,Struts这个 Web层框架主要处理接收参数,返回结果,与数据库没有关系。换句话说,它就是一个大的Servlet,既然是Servlet,我们就可以在web.xml文件中对它进行配置并映射URL地址。这里它叫做ActionServlet。我们可以把符合某一组特征的请求映射给这个ActionServlet,是一组而不是一个。当ActionServlet收到不同的请求后,它会交给不同的Action进行处理。这时需要参照struts-config.xml这个配置文件来查看哪个请求对应哪个Action。目前为止,我们可能会疑问,这样做的好处在哪里?以前每收到一个请求,我们会编写一个Servlet,而现在我们每遇到一个请求,我们会编写一个Action,这有什么区别呢?
ActionServlet在调用Action之前,会将页面参数封装到JavaBean对象中,这样可以省去大量的request.getParameter(“”)这个方法;同时如果用这个方法来获得参数,我们还需要进行类型转换,例如将字符串类型转换成整形或日期类型。但如果封装到JavaBean中,就不用再进行类型转换。但是参数被FormBean封装后,我们怎么知道哪个FormBean对应哪个Action呢?这个问题可以通过查询struts-config.xml文件来解决。那么对于这个Form类,我们可以看到里面对应着所有的属性,并且每一个属性都有一个set和get方法。这里需要强调一点,通常情况下,页面的属性名称和Form类的属性名称相同,但是严格来说即使不一样也可以,关键是get方法的名字去掉get后要和页面的属性名称一样,这里名称是严格区分大小写的。在数据被封装到JavaBean中后,通过图4,我们发现还需要经过FormBean的validate方法的验证,如果数据没有意义,即没有通过验证,则这些数据不会被传递给Action。这时会显示一个错误页面,这个错误页面由struts-config.xml中的input属性来决定。默认情况下,我们需要对这些属性进行验证。当通过验证后,我们再来看Action类,每个Action并不是直接返回页面,而是返回一个ActionForward对象,而这个对象对应一个页面,这种对应关系可以在struts-config.xml中看到。例如:<forward name="reg" path="/reg.jsp" />,这样就实现了代码和页面的解耦。以后每当想修改跳转的页面时,只需修改配置文件即可。
4Spring 框架
4.1Spring概述
Spring 是一个开源的控制反转(Inversion of Control, IoC)和面向切面(AOP)的容器框架,它的主要目的是简化企业开发。
4.2IoC (Inversion of Control)和DI(Dependency Injection)
所谓控制反转就是应用本身不负责依赖对象的创建及维护,它是由外部容器负责的。这样控制权就由应用转移到了外部容器,控制权的转移就是反转。
IOC控制反转:
public class PersonServiceBean{
private PersonDao personDao = new PersonDao();
public void save(Person person){
personDao.save(person);}}
personDao 是在应用内部创建及维护的。原来要创建对象personDao是由PersonDao负责创建的,控制反转后,对象personDao的创建不再由PersonDao控制,而是由外部容器(这里我们指的是Spring容器)来负责创建。
依赖注入(Dependency Injection):在运行期间,由外部容器动态地将依赖对象注入到组件中。通过接口来启用这个对象,不像原来,如果不提供依赖类,连编译都无法通过。
当我们把依赖对象交给外部容器负责创建时,那么PersonServiceBean类可以改为:
public class PersonServiceBean{
private PersonDao personDao;
public PersonServiceBean(PersonDao personDao){
this.personDao=personDao;}
public void save(Person person){
personDao.save(person);}}
依赖注入的3种方式:
(1) 使用构造器传递参数注入。在配置文件中,<constructor-arg index=”0” type=”类型” ref=”依赖对象的名称”></ constructor-arg>Index=”0”: 表示第一个参数</constructor-arg>标签对。构造方法中有几个参数,就要有几个标签对。
(2) 使用属性setter方法注入。在类中,添加参数的setter方法为,在配置文件中:<property name=”” ref=””></property>。
(3) 使用Field注入(用于注解方式)。
4.3AOP (Aspect Oriented Programming)
用AOP很容易实现如权限拦截、运行期监控等功能。Spring提供了两种面向切面使用方式:
(1) 基于注解方式:@Pointcut(“execution(*cn.demo.service..*.*(..))”)。
(2) 基于XML配置方式:execution(*cn.demo.service..*.*(..))”。
5Hibernate 框架
5.1Hibernate概述
ORM (Object Relational Mapping):解决面向对象程序设计与关系数据库之间数据不匹配的技术。它是开源的对象关系映射框架。Hibernate本质上是一个提供数据库服务的中间件。其常用的6个核心接口是:Session,SessionFactory,Configuration,Transaction,Query,Criteria。使用Hibernate主要是创建相关的XML“映射文档”。
5.2使用Hibernate的注意事项
(1) 默认的构造方法(必须的,无参的)。
(2) 有无意义的标示符id(主键,可选),但是强烈建议加上,否则Hibernate的一些特性会受到限制。这样操作效率也会更高。
(3) 非final的,对懒加载有影响。类不能被继承。在运行过程中,Hibernate会把这个实体类替换成一个新的类,它是继承该实体类的。如果不能继承,那么懒加载这个功能也就失效了。懒加载是为了提高性能,避免不必要的数据查询,推后与数据库交互的时间,延迟到当你需要访问这个属性的时候。代理只在session关闭之前有效。通过asm和cglib这两个Jar包实现懒加载。
对象状态:
(1) 瞬时(transient):数据库中没有数据与之对应,超过作用域会被JVM垃圾回收器回收,一般是new出现且与session没有关联的对象。
(2) 持久(persistent):数据库中有数据与之对应,当前与session有关联,并且相关联的session没有关闭,事务没有提交;持久对象状态发生改变,在事务提交时会影响到数据库(Hibernate能检测到)。
(3) 托管(detached):数据库中有数据与之对应,但当前没有session与之关联;托管对象发生改变,Hibernate不能检测到。
6结束语
通过Struts,Spring,Hibernate三种框架的集成,充分发挥各自优势。该框架不仅具有Struts清晰的控制结构、Hibernate带来的操作数据库的方便性,而且Spring的IoC实现模块间的解耦。
主要参考文献
[1] 张峰. 基于Ajax技术与J2EE框架的Web应用研究与实现[D]. 北京:中国地质大学,2008.
[2] 李涛. J2EE平台下快速WEB开发的研究与应用[D]. 武汉:武汉理工大学,2010.
[3] 朱平付. 基于J2EE的轻量级架构开发方法及应用研究[D]. 长沙:中南大学,2008.
[4] 张军芳. 基于J2EE平台和MVC模式的Web研究与应用[D]. 武汉:武汉理工大学,2008.