Java全栈开发Spring学习第三天

时间:2022-05-04
本文章向大家介绍Java全栈开发Spring学习第三天,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

今日内容

l Spring的事务管理

l 三大框架整合

1.1 上次课内容回顾:

Spring整合WEB项目:

* 需要配置一个监听器:ContextLoaderListener

* 配置全局初始化参数:

Spring的AOP的开发:

* AOP的概述:

* AOP:面向切面编程,是OOP的扩展.解决OOP开发中一些问题.

* AOP的术语:

* 连接点:可以被拦截到点.

* 切入点:真正被拦截到的点.

* 通知:增强的功能代码.

* 引介:

* 目标:被增强的类.

* 织入:将通知应用到目标的过程.

* 代理:被增强的对象织入了通知后,产生一个代理对象.

* 切面:多个切入点和多个通知的组合.

* Spring的传统的AOP的开发:

* 基于ProxyFactoryBean方式:

* 需要为每个被代理的对象,配置ProxyFactoryBean.

* 基于BeanPostProcessor的自动代理:

* 区别:

* ProxyFactoryBean :先有目标对象,将目标传给代理对象.

* BeanPostProcessor :在类产生过程中,就已经是代理对象.

* Spring的基于AspectJ的AOP的开发:

* 注解:

* @Aspect:

* 通知:

* @Before:

* @AfterReturing

* @AfterThrowing

* @Around

* @After

* 切入点:

* @Pointcut

* XML:

* <aop:config>

<aop:pointcut id=”” expression=””/>

<aop:aspect ref=””>

<aop:before method=”” pointcut-ref=””/>

</aop>

</aop:config>

Spring的JdbcTemplate:

* 连接池的配置:

* CRUD的操作:

1.2 Spring的事务管理:

1.2.1 回顾事务:

什么是事务:

事务是逻辑上一组操作,这组操作要么全都成功,要么全都失败.

事务特性:

原子性:

一致性:

隔离性:

持久性:

1.2.2 Spring的事务管理:

Spring的事务管理的分类:

一类:编程式事务管理.手动编写代码管理事务.

二类:声明式事务管理.通过配置完成事务管理.(AOP)

Spring管理事务的API:

PlatformTransactionManager :平台事务管理器

* 是真正管理事务的对象.

TransactionDefinition :事务定义信息.

* 定义事务的(隔离级别,传播行为,超时信息,只读)

TransactionStatus :事务状态.

* 管理事务的过程中,事务有一些状态的改变.状态信息被记录在该对象中.

Spring根据TransactionDefinition中定义的信息使用PlatformTransactionManager管理事务,管理事务过程中产生状态,将状态记录到TransactionStatus中.

Spring的事务管理的详解

PlatformTransactionManager

TransactionDefinition

常量:

* ISOLATION_*:定义事务的隔离级别.

* PROPAGATION_*:定义事务的传播行为.

* 超时信息:

方法:

TransactionStatus:事务状态

Spring的事务传播行为:

PROPAGATION_REQUIRED :如果A,B操作,如果A有事务使用A的事务将B包含进来.如果A没有事务创建一个新事务将A,B包进来.

PROPAGATION_SUPPORTS :如果A,B操作,如果A有事务,使用A的事务将B包含进来.如果A没有事务,不使用事务.

PROPAGATION_MANDATORY :如果A,B操作,如果A有事务,使用A的事务将B包含进来.如果A没有事务,就会抛出异常.

PROPAGATION_REQUIRES_NEW :如果A,B操作,如果A有事务,将A的事务挂起.创建一个新事务执行B操作.

PROPAGATION_NOT_SUPPORTED :如果A,B操作,总是以非事务方式运行,如果A有,将A挂起.

PROPAGATION_NEVER :如果A,B操作,总是以非事务方式运行,如果A有事务抛出异常.

PROPAGATION_NESTED :嵌套事务.如果A,B操作,A有事务,在A执行完之后设置一个保存点.如果B执行没有问题,一起提交.如果B出现问题.允许用户自己控制回滚到最初还是回滚到保存点.

1.2.3 Spring的事务管理的环境的搭建:

步骤一:创建表:

CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`money` double DEFAULT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

步骤二:创建一个WEB工厂,引入相应jar包:

步骤三:创建包结构:

步骤四:引入配置文件:

* log4j.properties

* jdbc.properties

* applicationContext.xml

步骤五:在Spring配置文件中配置Service和DAO:

