今日的三大主要內容: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結束了就是教育辦公系統了,這個十分重要,要好好學習!