Struts2,Spring,Hibernate各自的职责

        MVC由Struts2负责实现。

        系统的组件都由Spring集中管理。采用依赖注入来管理系统中各组件的依赖关系。避免个组件之间的硬编码组合。提高可扩展性。

        持久化解决方案借助Hibernate ORM框架实现,通过Hibenater,以面向对象的方式进行持久化操作。

 

 

一.整合Struts2和Spring

Struts2整合Spring需要Spring的插件包struts2-spring-plugin-x-x-x.jar。Struts2内置了该包。

Spring插件通过覆盖Struts2的ObjectFactory来增强核心框架对象的创建。当创建一个对象时,它会使用Struts2配置文件中的class属性去和Spring配置文件中的id属性进行关联。如果能找到,则由Spring创建,否则由Struts2框架自身创建,然后由Spring来装配。

 

1.为Web应用配置Struts2框架

web.xml配置

 



<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <!-- struts2控制器 -->
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
        </filter-class>
    </filter>

    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>



 

 

2.安装Spring插件

为了让Struts2框架与Spring整合起来,还应该在Web应用中增加Struts2的Spring插件。

将Spring插件包struts2-spring-plugin-x-x-x.jar和spring.jar放到WEB-INF/lib目录下。即完成了Spring插件的安装。

该插件中包含了一个struts-plugin.xml文件,该文件包含如下代码行:

<constant name=”struts.objectFactory” value=”spring”>

安装了Spring插件后,系统默认使用Spring容器作为Struts2的装配器,即Action又Spring负责装配其属性。

 

 

为保证Spring容器在Web应用时立即完成Spring容器的初始化。

需在web.xml文件中配置Spring监听器:



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



经过以上配置,Spring IoC容器会在Web应用启动时初始化,且成为Struts2框架默认的objectFactory。

 

3.添加Spring核心配置文件

在Web应用的WEB-INF/lib文件夹下配置Spring的核心配置文件。默认文件名为 applicationContext.xml。

ContentLoaderListener初始化Spring容器时,ContextLoaderListener默认加载系统WEB-INF/lib路径下的applicationContext. xml文件,无需增加额外的配置。

Spring 2.5 的核心配置文件



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd >
    ......
</beans>


 

以上所有步骤完成了Struts2+Spring的基本配置。其他配置均在以上基础上进行。Hibernate的使用由Spring负责管理。

 

 

 

二.实现持久层

1.装配数据源

如果持久层选择用Hibernate,则首先需要装配数据源,数据源由Spring IoC管理。Spring配置片段如下:

 



<!-- 定义数据源Bean -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <!-- 指定连接数据库驱动 -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
    <!-- 指定连接数据库URL -->
    <property name="url" value=“jdbc:mysql://localhost:3306/数据源名?useUnicode=true&characterEncoding=utf-8">
    </property></property>
    <!-- 指定连接数据库的用户名 -->
    <property name="username" value="root"></property>
    <!-- 指定连接数据库的密码 -->
    <property name="password" value="root"></property>
    <!-- 指定连接数据库连接池的最大连接数 -->
    <property name="maxPoolSize " value="20 "></property>
    <!-- 指定连接数据库连接池的最小连接数 -->
    <property name="minPoolSize " value="1 "></property>
    <!-- 指定连接数据库连接池的初始化连接数 -->
    <property name="initialPoolSize " value="1 "></property>
    <!-- 指定连接数据库连接池的最大空闲时间-->
    <property name="maxIdleTime " value="20 "></property>
</bean>



 

2.管理Hiernate SessionFactory

Hibernate的SessionFactory是Hibernate持久化操作的基础对象,SessionFactory是整个数据库经过编辑后的内存镜像。通常对应一个底层数据库。进行Hibernate操作之前必须完成SessionFactory的初始化。

 

在SSH中,SessionFactory由Spring创建并管理。使用SessionFactory需要数据库连接对象。所以需要把数据源Bean配置给SessionFactory。