<!-- 配置Service -->
<beanid="accountService"class="cn.itcast.service.AccountServiceImpl">
<propertyname="accountDao" ref="accountDao"/>
</bean>
<!-- 配置DAO -->
<beanid="accountDao"class="cn.itcast.dao.AccountDaoImpl">
<propertyname="dataSource"ref="dataSource"/>
</bean>

步骤六:编写业务层和DAO中的方法的代码:

DAO中代码:

@Override
publicvoid outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money = money - ? where name = ?", money,from);
}
@Override
publicvoid inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money = money + ? where name = ?", money,to);
}
Service的代码:
@Override
/**
* 业务层转账的方法:
* from:转出账号
* to:转入账号
* money:转账金额
*/
publicvoid transfer(String from, String to, Double money) {
this.accountDao.outMoney(from, money);
this.accountDao.inMoney(to, money);
}

步骤七:编写测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
publicclass SpringDemo1 {
@Resource(name="accountService")
private AccountService accountService;
@Test
publicvoiddemo1(){
accountService.transfer("老马", "凤姐", 1000d);
}
}

1.2.4 Spring的编程式事务管理(了解)

步骤一:在Spring中配置一个事务管理器:

<!-- 配置事务管理器 -->
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"/>
</bean>

步骤二:配置事务管理的模板:

<!-- 配置事务管理的模板 -->
<beanid="transactionTemplate"class="org.springframework.transaction.support.TransactionTemplate">
<propertyname="transactionManager"ref="transactionManager"/>
</bean>

步骤三:在业务层类中注入事务管理的模板:

<!-- 配置Service -->
<beanid="accountService"class="cn.itcast.transaction.demo1.service.AccountServiceImpl">
<propertyname="accountDao"ref="accountDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>

步骤四:在事务管理的地方编写代码:

publicvoid transfer(final String from, final String to, final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protectedvoid doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(from, money);
intd = 1 / 0;
accountDao.inMoney(to, money);
}
});
}

1.2.5 Spring的声明式事务管理:基于TransactionProxyFactoryBean

步骤一:恢复转账环境:

步骤二:配置事务管理器:

<!-- 配置事务管理器 -->
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"></property>
</bean>

步骤三:配置产生业务层的代理对象(AOP)

引入AOP开发包:

<!-- 配置产生代理对象 -->
<beanid="accountServiceProxy"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<propertyname="target"ref="accountService"/>
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="transactionAttributes">
<props>
<!-- 格式:PROPAGATION,ISOLATION,readOnly,-Exception,+Exception -->
<propkey="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>

步骤四:编写测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
publicclass SpringDemo2 {
@Resource(name="accountServiceProxy") // 注入代理对象
private AccountService accountService;
@Test
publicvoid demo1(){
accountService.transfer("老马", "凤姐", 1000d);
}
}

1.2.6 Spring的声明式事务管理:基于AspectJ的XML方式的事务管理

步骤一:恢复开发环境:

步骤二:引入aspectj的开发包:

步骤三:配置事务管理器:

<!-- 配置事务管理器 -->
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"/>
</bean>

步骤四:配置增强:

<!-- 配置事务增强 -->
<tx:adviceid="txAdvice"transaction-manager="transactionManager">
<tx:attributes>
<!--
propagation:事务传播行为:
isolation:隔离级别
read-only:是否为只读事务.
timeout :是否超时.
rollback-for:类似-Exception.发生哪些异常回滚事务.
no-rollback-for:类似+Exception.发生哪些异常不回滚.
-->
<tx:methodname="transfer"propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>

步骤五:配置AOP:

<!-- AOP的配置 -->
<aop:config>
<aop:pointcutexpression="execution(* cn.itcast.transaction.demo3.service.AccountServiceImpl.*(..))"id="pointcut1"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="pointcut1"/>
</aop:config>

步骤六:编写测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
publicclass SpringDemo3 {
@Resource(name="accountService")
private AccountService accountService;
@Test
publicvoid demo1(){
accountService.transfer("老马", "凤姐", 1000d);
}
}

1.2.7 Spring的声明式事务管理:基于AspectJ注解的声明式事务管理

步骤一:恢复开发环境:

步骤二:配置事务管理器:

<!-- 配置事务管理器 -->
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"/>
</bean>

步骤三:开启注解事务:

<!-- 开启注解事务 -->
<tx:annotation-driventransaction-manager="transactionManager"/>

