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"