以下是在Spring中配置SessionFactory Bean配置片段:



<!-- 定义了Hibernate的SessionFactory-->
<bean id="sessionFactory " class="org.springframework.orm.hibernate3.localSessionFactory">
    <!-- 装配数据源  -->
    <property name="dateSource" ref=”dateSource”></property>
    <property name="mappingResources" >
    <!--列出所有的Hibernate映射文件-->
        <list>
            <value>Test hbm.xml</value>
            <!--   其它映射文件   -->
        </list>
    </property>
    <property name="username" value="root">
        <props>
            <prop key=”hibernate.dialect”>org.hibernate.dialect.MySQLDialect</prop>
            <prop key=”show_sql”>true </prop>
            <prop key=”hibernate.hbm2ddl.auto”>update</prop>
            <prop key=”hibernate.jdbc.batch_size”>20</prop>
        </props>
    </property>
</bean>



  

通过Spring配置文件中增加如上的配置片段,就可以自动创建Hibernate的SessionFactory。

 

 

3.编写实体类(entity)

 

 

4.编写映射文件

一旦提供了映射文件Hibernate就可以理解POJO与对应表之间的关系了。

 

注:由于人们对Hibernate的使用存在误区。在实际开发中,很多情况下都是先有表再有映射对象。但Hibernate使用应该是先建立对象,再有映射表。

 

根据MVC架构和DAO设计模式,使用Struts2与Spring DAO(Hibernate)模块编写实际代码。

 

 

5.DAO

Spring容器管理SessionFactory。Spring对SessionFactory的初始化后,SessionFactoy就一直处于Spring容器管理下。当DAO组件需要进行持久化访问时,Spring容器负责将SessionFactory注入对应的DAO组件。

 

5.1. DAO接口

通过DAO接口,让系统中的业务逻辑组件面向DAO接口编程,让系统的业务逻辑组件依赖DAO接口,而是依赖于具体的类。从而提高解耦。

面向接口编程是一种良好的习惯,能让系统的个组件之间的依赖提升到接口层次,避免类层次的直接耦合。一旦系统需要重构,需要带动系统中的某个组件时,只要该组件的接口不会改变,依赖该组件上层组件也无需改变,从而提供了更好的复用。

 

5.2. 实现DAO组件

DAO组件实现了DAO接口,用以完成系统实际的CURD操作。

Spring框架为Hibernate持久化访问的DAO组件提供了HibernateDAOSupport基类, 该基类可以很方便的实现DAO组件。

DAO组件需要继承HibernateDAOSupport类,实现对应的DAO接口。

 

public class XxxDaoImpl extends HibernateDaoSupport  implements XxxDao{
    //CURD
}

 

5.3. 配置DAO组件

用Spring将装配好的SessionFactory注入DAO组件。

DAO组件的父类HibernateDaoSupport中包含了对SessionFactory的setter方法。

配置片段如下:

 



<!--配置系统DAO组件-->
<bean id=” xxxDao” class=”. XxxDaoImpl”>
    <property name=”sessionFactory” ref=”sessionFactory”>
</bean>


 

经过上面的配置后,系统DAO组件就可以正常运行了。

 

 

 

三.实现业务逻辑层(Biz或Service)

系统的业务逻辑组件所包含的方法取决于系统的业务需求,用户的每个业务请求通常都应该提供一个与之对应的业务逻辑方法

 

1. 定义业务逻辑组件接口(Biz或Service)

系统的业务逻辑也采用接口和实现分离份额规则,让业务逻辑组件接口定义该接口应该包含的功能(定义方法),而实现类提供该组件的实现。

 

public interface UserManger{
    //…
}

 

 

2. 提供业务逻辑组件实现类

依赖底层DAO组件提供的持久化操作,业务逻辑组件可以更加专注于业务逻辑的实现,无需理会底层的持久化实现。