步骤四:在业务层添加一个注解@Transactional

注解的属性:

* @Transactional中属性

* propagation:传播行为.

* readOnly:是否只读

* timeout:超时信息

* isolation:隔离级别

1.2.8 Spring的事务管理的总结:

Spring将事务管理分成两类:

* 编程式事务管理:

* 使用事务管理模板的方式.需要手动编写代码.

* 声明式事务管理:

* 基于TransactionProxyFactoryBean的方式:

* 需要为每个进行事务管理的类,都去配置一个TransactionProxyFactoryBean.

* 基于AspectJ的XML的方式:

* 基于AspectJ的注解的方式:

1.3 SSH整合:

1.3.1 SSH框架整合方式一:

步骤一:创建WEB项目,引入相应的jar包:

Struts2框架:

* Struts2_HOME/apps/struts2-blank.war

Struts2需要了解的jar

struts2-json-plugin-2.3.15.3.jar :Struts2整合AJAX的开发包.

struts2-spring-plugin-2.3.15.3.jar:Struts2和Spring整合的jar包.

struts2-convention-plugin-2.3.15.3.jar:Struts2注解开发包.

Hibernate3框架:

* Hibernate_HOME/hibernate3.jar

* Hibernate_HOME/lib/required/*.jar

* Hibernate_HOME/lib/jpa/*.jar

* slf4j-log4j.jar

* 数据库驱动.

* C3P0连接池:

Spring3框架:

Spring3.2 开发最基本jar包

spring-beans-3.2.0.RELEASE.jar
spring-context-3.2.0.RELEASE.jar
spring-core-3.2.0.RELEASE.jar
spring-expression-3.2.0.RELEASE.jar
com.springsource.org.apache.commons.logging-1.1.1.jar
com.springsource.org.apache.log4j-1.2.15.jar

AOP开发

spring-aop-3.2.0.RELEASE.jar

spring-aspects-3.2.0.RELEASE.jar

com.springsource.org.aopalliance-1.0.0.jar

com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

Spring Jdbc开发

spring-jdbc-3.2.0.RELEASE.jar

spring-tx-3.2.0.RELEASE.jar

Spring事务管理

spring-tx-3.2.0.RELEASE.jar

Spring整合其他ORM框架

spring-orm-3.2.0.RELEASE.jar

Spring在web中使用

spring-web-3.2.0.RELEASE.jar

Spring整合Junit测试

spring-test-3.2.0.RELEASE.jar

步骤二:引入配置文件:

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>
* struts.xml

Hibernate框架的配置文件:

* hibernate.cfg.xml

* 映射文件.

Spring框架的配置文件:

* web.xml
<!-- Spring的核心监听器 -->
<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>
* applicationContext.xml
* log4j.properties

步骤三:创建包结构:

步骤四:创建一个页面.

<h1>商品添加页面</h1>
<s:formmethod="post"action=""namespace="/"theme="simple">
<TABLEborder="1"width="600">
<TR>
<TD>商品名
<TR>称</TD>
<TD><s:textfieldname="pname"/></TD>
</TR>
<TD>商品价格</TD>
<TD><s:textfieldname="price"/></TD>
</TR>
<TR>
<TDcolspan="2"><INPUTTYPE="submit"value="添加"></TD>
</TR>
</TABLE>
</s:form>

步骤五:创建Action,Service,DAO,Domain类对象:

Action类:

publicclassProductActionextends ActionSupport implementsModelDriven<Product>{
// 模型驱动使用的对象
private Product product = new Product();
@Override
public Product getModel() {
returnproduct;
}
/**
* 保存商品执行的方法:save
*/
publicString save(){
System.out.println("保存商品的WEB层代码执行了...");
returnNONE;
}
}

步骤六:配置Action(Struts2和Spring进行整合)

Struts2和Spring进行整合两种方式:

* 第一种配置方式:Action类由Struts2自身创建.

1.配置Action的类

<packagename="ssh"extends="struts-default"namespace="/">
<actionname="product_*"class="cn.itcast.ssh.web.ProductAction"method="{1}">
</action>
</package>

2.配置业务层的类:

<!-- 配置业务层的类 -->
<beanid="productService"class="cn.itcast.ssh.service.ProductService">
</bean>

3.传统的方法:在Action中获得业务层类:

// 执行业务层类:
WebApplicationContext applicationContext = WebApplicationContextUtils
.getWebApplicationContext(ServletActionContext
.getServletContext());
ProductService productService = (ProductService) applicationContext
.getBean("productService");

4.引入了一个struts2-spring-plugin-2.3.15.3.jar

* 开启一个常量:<constant name="struts.objectFactory" value="spring" />

* 这个常量的开启导致下面这个常量生效:

--让Action按名称完成自动注入.

5.在Action中对Service提供一个set方法即可.

* 第二种配置方式Action类交给Spring管理创建.(推荐.)

1.将Action的创建配置到Spring中

<!-- 配置Action的类 -->
<beanid="productAction"class="cn.itcast.ssh.web.ProductAction">
</bean>

2.在struts.xml中进行如下配置:

<packagename="ssh"extends="struts-default"namespace="/">
<actionname="product_*"class="productAction"method="{1}">
</action>
</package>

3.需要在Spring创建Action时候配置为多例.

* scope=”prototype”

4.一旦将Action交给Spring管理.属性必须手动注入.

<!-- 配置Action的类 -->
<beanid="productAction"class="cn.itcast.ssh.web.ProductAction"scope="prototype">
<property name="productService" ref="productService"/>
</bean>

步骤七:在业务层调用DAO:

DAO配置到Spring中.并且完成在业务层的注入.

<!-- 配置业务层的类 -->
<beanid="productService"class="cn.itcast.ssh.service.ProductService">
<property name="productDao" ref="productDao"/>
</bean>
<!-- 配置DAO -->
<beanid="productDao"class="cn.itcast.ssh.dao.ProductDao">
</bean>

步骤八:创建映射文件

创建实体和映射:

<hibernate-mapping>
<class name="cn.itcast.ssh.domain.Product"table="product">
<id name="pid"column="pid">
<generator class="native"/>
</id>
<property name="pname"column="pname"length="20"/>
<property name="price"column="price"/>
</class>
</hibernate-mapping>

在核心配置中引入映射文件:

步骤九:Spring整合Hibernate:

<!-- 整合Hibernate -->
<beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>

在DAO中继承HibernateDaoSupport类

<!-- 配置DAO -->
<beanid="productDao"class="cn.itcast.ssh.dao.ProductDao">
<property name="sessionFactory"ref="sessionFactory"/>
</bean>

步骤十:在DAO中调用模板完成保存操作:

publicvoid save(Product product) {
System.out.println("保存商品的DAO层代码执行了...");
this.getHibernateTemplate().save(product);
}

步骤十一:事务管理:

<!-- 配置事务管理器 -->
<beanid="transactionManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driventransaction-manager="transactionManager"/>

在Service上添加一个@Transactional

1.3.2 SSH框架整合方式二:

步骤一:复制之前web项目

步骤二:去掉Hibernate的配置文件:

Hibernate.cfg.xml中的配置的内容:

1.数据库连接基本属性:

2.数据库连接池:

3.hibernate的属性:

4.映射文件:

去掉连接池和数据库基本参数:

<!-- 引入属性文件 -->
<context:property-placeholderlocation="classpath:jdbc.properties"/>
<!-- 配置C3P0连接池 -->
<beanid="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource">
<propertyname="driverClass"value="${jdbc.driverClass}"/>
<propertyname="jdbcUrl" value="${jdbc.url}"/>
<propertyname="user" value="${jdbc.user}"/>
<propertyname="password" value="${jdbc.password}"/>
</bean>

去掉Hibernate的属性和映射:

<!-- 整合Hibernate -->
<beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="dataSource"ref="dataSource"/>
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<propkey="hibernate.show_sql">true</prop>
<propkey="hibernate.format_sql">true</prop>
<propkey="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
<propertyname="mappingResources">
<list>
<value>cn/itcast/ssh/domain/Product.hbm.xml</value>
</list>
</property>
</bean>

1.3.3 HibernateTemplate的使用:

常用的API:

Serializable save(Object entity)
void update(Object entity)
void delete(Object entity)
<T> T get(Class<T> entityClass, Serializable id)
<T> T load(Class<T> entityClass, Serializable id)
List find(String queryString, Object... values)
List findByCriteria(DetachedCriteria criteria)
List findByNamedQuery(String queryName, Object... values)

1.3.4 延迟加载问题的解决:OpenSessionInViewFilter的使用:

分析如何出现延迟加载问题:

见图三

解决方案:

<!-- 延迟加载问题的过滤器 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>