基于Spring框架的WebSphere应用开发

轻量级的企业应用开发越来越受到广大J2EE应用开发者的追捧,而Spring框架又是轻量级容器的杰出代表。由于Spring的使用日渐广泛,因此已有许多基于WebSphere应用服务器(WAS)的应用采用了Spring框架。
本文首先介绍使用Spring开发Web应用的基本问题,然后结合WebSphere应用服务器,讲述Spring应用如何结合容器提供的服务。文章目的是与大家一起探讨如何更好的采用Spring框架开发基于WebSphere应用服务器的应用。

  1、Spring框架的主要思想描述

  Spring框架的核心思想我们可以用两个字来描述,那就是"解耦"。应用程序的各个部分之间(包括代码内部和代码与平台之间)尽量形成一种松耦合的结构,使得应用程序有更多的灵活性。应用内部的解耦主要通过一种称为控制反转(IOC)的技术来实现。控制反转的基本思想就是本来由应用程序本身来主动控制的调用等逻辑转变成由外部配置文件来被动控制。通常我们用一个所谓的好莱坞原则(Don't call me. I will call you.)来比喻这种控制反转的关系。由于控制反转的概念相对比较广泛,很多应用服务器实际上也实现了不同程度的控制反转技术,只是这些应用服务器对应用程序的侵入性太强。因此Martin Fowler专门写了一篇文章讨论控制反转这个概念,并提出一个描述更为准确的概念,叫依赖注入(Dependency Injection)。

  Spring框架中的各个部分都充分使用了这种依赖注入的技术实现,从而给应用以最大的灵活度。实际上,这种依赖注入的参数化应用控制并不是Spring的首创,比如IBM的多渠道应用整合平台(Branch Transformation Toolkit,BTT)很早就采用了这种外部参数化控制的技术。BTT中的"对象工厂"与Spring框架中的BeanFactory也有着异曲同工之妙。

  Spring框架另外一个比较重要的技术是它对于面向切面的编程(AOP)的支持。随着应用复杂度的逐渐上升和对应用灵活性要求的提高,IT逻辑和业务逻辑尽量分离的呼声也越来越高。AOP技术作为实现这种分离的一种比较好的途径而越来越受到大家的重视。Spring提供的是一种动态AOP实现,也即通过代理模式动态地在目标对象的方法前后插入相应的处理代码。应用程序与底层应用服务器平台的解耦也可以借助AOP技术来实现。Spring内置的AOP支持是一种锦上添花的功能。它使得一些本来必须由容器支持的功能,比如事务控制可以脱离开容器运行,从而达到"瘦身"的目的。这也是为什么Spring框架常被人成为轻量级容器的一个原因。

Spring框架可以与许多已有的框架技术结合使用。J2EE技术应用的一个重要特点是相关的开源社区非常活跃。Web应用的不同层次都有非常多优秀的开源框架存在。比如Web层的Struts,OR映射层的Hibernate等。Spring框架并不重新发明轮子,它的出现不是为了替代这些已有的框架。相反,Spring框架在设计上可以独立构建应用或者结合已有的框架一起构建应用。另外一个值得指出的地方是Spring框架的几大模块之间相互耦合度很小,因此Spring框架的使用可以根据实际需要选其部分模块循序渐进的使用,而非必须统统照搬。

  2、基于Spring的Web应用基础

  2.1 Web应用的典型层次

  Web应用一般在逻辑上根据功能分为以下几层:

  1.展示层

  这一层主要如何生成展示给最终用户的界面,尽可能少的包含业务逻辑处理。对于基于J2EE的Web应用,JSP是其最为常见的一种技术。Spring对于展示层的支持非常灵活,除了直接支持JSP之外,它还支持基于FreeMarker模板,基于Velocity模板或其它文档类型的界面等的表现层实现。

  2.业务层

  业务层一般包含主要的业务逻辑,尤其是与用例相对应的那些业务逻辑。另外,这一层也适合包含事务管理和安全控制方面的逻辑。良好的业务层设计可以使得展示层可以采用不同的技术而不影响业务层。业务层的功能上可以类比于J2EE技术中的无状态会话BEAN层次。

  3.数据访问对象(DAO)接口层

  DAO实际上就是数据接口层,在应用中建议通过接口来体现。DAO的存在使得数据访问可以与底层持久化层的具体实现相分离。一般在DAO接口中主要就是实现数据对象的查询、存储、删除等操作。从理论上讲,DAO层与底层数据的存储方式是独立的,也就是说并不一定要求是关系型数据库。Spring框架在设计的时候也考虑到了其它非关系型数据库数据源的情况。

  4.持久业务对象

  持久业务对象是问题域中业务对象的持久化表示,比如一个用户对象,一个银行帐户等。我们一般通过某种O/R映射技术来实现这些业务对象的持久化。持久业务对象是可以包含业务逻辑的,与业务层所包含的业务逻辑不同的地方是持久业务对象所包含的是与具体业务对象直接相关且更为通用的业务逻辑。

  5.企业信息系统

  企业信息系统泛指Web应用需要连接的后台系统,一般可以分为三大类,即ERP系统,企业传统的遗留系统和关系型数据库。大部分Web应用都是基于关系型数据库的,这也是像Spring等常见框架所主要考虑的企业信息系统。

  设计良好的Web应用在层次一般是上一层依赖下一层,但是下一层不依赖上一层。我们可以暂时概括为"向下而不向上依赖原则"。为了使得不同层次之间的依赖降到最低,建议使用接口耦合。这一点又是Spring框架发挥它外部配置优势的地方。

  2.2 MVC的选择

  虽然说MVC这种模式早在Java语言出现前就有了,但是这种模式在J2EE时代才大行其道,为广大Web应用开发者所接受。对于各种基于MVC的框架而言,其要解决的问题主要可以分为以下几部分:

  1.将Web页面中的输入封装成一个数据对象,比如像Struts的表单BEAN,Spring MVC中的命令类等。

  2.根据请求的不同,由负责分发的控制器来映射和调用相应的逻辑处理单元,并将上面的数据对象作为参数传入。

  3.逻辑处理单元完成相应的处理之后又把结果放入一个数据对象。

  4.在选择的展现界面中把返回的数据对象通过某种方式显示出来。

  在使用Spring构建MVC的时候,可以选择直接使用Spring自己的MVC实现,或者利用Spring对已有的一些MVC框架的支持。比如Spring可以支持Struts,WebWork等,与它们结合使用。Spring引以为傲的非侵入的特性在Spring MVC上表现得并不如人意。它与Servlet API的耦合度较其它部分高,而且需要使用一些Spring的接口和类。

  Spring MVC的主要分发器实现是org.springframework.web.servlet.DispatcherServlet,这是Spring MVC的访问入口。Spring提供SimpleFormController,AbstractCommandController等类来帮助应用构建各种控制器动作,并用ModelAndView类来联系展示和逻辑返回数据。如上节所述,Spring MVC能够支持不同的界面展示技术,而且界面的展示和其后面控制器的实现是分离的,也即界面展示技术的变化不用修改控制器的实现,只需要利用Spring的控制反转技术修改外部配置文件即可。比如,在使用JSP展示技术时,外部配置文件的viewResolver定义如下:

<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass">
<value>org.springframework.web.servlet.view.JstlView</value>
</property>
<property name="prefix"><value>/view/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>

  如果切换到FreeMaker模板技术,那么除了页面模板的修改之外,主要就是把对应的外部配置文件更改一下即可,如下所示。具体的展示逻辑部分不用做什么修改。

<bean id="viewResolver"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass">
<value>
org.springframework.web.servlet.view.freemarker.FreeMarkerView
</value>
</property>
<property name="suffix"><value>.ftl</value></property>
</bean>
<bean id="freemarkerConfig"
class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath">
<value>/view/</value>
</property>
</bean>


  如果不使用Spring的MVC框架而想结合已有的一些MVC框架,Spring也是支持的。Spring对于常见的MVC框架都提供了支持,包括Struts,WebWork,Tapestry和JSF等。结合使用这些框架的一个好处是可以使用一些已有的熟悉的技术,另外结合Spring的AOP拦截器可以相对比较容易地处理框架动作共有的事情,比如动作的日志处理等。如果选择这些MVC框架,那么在使用框架的配置文件和应用的Spring配置文件都需要做相应的修改。比如使用Struts的时候,Struts-config.xml配置文件中的映射动作类型一般会设置成org.springframework.web.struts.DelegatingActionProxy,或者设置控制器为org.springframework.web.struts.DelegatingRequestProcessor。然后需要在相应应的WebApplicationContext中定义与Struts Action对应的Bean。这样就可以充分利用Spring的控制反转技术来管理Struts的Action了。

  另外在使用这些框架的时候要解决的一个问题是上下文的装载。比如使用Struts,可以使用ContextLoaderPlugin来装载Web上下文。这个ContextLoaderPlugin替换了原来通过DispacherServlet装载的方式。需要在struts-config.xml文件中添加如下条目:<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"/>。这种方式可以使Spring的Web上下文随着Struts ActionServlet的初始化而装载。

  因此,如果用户已有的应用是基于某个MVC框架,或者用户熟悉某个框架,那么可以利用Spring对这些框架的支持结合使用。因为我们的目的本来就是为了解决问题而不是为了使用某种技术。但是对其它用户而言,如果不是对已有的一些MVC框架比较熟悉的话,那就直接使用Spring的MVC框架就可以了。 

2.3 Web Context设置

  对于不依赖于应用服务器的Spring 上下文(Context)设置,通常在应用代码中通过FileSystemXmlApplicationContext或ClasspathXmlApplicationContext来获取。比如使用这样的代码来得到上下文:

ApplicationContext ctx = new FileSystemXmlApplicationContext("config.xml");


  但是按照控制反转的原则,应用程序代码应该尽可能少的知道上下文的设置。因此,在基于Spring的Web应用中,这样的代码也可以省去。Spring可以通过配置让Web容器自动装载上下文配置文件。从本质上讲,Web应用的ServletContext就是Spring用来存放应用上下文的地方。Spring中与Web Context装载相关的有几个类:

  1.ContextLoaderListener:一般的应用服务器如WAS都能先装载Listener,如果不是的话,那么只能使用ContextLoaderServlet。

  2.ContextLoaderServlet:需要配置<load-on-startup>使得它率先装载。真正装载Context的类是ContextLoader,上面两个类只是两种调用ContextLoader的不同途径。ContextLoader内部实际调用的是XmlWebApplicationContext,其缺省配置文件为/WEB-INF/applicationContext.xml。

  如果使用ContextLoaderListener,其在web.xml中的配置一般如下:

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>


  如果使用ContextLoaderServlet,其在web.xml中的配置一般如下:

<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


  应用本身可能除了基于HTTP的Web渠道之外还通过别的渠道对外提供服务,因此,一个比较好的做法是把展示相关的配置与后面业务处理部分的配置分开。这样如果更改了应用的访问渠道,只需要修改对应的配置文件即可。因此,Spring提供了一个WebApplicationContext的概念。在WebApplicationContext中一般包含与Web访问相关的配置定义,包括各种控制动作的定义、界面展示的定义等等。

  WebApplicationContext一般由DispatcherServlet来初始化。在上下文层次结构上可以把它看成是ApplcationContext的子上下文。在缺省的情况下,DispatcherServlet装载的配置文件名称为其Servlet名称-Servlet.xml,但是可以通过contextConfigLocation参数来定制。DispatcherServlet在web.xml中的定义示例如下:

<servlet>
<servlet-name>Dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/context/Webcontrollers.xml</param-value>
</init-param>


  2.4 数据持久化层

  虽然使用J2EE技术的Web应用可以连接多种不同的企业信息系统(EIS),但是毫无疑问数据库是其中最为重要和常见的一种。正因如此,Spring对数据库访问提供了非常完备的支持。数据访问对象(DAO)模式是J2EE模式中非常重要的一种。它的主要目的是使得持久化层与业务逻辑层分离,从而屏蔽持久化层的具体实现。我们可以把Spring的DAO支持分为两大类,一是直接基于Spring JDBC模板的数据访问,另一类是基于某种O/R映射框架的数据访问。这里刚好可以使用Spring的控制反转特性,通过外部配置文件来定义DAO接口和实际实现类之间的关系。Spring框架目前支持的O/R映射框架包括Hibernate、JDO、TopLink、iBATIS等。

  假设我们定义了一个userDAO。当使用JDBC来实现这个DAO的时候,定义的类可以如下所示:

public class userDAOJDBC extends JdbcDaoSupport implements userDAO{ … }


  如果使用Hibernate来实现这个DAO的时候,定义的类如下:

public class UserDAOHibernate extends HibernateDaoSupport implements UserDAO { … }


  Spring对于其它的O/R映射机制都有相应的抽象类供应用使用,比如对于iBATIS有SqlMapClientDaoSupport,对于JDO有JdoDaoSupport等。

  下面我们看一下如何在Spring的配置文件中定义上述DAO与具体实现的关系。假设我们的userDAO具体实现是通过Hibernate,那么在applicationContext.xml中的一个DAO可以定义如下:

<bean id="userDAO" class="com.fgw.dao.hibernate.UserDAOHibernate">
<property name="sessionFactory">
<ref local="sessionFactory"/>
</property>
</bean>


  在这里我们实际DAO接口定义是:com.fgw.dao.UserDAO,而具体实现类为:com.fgw.dao.hibernate.UserDAOHibernate。显然,对于其它DAO的实现,我们只需要在配置文件中修改相应的实现类(具体实现类当然是比不可少的)和属性即可。比如对于JDBC的DAO实现,属性就定义成相应的数据源。

 
阅读更多

没有更多推荐了,返回首页