因为系统的业务逻辑组件依赖DAO组件,这种依赖是一种松耦合的依赖,是接口层次的依赖。且以业务逻辑组件不需要直接定位DAO,无需理会DAO组件的实例化过程。Spring容器负责DAO组件的实例化,并把DAO组件实例注入业务逻辑组件,从而实现业务逻辑组件和DAO组件的高层次解耦。

让业务逻辑组件可以接受Spring容器注入DAO组件,必须为业务逻辑组件提供对应的setter方法。

 

public class UserMangerImpl implements UserManger{
    private UserDao userDao;
    public void setUser(UserDao userdao){
        this. userDao= userDao;
    }
    //实现UserDao的方法
    ….
}

 

 

3. 异常处理

业务逻辑方法处理底层持久异常的哲学:业务逻辑方法捕捉底层持久层异常,并抛出新异常。

 

这种异常处理哲学是为了保证持久层异常不会扩散到系统的表现层,从而提高系统安全性;业务逻辑方法抛出一个新异常,新异常里包装的是系统的提示信息。

 

在实际系统中,业务逻辑方法抛出的应该是用户自定义异常,从而为浏览者提供更丰富的提示信息。除此之外,还应该通过日志记录系统的底层异常,记录底层异常的目的是为系统维护提供更多有用的提示信息。

 

 

4. 配置以业务逻辑组件

首先将业务逻辑组件部署在spring容器中。

还应配置该业务逻辑组件所需要的DAO组件。

配置片段如下:

 



<bean id=”mgr” class=”org.xxxxxx. UserMangerImpl”>
    <property name=”userDao” ref=”userDao”>
</bean>


 

在Spring配置了业务逻辑组件之后,还需要为业务逻辑方法增加事务控制。因为用户的业务逻辑方法对应用户的一次业务请求。通常,用户的每次业务请求都是逻辑不可分的。因此应该为该方法增加增加事务控制。

 

 

 

四.Action的装配

Action有两种整合方式。

        1.通过Spring生成Action。通过Spring注入的形式装配Action的属性。

        2.通过Struts2生产Action。默认情况下由Spring按Name的形式自动装配Action的属性。

 

1. 方法一 

Spring生成Action 。好处:Action对象存在与Spring容器中,便于单元测试。

首先通过Spring配置文件来配置Action。

配置片段如下:



<bean id="LoginAction" class="action.LoginAction" scope="protptype">
       <property name="loginDao" ref="LoginDao"/>
</bean>


 

<bean>的class属性值为类的全限定名。

通过scope="property"配置。为每个请求创建一个Action实例。

 

在struts.xml或者等效的Struts2配置文件中配置Action时。

配置片段如下:



<action name="loginAction" class="LoginAction">
       <result name="success">/index.jsp</result>
</action>



 

注意:Spring配置文件的<bean>元素的class属性值与struts.xml的<action>元素的id或name属性值需要一致。

 

 

2. 方法二

利用struts-spring-plugin插件自动初始化Action。只需要在struts.xml中配置action即可,不需要在Spring配置文件中配置Action。

 

Spring容器为Struts2的Action依赖注入业务逻辑组件时,默认采用byName的自动装配策略。在这种自动装配策略下所有Action无需显示配置依赖的业务逻辑组件,假如Action需要一个名为”abc”的Bean,只要为该Action提供一个setAbc的setter方法。Spring可以根据名字来将abc Bean依赖注入该Action组件。

这种方式没有指定Action的作用域。Spring插件为每个请求创建一个Action实例。

 

当Action组件获得了业务逻辑组件引用后,就可以调用业务逻辑组件的业务逻辑方法来处理用户请求。

 

默认情况下,插件使用by name的方式装配,通过增加Struts2常量来修改匹配方式:设置方式:struts.objectFactory.spring.autoWire = typeName。

typeName的值如下:

name:相当于spring配置的autowrie="byName"(默认)

type:相当于spring配置的autowrie="byType"

auto:相当于spring 配置的autowrie="autodetect"

constructor: 相当于spring配置的autowrie="constructor"