Spring学习笔记四:Spring整合SSH框架,整合c3p0连接池,spring的aop事务操作,扩大session作用范围

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33322074/article/details/89357688

1. Spring学习笔记四:Spring整合SSH框架,整合c3p0连接池,spring的aop事务操作,扩大session作用范围。

1.1. SSH框架整合原理

  1. SSH整合是通过Spring牵线搭桥的,由spring容器接管Struts2的Action创建,由Spring接管实例化的创建,由spring接管sessionFactory,维护session,由spring接管aop事务。

spring整合ssh原理

1.2. ssh框架整合步骤

1.2.1. 导包(42个)
  1. hibernate包
    • hibernate/lib/required(9个)
    • hibernate/lib/jpa (1个)
    • 数据库连接驱动包(1个)
  2. Struts2包
    • struts-blank.war/WEB-INF/lib/*(13个,有一个javassist-xx-GA.jar重复去掉剩余12个)
    • Struts整合spring插件包:struts2-spring-plugin-xxx.jar,这个包一旦导入必须整合spring否则报错。(1个)
  3. 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个)
  4. 标签库包(2个)
    • standard.jar
    • jstl-jar
1.2.2. 配置spring配置文件applicationContext.xml
  1. 导入约束
    • 四个:beans,context,aop,tx

配置约束

  1. 配置web.xml让spring随项目启动而启动
    • 若忘记参数可以在spring-framework-release中web-sources.jar中导包。
<!-- 让spring随web启动而创建的监听器 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 配置spring配置文件位置参数 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
</context-param>
1.2.3. 配置struts.xml
  1. 导入约束dtd约束
  2. 配置struts2核心过滤器到web.xml
<!-- 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>
1.2.4. 整合struts2的Action到spring
  1. 导包(已经导入)
    • struts2-spring-plugin-jar
  2. 配置常量
    • struts.xml中配置Action由spring管理
    • 第二个默认已经配置好了,这些东西都在struts包里的default.xml中
<!-- #  struts.objectFactory = spring	将action的创建交给spring容器	
   struts.objectFactory.spring.autoWire = name spring负责装配Action依赖属性
   -->
<constant name="struts.objectFactory" value="spring"></constant>
  1. 整合方案一:struts2仍然创建Action,spring负责组装依赖属性。(不推荐)
    • spring完整管理action的生命周期,spring中功能才能应用到Action上。
<!-- 整合方案1:class属性上仍然配置action的完整类名
    struts2仍然创建action,由spring负责组装Action中的依赖属性
   -->
<action name="UserAction_*" class="cn.it.web.action.UserAction" method="{1}" >
    <result name="success" >/success.jsp</result>
</action>
  1. 整合方案二:Action,依赖属性,都是由spring创建组装。
    • 整合方案2:class属性上填写spring中action对象的BeanName,完全由spring管理action生命周期,包括Action的创建, 注意:需要手动组装依赖属性
<!-- 
    整合方案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>
  1. 方案二中的applicationContext.xml配置
    • 上面class属性是下面的bean的name属性,
    • struts2每次请求都会创建一个Action,因此必须配置成多例的。
<!-- action -->
<!-- 注意:Action对象作用范围一定是多例的.这样才符合struts2架构 -->
<bean name="userAction" class="cn.it.web.action.UserAction" scope="prototype" >
    <property name="userService" ref="userService" ></property>
</bean>

1.3. spring整合Hibernate

  1. 创建实体类和映射文件
  2. 配置hibernate.hbm.xml文件
    • 必选部分:数据库驱动,url,用户名,密码,方言。
    • 可选部分:生成sql语句,sql语句格式化,自动建表。
    • 引入实体配置文件
1.3.1. 整合原理与具体操作
  1. 将sessionFactory对象交给spring管理。
  2. 将sessionFactory配置到spring容器。
  3. 加载配置:两种方案,方案一:不推荐
    • 仍然使用hibernate.cfg.xml配置信息,在spring中导入配置信息路径即可。
<!-- 加载配置方案1:仍然使用外部的hibernate.cfg.xml配置信息 -->
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
    <property name="configLocation" value="classpath:hibernate.cfg.xml" ></property>
</bean>
  1. 加载配置:方案二(重点)
    • 在spring配置完成,减少配置文件
    • 导入hibernate各个配置,必选配置,可选配置
    • 导入orm配置文件
<!-- 加载配置方案2:在spring配置中放置hibernate配置信息 -->
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
    <!-- 将连接池注入到sessionFactory, hibernate会通过连接池获得连接 -->
    <property name="dataSource" ref="dataSource" ></property>
    <!-- 配置hibernate基本信息 -->
    <property name="hibernateProperties">
        <props>
            <!--  必选配置 
            <prop key="hibernate.connection.driver_class" >com.mysql.jdbc.Driver</prop>
            <prop key="hibernate.connection.url" >jdbc:mysql:///crm_32</prop>
            <prop key="hibernate.connection.username" >root</prop>
            <prop key="hibernate.connection.password" >1234</prop>  -->
            <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>
    <!-- 引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置 -->
    <property name="mappingDirectoryLocations" value="classpath:cn/it/domain" ></property>
</bean>

1.4. spring整合c3p0连接池

  1. 添加读取文件db.properties
  2. 添加配置文件c3p0配置文件,并导入db.properties文件
  3. 配置完c3p0后就不需要在applicationContext.xml中配置driver,url,root,password了。
<!-- 读取db.properties文件 -->
<context:property-placeholder location="classpath:db.properties" />
<!-- 配置c3p0连接池 -->
<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操作数据库

  1. spring整合过jdbc操作数据库,让jdbc操作数据库的类继承JdbcDaoSupport,实现了在spring监管下操作数据库。
  2. spring对于dao层的任何框架都进行了处理,对jdbc有封装,对Hibernate也有封装,对mybaties也有封装。
  3. spring整合hibernate就是让dao层,继承HibernateDaoSupport,获取spring封装下的方法,实现操作数据库。HibernateDaoSupport根据连接池创建了jdbc模板,实现类可以直接继承使用。HIbernateDaoSupport封装了session操作。
//HibernateDaoSupport 为dao注入sessionFactory
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
  1. 那么在ssh框架中操作数据库有两种方法,一种是hql语句,一种是Criteria方法
    • hql语句下,注意:内部类要引用外部变量,外部变量必须使用final修饰。
public User getByUserCode(final String usercode) {
		//HQL
		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;
			}
		});
  1. 使用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;
}
  1. 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. 准备工作
  1. 在处理jdbc的aop事务时已经讲过,这个和那个是一样的,spring通过aop思想对所有的方法进行事务处理操作。相当于把事务处理操作单独拉出来,谁用事务就给它安装。
  2. 在applicationContext.xml中配置核心事务管理器
<!-- 核心事务管理器 -->
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" >
    <property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
  1. 在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>
  1. 配置将通知织入事务
    • 配置切点,即:目标对象
    • 配置切面,即:通知
<!-- 配置将通知织入目标对象
 配置切点
 配置切面 -->
<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. 注解配置事务

  1. 开启注解事务,在ac.xml中配置
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
  1. 在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作用范围

  1. 由于hibernate加载机制默认懒加载机制即:延迟加载,只有调用时才加载,不调用不加载。
  2. 延迟加载机制:当查询时,会返回一个代理对象,不会先查,而是等用的时候再查,但是,等到页面再获取查的内容时,session已经在service层关闭,就会导致no session问题。解决方案是,把session作用范围扩大到一次请求。
  3. 目的:确保在view层session仍然是打开状态。
  4. 解决方案:是配置filter在web.xml,
    • 注意一定要放在struts的filter之前
    • 配置OpenSessionViewFilter过滤器
<!-- 扩大session作用范围
   注意: 任何filter一定要在struts的filter之前调用 -->
<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>

猜你喜欢

转载自blog.csdn.net/qq_33322074/article/details/89357688