1. Spring学习笔记四:Spring整合SSH框架,整合c3p0连接池,spring的aop事务操作,扩大session作用范围。
1.1. SSH框架整合原理
- SSH整合是通过Spring牵线搭桥的,由spring容器接管Struts2的Action创建,由Spring接管实例化的创建,由spring接管sessionFactory,维护session,由spring接管aop事务。

1.2. ssh框架整合步骤
1.2.1. 导包(42个)
- hibernate包
- hibernate/lib/required(9个)
- hibernate/lib/jpa (1个)
- 数据库连接驱动包(1个)
- Struts2包
- struts-blank.war/WEB-INF/lib/*(13个,有一个javassist-xx-GA.jar重复去掉剩余12个)
- Struts整合spring插件包:struts2-spring-plugin-xxx.jar,这个包一旦导入必须整合spring否则报错。(1个)
- spring包
- 基本包:core,beans,context,expression,logging,log4j即:4个spring核心包+2个日志包(6个)
- 整合web包:sprign-web包(1个)
- 整合aop包:spring-aop,spring-aspect,aop联盟(第三方包),aopweaving织入包(4个)
- 整合hibernate和事务:spring-jdbc,spring-tx,c3p0,spring-orm(4个)
- 整合junit4测试:spring-test(1个)
- 标签库包(2个)
1.2.2. 配置spring配置文件applicationContext.xml
- 导入约束

- 配置web.xml让spring随项目启动而启动
- 若忘记参数可以在spring-framework-release中web-sources.jar中导包。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
1.2.3. 配置struts.xml
- 导入约束dtd约束
- 配置struts2核心过滤器到web.xml
<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>
1.2.4. 整合struts2的Action到spring
- 导包(已经导入)
- struts2-spring-plugin-jar
- 配置常量
- struts.xml中配置Action由spring管理
- 第二个默认已经配置好了,这些东西都在struts包里的default.xml中
<constant name="struts.objectFactory" value="spring"></constant>
- 整合方案一:struts2仍然创建Action,spring负责组装依赖属性。(不推荐)
- spring完整管理action的生命周期,spring中功能才能应用到Action上。
<action name="UserAction_*" class="cn.it.web.action.UserAction" method="{1}" >
<result name="success" >/success.jsp</result>
</action>
- 整合方案二:Action,依赖属性,都是由spring创建组装。
- 整合方案2:class属性上填写spring中action对象的BeanName,完全由spring管理action生命周期,包括Action的创建, 注意:需要手动组装依赖属性
<action name="UserAction_*" class="userAction" method="{1}" >
<result name="toHome" type="redirect" >/index.htm</result>
<result name="error" >/login.jsp</result>
</action>
- 方案二中的applicationContext.xml配置
- 上面class属性是下面的bean的name属性,
- struts2每次请求都会创建一个Action,因此必须配置成多例的。
<bean name="userAction" class="cn.it.web.action.UserAction" scope="prototype" >
<property name="userService" ref="userService" ></property>
</bean>
1.3. spring整合Hibernate
- 创建实体类和映射文件
- 配置hibernate.hbm.xml文件
- 必选部分:数据库驱动,url,用户名,密码,方言。
- 可选部分:生成sql语句,sql语句格式化,自动建表。
- 引入实体配置文件
1.3.1. 整合原理与具体操作
- 将sessionFactory对象交给spring管理。
- 将sessionFactory配置到spring容器。
- 加载配置:两种方案,方案一:不推荐
- 仍然使用hibernate.cfg.xml配置信息,在spring中导入配置信息路径即可。
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<property name="configLocation" value="classpath:hibernate.cfg.xml" ></property>
</bean>
- 加载配置:方案二(重点)
- 在spring配置完成,减少配置文件
- 导入hibernate各个配置,必选配置,可选配置
- 导入orm配置文件
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<property name="dataSource" ref="dataSource" ></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect" >org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql" >true</prop>
<prop key="hibernate.format_sql" >true</prop>
<prop key="hibernate.hbm2ddl.auto" >update</prop>
</props>
</property>
<property name="mappingDirectoryLocations" value="classpath:cn/it/domain" ></property>
</bean>
1.4. spring整合c3p0连接池
- 添加读取文件db.properties
- 添加配置文件c3p0配置文件,并导入db.properties文件
- 配置完c3p0后就不需要在applicationContext.xml中配置driver,url,root,password了。
<context:property-placeholder location="classpath:db.properties" />
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
<property name="driverClass" value="${jdbc.driverClass}" ></property>
<property name="user" value="${jdbc.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
1.5. spring整合hibernate操作数据库
- spring整合过jdbc操作数据库,让jdbc操作数据库的类继承JdbcDaoSupport,实现了在spring监管下操作数据库。
- spring对于dao层的任何框架都进行了处理,对jdbc有封装,对Hibernate也有封装,对mybaties也有封装。
- spring整合hibernate就是让dao层,继承HibernateDaoSupport,获取spring封装下的方法,实现操作数据库。HibernateDaoSupport根据连接池创建了jdbc模板,实现类可以直接继承使用。HIbernateDaoSupport封装了session操作。
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
- 那么在ssh框架中操作数据库有两种方法,一种是hql语句,一种是Criteria方法
- hql语句***意:内部类要引用外部变量,外部变量必须使用final修饰。
public User getByUserCode(final String usercode) {
return getHibernateTemplate().execute(new HibernateCallback<User>() {
@Override
public User doInHibernate(Session session) throws HibernateException {
String hql = "from User where user_code = ? ";
Query query = session.createQuery(hql);
query.setParameter(0, usercode);
User user = (User) query.uniqueResult();
return user;
}
});
- 使用criteria方法操作数据库
DetachedCriteria dc = DetachedCriteria.forClass(User.class);
dc.add(Restrictions.eq("user_code", usercode));
List<User> list = (List<User>) getHibernateTemplate().findByCriteria(dc);
if(list != null && list.size()>0){
return list.get(0);
}else{
return null;
}
- spring整合下的dao依赖属性是sessionFactory
<!-- dao -->
<bean name="userDao" class="cn.itcast.dao.impl.UserDaoImpl" >
<!-- 注入sessionFactory -->
<property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
1.6. spring的aop事务处理
1.6.1. 准备工作
- 在处理jdbc的aop事务时已经讲过,这个和那个是一样的,spring通过aop思想对所有的方法进行事务处理操作。相当于把事务处理操作单独拉出来,谁用事务就给它安装。
- 在applicationContext.xml中配置核心事务管理器
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" >
<property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
- 在ac.xml中配置通知
- 引用事务管理器
- 配置事务属性,以方法为单位,配置该方法事务的隔离级别,多例
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
- 配置将通知织入事务
<aop:config>
<aop:pointcut expression="execution(* cn.it.service.impl.*ServiceImpl.*(..))" id="txPc"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>
1.7. 注解配置事务
- 开启注解事务,在ac.xml中配置
<tx:annotation-driven transaction-manager="transactionManager" />
- 在service类中使用注解
- 放在类上面表示对所有方法进行注解
- 放在方法上面表示对某个方法进行注解
- 如果某个方法只要求读,那么就要对这个方法进行单独注解。
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true)
public class UserServiceImpl implements UserService{
@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)
public void saveUser(User u) {
ud.save(u);
}
1.8. 扩大session作用范围
- 由于hibernate加载机制默认懒加载机制即:延迟加载,只有调用时才加载,不调用不加载。
- 延迟加载机制:当查询时,会返回一个代理对象,不会先查,而是等用的时候再查,但是,等到页面再获取查的内容时,session已经在service层关闭,就会导致no session问题。解决方案是,把session作用范围扩大到一次请求。
- 目的:确保在view层session仍然是打开状态。
- 解决方案:是配置filter在web.xml,
- 注意一定要放在struts的filter之前
- 配置OpenSessionViewFilter过滤器
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>