今日的三大主要内容:Spring中的数据库操作事务、Spring整合hibernate、Spring整合Struts1.X,最来再来一个SSH整合。
数据库操作、数据库事务管理、hibernate、Sturts,这些大家都已经十分熟悉了。所以将他们与Spring整合使课程内容比较简单。Spring的特性是什么?不就是IOC的DI和AOP吗!简单在大脑里回顾一下,SSH整合正是使用这些特性。
一、Spring中的事务
Spring为什么提供对事务的支持?还记得我们在编写OA项目时,为了统一处理一类事务的多个Dao方法对数据库的操作是在一个事务中进行的,我们添加了一个“*.do”的过滤器,在过滤器中使用当前线程(ThreadLocal)的Session来处理事务。
其中我们也曾提到过将事务统一在过滤器中只是为解决一时之需,将事务统一放在Service的方法中才是优雅的做法。我们使用Spring就可以实现将事务统一放在Service的方法上。
1.在Spring中引入事务
通过外部Bean引入数据源我就不再做总结了,这里直接列出引入Spring中事务类的方法。下面为引入Jdbc的事务管理:
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> |
“tx”元素指定使用注解进行事务处理的Bean。
引入Hibernate的事务管理:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> |
2.使用Spring的事务
在Service方法上添加事务注解“@Transactional”,此时的Service方法便具有了事务管理。这正是使用AOP的编程思想,在过滤器上添加事务统一管理,也正是AOP的思想。
事务的传播性,当一个具有事务的方法调用另一个具有事务的方法时。此时可以设置事务的传播属性,实现不同的需求。事务的传播性有:
传播属性 |
描述 |
REQUIRED |
如果有事务在运行,当前的方法就在这个事务内运行,否则启动一个新的事务,并在自己的事务内运行。 |
REQUIRED_NEW |
当前的方法必须启动新的事务,并在它自己的事务内运行。如果有事务正在运行,则将它挂起。 |
SUPPORTS |
如果有事务在运行,当前的方法就在这个事务内运行。否则它可以不运行在事务中。 |
NOT_SUPPORTED |
当前的方法 不运行在事务中。如果有运行的事务,将它挂起。 |
MANDATORY |
当前的方法运行在事务内容,如果没有正在运行的事务,则抛异常。 |
NEVER |
当前的方法不应该运行在事务中。如果有运行的事务,则抛异常。 |
NESTED |
如果有事务在运行,当前的方法在这个事务的嵌套事务内运行。否则,启动一个新的事务,并在它自己的事务内运行。 |
前两项是常用的。
“Transactional”注解所具有的属性:
@Transactional(propagation=Propagation.REQUIRES_NEW, // 事务传播属性 isolation=Isolation.READ_COMMITTED,// 事务隔离级别 rollbackFor=Exception.class,// 异常回滚 unrollbackFor=IOException.class,// 异常不回滚 timeout=2, // 超时事务 readOnly=false)// 只读事务 |
属性 |
类型 |
描述 |
propagation |
枚举型:Propagation |
可选的传播性设置 |
isolation |
枚举型:Isolation |
可选的隔离性级别(默认值:ISOLATION_DEFAULT) |
readOnly |
布尔型 |
读写型事务 vs. 只读型事务。只读型事务一般用于查询。 |
timeout |
int型(以秒为单位) |
事务超时,如果在指定时间内没有完成事务,事务则回滚。 |
rollbackFor |
一组 Class 类的实例,必须是Throwable 的子类 |
一组异常类,遇到时 必须 进行回滚。默认情况下checked exceptions不进行回滚,仅unchecked exceptions(即RuntimeException的子类)才进行事务回滚。 |
rollbackForClassname |
一组 Class 类的名字,必须是Throwable的子类 |
一组异常类名,遇到时 必须 进行回滚 |
noRollbackFor |
一组 Class 类的实例,必须是Throwable 的子类 |
一组异常类,遇到时 必须不 回滚。 |
noRollbackForClassname |
一组 Class 类的名字,必须是Throwable 的子类 |
一组异常类,遇到时 必须不 回滚 |
使用XML文件配置Spring事务:
<tx:advice id="testTransaction" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="methodName" propagation="REQUIRED" read-only="false" rollback-for="Expetion" timeout="2" isolation="READ_COMMITTED" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* cn.itcast.cc.spring.transaction.*.*(..))" id="aopTransaction" /> <aop:advisor advice-ref="testTransaction" pointcut-ref="aopTransaction" /> </aop:config> |
二、Spring整合Hibernate
Spring支持大多数流行的ORM框架,包括HibernateJDO,TopLink,Ibatis和JPA。它这些ORM框架的支持是一致的,因此可以把和Hibernate整合技术应用到其他ORM框架上。Spring2.0同时支持Hibernate2.x和3.x。但Spring2.5只支持Hibernate3.1或更高版本
1.在Spring中配置SessionFactory
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> </bean> |
其中的DataSource是我们在第一天就讲到的使用外部Bean配置数据源。
虽然我们使用的数据源是一个Bean,它涉及到Hibernate私有配置的信息被声明在“hibernate.cfg.xml”文件中。但现在我们可以这个外在的“hibernate.cfg.xml”文件,我们需要在上面的baen中添加:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> <property name="mappingResources"> <list> <value>cn/itcast/spring/hibernate/Customer.hbm.xml</value> </list> </property> </bean> |
OK,SessionFactory已经被我们整合进来了!十分简单,跟其他的类一样。
还记得我们昨天使用的JdbcTemplate吗?那是Spring为JDBC提供的支持,Spring也有为Hibernate提供支持:
支持类 |
JDBC |
Hibernate |
模板类 |
JdbcTemplate |
HibernateTemplate |
DAO支持类 |
JdbcDaoSupport |
HibernateDaoSupport |
事务管理类 |
DataSourceTransactionManager |
HibernateTransactionManager |
使用HibernateTemplate,需要声明一个Bean:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory"/> </bean> |
DAO支持类对我们来说比较陌生,HibernateDAO可以通过继承HibernateDaoSupport来继承setSessionFactory()和setHibernateTemplate()方法。然后,只要在DAO方法中调用getHibernateTemplate()方法就可以获取到模板实例。
三、Spring整合Struts1.x
1.通过注册Servlet监听器ContextLoaderListener,Web应用程序可以加载Spring的ApplicationContext对象。这个监听器会将加载好的ApplicationContext对象保存到Web应用程序的ServletContext中。随后,Servlet或可以访问ServletContext的任意对象就能通过一个辅助方法来访问Spring的应用程序上下文了。
<context-param> <param-name>contextConfigFile</param-name> <param-value>beans.xml</param-value> </context-param> <listener> <listener-class>cn.itcast.cc.spring.SpringServletContextListener</listener-class> </listener> |
在SpringServletContextListener的contextInitialized方法中:
public void contextInitialized(ServletContextEvent arg0) { String cfgFile = arg0.getServletContext().getInitParameter("contextConfigFile"); ApplicationContext ac = new ClassPathXmlApplicationContext(cfgFile); arg0.getServletContext().setAttribute("applicationContext", ac); } |
以后在Action中需要使用SpringIOC容器中的Bean时,就可以先到ServletContext中去获取ApplicationContext,然后再获取相应的Bean。
2.在web.xml文件中注册Spring提供的Servlet监听器ContextLoaderListener,它会在当前web应用被加载时将Spring的ApplicationContext保存到ServletContext对象中。
ContextLoaderListener监听器通过查找web应用初始化参数contextConfigLocation来获取Bean配置文件的位置。如果有多个Bean配置文件,可以通过逗号或空格进行分隔。contextConfigLocation的默认值为/WEB-INF/applicationContext.xml。若实际的文件和默认值一致则可以省略这个web应用的初始化参数。
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:beans.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> |
在需要Bean的Action或Servlet中获取Bean的方法:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()); ac.getBean("beanName"); } |
3.通过注册Servlet监听器ContextLoaderListener,Struts应用程序能够加载Spring的ApplicationContext对象,并像在通用的Web应用程序中那样在Servlet上下文中对它进行访问。然而,Spring还提供了更好的,特定于Struts的解决方案。
-
在struts配置文件中注册Struts插件来加载应用程序上下文,它会自动引用Servlet监听器加载的应用程序上下文作为它的父上下文,以便可以引用其中声明的Bean。
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="classpath:struts-config.xml,classpath:beans.xml" />
</plug-in>
Spring提供了一个ActionSupport对象,这是Action类的一个子类,通过它的getWebApplicationContext()方法可以获取到Spring的应用程序上下文。
public class LoginAction extends ActionSupport { @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { ApplicationContext ac = this.getWebApplicationContext(); HelloSpring hs = (HelloSpring) ac.getBean("helloSpring"); request.setAttribute("message", hs.hello("changcheng")); return mapping.findForward("success"); } } |
-
在spring的应用程序上下文中声明Struts的Action对象,使用Spring的依赖注入来注入Spring应用程序上下文的其他Bean。
我们的Action类:
public class LoginAction extends Action { private HelloSpring helloSpring; public void setHelloSpring(HelloSpring hs) { this.helloSpring = hs; System.out.println("*****注入*****:" + this.helloSpring); } @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { request.setAttribute("message", this.helloSpring.hello("changcheng")); return mapping.findForward("success"); } } |
在struts-config.xml中将的Action配置为:
<action-mappings> <action path="/login"> <forward name="success" path="/success.jsp" /> </action> </action-mappings> <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor" /> |
在beans.xml中配置:
<bean id="helloSpring" class="cn.itcast.cc.spring.struts.hello.HelloSpring" /> <bean name="/login" class="cn.itcast.cc.spring.struts.action.LoginAction"> <property name="helloSpring" ref="helloSpring"/> </bean> |
这种方法也需要“1)”的plug-in。
四、SSH整合(Spring、Struts1.x、Hibernate)
将上面的二和三放到一起就是SSH整合,佟老师使用一个使用注册的例子演示SSH整合。我只简单说一下思想吧!
1).创建动态WEB工程。
2).在web.xml添加spring的“ContextLoaderListener”监听器和Struts的ActionServlet。
3).在Spring的配置文件中引入数据源和Hibernate的SessionFactory和HibernateTransactionManager。
4).为struts添加spring的“DelegatingRequestProcessor”控制器。
5).为Action、Service、Dao添加Spring的AOP注解。
Spring结束了就是教育办公系统了,这个十分重要,要好好学习!