Spring框架

来源:互联网 发布:免费手机录音软件 编辑:程序博客网 时间:2024/06/06 11:42

spring框架

1 概述

spring就是一个大工厂。

创建和维护和管理JavaBean对象。

spring整个过程中负责组装的作用。

spring是一个IoC 和 AOP 的容器。

 

1 IoC 控制反转

2 AOP 面向切面编程

3 容器 管理对象的生命周期

 

2 体系结构

3 第一个Spring小案例

public class Goods {

     @Override

     public String toString() {

         return "这是Goods类的ToString!";

     }

}

     public staticvoid main(String[]args) {

         ApplicationContext context = new ClassPathXmlApplicationContext(

                   "applicationContext.xml");

         Goods goods = (Goods) context.getBean("goods");

         System.out.println(goods);

     }

4 Spring容器

     Spring容器就是一个管理JavaBean的一个工厂。

     基于BeanFactory类。在SpringCore中最核心的工厂类。

     现在开发时,使用ApplicationContext这个是BeanFactory的子类。

4.1 ApplicationContext。

     ApplicationContext是应用程序上下文,就是Spring容器对象。

     由Spring整理的所有javabean由ApplicationContext对象获得。

4.2 applicationContext.xml文件

     是Spring的核心配置文件,所有由Spring容器管理的对象都在这个文件中配置。

     当创建Spring容器(ApplicationContext)时要加载这个配置文件。

4.3 获得Spring容器对象

     使用ClassPathXmlApplicationContext类创建Spring容器对象。

4.4 ClassPathXmlApplicationContext

     基于类路径查询xml文件创建ApplicationContext类实例的工厂。

4.5 获得ApplicationContext对象

ApplicationContext context = newClassPathXmlApplicationContext("applictionContext.xml");

4.6 从容器对象中取JavaBean

     调用ApplicationContext对象的getBean方法,从配置文件中获取JavaBean对象

 

5 ApplicationContext.xml文件

<beans>

     <bean>这个bean的标记就是一个JavaBean的实例。

</beans>

5.1 bean标记一些属性

<bean id="goods" class="com.no8.domain.Goods"/>

     1class : 表示JavaBean的类名

     2 id : 表示JavaBean的实例的标识。

<bean name="goods" class="com.no8.domain.Goods"/>

     3name : 表示JavaBean的实例的标识

id比name的规范更严格。在name中还可以使用一些符号(“/”)

<bean name="goods" class="com.no8.domain.Goods"scope="singleton"/>

     4scope :表示这个对象的实例特性。

         1singleton : 单例,表示整个应用只有一个实例。

         2prototype : 原型,多例。每调用一次就是一个新的对象

当使用Spring整合struts2的Action时,一定要做成多例的。

 

6 IoC/DI

依赖注入(Dependency Injection)/控制反转(Inversion of Control)

6.1 第一版:

public class GoodsDAO {

     public void save(){

         System.out.println("GoodsDAO.save()");

     }

}

public class GoodsService {

     private GoodsDAO goodsDAO = new GoodsDAO();

     public void save(){

         System.out.println("GoodsSerivce.save()");

         goodsDAO.save();

     }

}

     public staticvoid main(String[]args) {

         GoodsService goodsService = new GoodsService();

         goodsService.save();

     }

在GoodsService类中写死了依赖于哪个DAO。

GoodsService这个类使用哪个DAO是这个类自己说了算。控制权在GoodsService手里。

问题:以后修改DAO的依赖对象,只能修改源文件。

这个叫主动获取。

6.2 第二版:

public interface IDAO {

     public void save();

}

public class GoodsDAO implements IDAO {

     public void save(){

         System.out.println("GoodsDAO.save()");

     }

}

public class GoodsService {

     private IDAO idao;

     public void save(){

         System.out.println("GoodsSerivce.save()");

         idao.save();

     }

     public IDAO getIdao() {

         return idao;

     }

     public void setIdao(IDAOidao) {

         this.idao =idao;

     }

}

     public staticvoid main(String[]args) {

         GoodsDAO goodsDAO = new GoodsDAO();

         GoodsService goodsService = new GoodsService();

         goodsService.setIdao(goodsDAO);//依赖注入

         goodsService.save();

     }

在GoodsService类中没有指明使用哪个DAO。只是制定了接口,

GoodsService这个类,使用哪个DAO说了不算。控制权不在GoodsService手里,在使用GoodsSerice这个类的方法手里。

 

 

控制权从在GoodsSerivce手里到不在手里的过程叫控制反转。

因为控制权现在外部容器,所以外部容器要想调用GoodsSerivce方法就必须注入一个依赖对象(DAO)

将DAO设置到Service的过程叫依赖注入。

goodsService.setIdao(goodsDAO);//依赖注入

7 使用Spring实现依赖注入_基于XML文件

public interface IDAO {

     public void save();

}

public class GoodsDAO implements IDAO {

     public void save(){

         System.out.println("GoodsDAO.save()");

     }

}

public class GoodsService {

     private IDAO idao;

     public void save(){

         System.out.println("GoodsSerivce.save()");

         idao.save();

     }

     public IDAO getIdao() {

         return idao;

     }

     public void setIdao(IDAOidao) {

         this.idao =idao;

     }

}

     <bean name="goodsDAO" class="com.no8.dao.GoodsDAO"/>

    

     <bean name="goodsSerivce" class="com.no8.service.GoodsService">

         <!-- <property name="idao" ref="goodsDAO"></property> -->

         <propertyname="idao">

              <refbean="goodsDAO"/>

         </property>

     </bean>

     public staticvoid main(String[]args) {

         ApplicationContext context = new ClassPathXmlApplicationContext(

                   "applicationContext.xml");

         GoodsService service = (GoodsService)context.getBean("goodsSerivce");

         service.save();

     }

8 使用Spring注解

8.1引入context命名空间

<beansxmlns="http://www.springframework.org/schema/beans"

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xmlns:p="http://www.springframework.org/schema/p"

     xmlns:context="http://www.springframework.org/schema/context"

     xmlns:aop="http://www.springframework.org/schema/aop"

     xsi:schemaLocation="http://www.springframework.org/schema/aop

         http://www.springframework.org/schema/aop/spring-aop-4.1.xsd

         http://www.springframework.org/schema/beans

         http://www.springframework.org/schema/beans/spring-beans-4.1.xsd

         http://www.springframework.org/schema/context

         http://www.springframework.org/schema/context/spring-context-4.1.xsd">

8.2 注册注解的后台处理类

<context:annotation-config/>

8.3 指明注解扫描的包

<context:component-scanbase-package="com.no8.service,com.no8.dao"/>

8.4 类的注解

@Controller("value") 控制器层

@Service("value") 业务层

@Repository("value") 数据访问层

@Component("value") 通用

@Scope("prototype") 表示多例模式

8.5 依赖注入的注解

@Autowired 按类型自动装配

@Qualifier(“依赖对象”) 按名字自动装配

@Repository("GoodsDAO")

public class GoodsDAOimplements IDAO {

     public void save(){

         System.out.println("GoodsDAO.save()");

     }

}

@Service("GoodsService")

@Scope("prototype")

public class GoodsService {

     @Autowired @Qualifier("GoodsDAO")

     private IDAO idao;

     public void save() {

         System.out.println("GoodsSerivce.save()");

         idao.save();

     }

     public IDAO getIdao() {

         return idao;

     }

     public void setIdao(IDAOidao) {

         this.idao =idao;

     }

}

 

public staticvoid main(String[]args) {

     ApplicationContext context = new ClassPathXmlApplicationContext(

              "applicationContext.xml");

     GoodsService goodsService = (GoodsService)context.getBean("GoodsService");

     goodsService.save();

}

9 AOP

     面向方面编程,面向切面编程

     切面:切开的面就是切面。

现在开发环境比较复杂,很多业务还要有服务的方法

     保存业务

         事务,日志,权限

     删除业务

         事务,日志,权限

     修改业务

         事务,日志,权限

真实开发环境时业务之间经常性有交叉。

开发时理想状态:每个人只做自己的事情。

真正执行保存业务时,不能只有保存业务,必须还要加入权限,事务,日志等这些服务业务。

在Spring中这个工厂里自动实现将服务业务代码以切面的方式加入到业务代码中。

 

10 代理模式

     代理:自己不想做,让别人帮你做。

     代理模式:在一个原有功能基础上添加新的功能。

     代理模式:静态代理和动态代理

11 静态代理

1 版本一:所有代码全部写在一个方法中

public class GoodsService {

     public void save() {

         try {

              System.out.println("事务开始");

              System.out.println("save业务方法");

              System.out.println("事务提交");

         } catch (Exception e) {

              e.printStackTrace();

              System.out.println("事务回滚");

         }

     }

}

2 版本二:基于类的静态代理

     将事务代码分离。

     保存让业务代码只有业务方法

public class GoodsService {

     public voidsave() {

         System.out.println("save业务方法");

     }

}

public class ProxyGoodsServiceextends GoodsService {

     @Override

     public void save() {

         try {

              System.out.println("事务开始");

              super.save();

              System.out.println("事务提交");

         } catch (Exception e) {

              System.out.println("事务回滚");

         }

     }

}

public class Test {

     public static void main(String[] args) {

         // TODO Auto-generated method stub

         GoodsService goodsService = new ProxyGoodsService();

         goodsService.save();

     }

}

3 版本三:基于接口的静态代理

     为业务方法创建一个接口。通过接口来暴露被代理的方法。

public interface Service {

     public void save() ;

}

     代理类和被代理类都实现同一个接口。

public class GoodsServiceimplements Service {

     public void save() {

         System.out.println("save业务方法");

     }

}

public class ProxyTranServiceimplements Service

     在代理类中如何确定被代理的对象?将接口做为代理类的属性,这个属性就是被代理对象。

public class ProxyTranServiceimplements Service {

     private Service service;//被代理对象

     @Override

     public void save() {

         try {

              System.out.println("事务开始");

              service.save();

              System.out.println("事务提交");

         } catch (Exception e) {

              System.out.println("事务回滚");

         }

     }

     public Service getService() {

         return service;

     }

     public void setService(Serviceservice) {

         this.service =service;

     }

}

4 版本4:提出方面代码,做为AOP接口。

     问题1:在一个业务代码中,有几个位置可以以切面的方式加入方面代码?

     有四个,之前(before) ,之后(after) ,异常(exception),最终(finally)

创建一个切面的接口。AOP

public interface AOP {

     public void before();

     public void after();

     public void execption();

     public void finaly();

}

编写一个事务的切面类

public class TranAOP implements AOP {

     @Override

     public void before() {

         System.out.println("开始事务");

     }

     @Override

     public void after() {

         System.out.println("提交事务");

     }

     @Override

     public void execption() {

         System.out.println("回滚事务");

     }

     @Override

     public void finaly() {

     }

}

编写代理类。代理业务和切面,将业务和切面纺织到一起。

public class ProxyAOPSerivceimplements Service{

     private Service serivce;//被代理对象

     private AOP aop;//加入切面代码

     public ProxyAOPSerivce(Service serivce, AOP aop) {

         super();

         this.serivce =serivce;

         this.aop =aop;

     }

     @Override

     public void save() {

         try{

              this.aop.before();

              this.serivce.save();

              this.aop.after();

         }catch(Exception e){

              e.printStackTrace();

              this.aop.execption();

              throw new RuntimeException(e);

         }finally{

              this.aop.finaly();

         }

     }

测试类

     public staticvoid main(String[]args) {

         // TODO Auto-generated method stub

         Service tranService = new ProxyAOPSerivce(

                   new GoodsService(),

                   new TranAOP());

         tranService.save();

     }

     public staticvoid main(String[]args) {

         Service tranService = new ProxyAOPSerivce(

                   new GoodsService(),

                   new TranAOP());

         tranService.save();

         System.out.println("---------");

         Service logService = new ProxyAOPSerivce(

                   tranService,

                   new LogAOP());

         logService.save();

     }

 

12 动态代理

     静态代理:针对接口编写代理类。代理类一定存在。

     动态代理:程序运行时,根据你要被代理对象动态生成的代理类。

     动态代理共两种:1 JDK动态代理 2 CGLIB动态代理

12.1 基于JDK动态代理

     1调用Proxy类的静态方法获得一个动态代理类的实例

    public static Object newProxyInstance(ClassLoaderloader,

                                          Class<?>[] interfaces,

                                          InvocationHandler h)

ClassLoader loader 类加载器,因为动态代理类不存在,借别人的类加载。一般情况下使用被代理对象的类加载器。

Class<?>[] interfaces 接口类对象的集合,针对接口的代理。针对哪个接口做代理。

一般情况使用被代理对象的接口

InvocationHandler h 句柄,回调函数。这里编写代理的规则代码。

     2InvocationHandler接口

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

Object proxy 代理对象

Method method 反射类,表示是一个方法,被代理的方法。

Object[] args 被代理方法执行时的参数的数组。

     3测试类

     public staticvoid main(String[]args) {

         GoodsService goodsService = new GoodsService();

         // 使用JDK的动态代理将事务加进入

         Service service = (Service) Proxy.newProxyInstance(

                   goodsService.getClass().getClassLoader(),

                   goodsService.getClass().getInterfaces(),

                   new InvocationHandler() {

              @Override

              public Object invoke(Object proxy, Method method, Object[] args)

                       throws Throwable {

                   try {

                       System.out.println("事务开始");

                       Object o = method.invoke(goodsService, args);

                       System.out.println("事务提交");

                       return o;

                   } catch (Exception e) {

                       e.printStackTrace();

                       System.out.println("事务回滚");

                       throw e;

                   } finally{

                      

                   }

              }

         });

         service.save();

         System.out.println(service.getClass().getName());

     }

12.2 基于JDK动态代理的结构设计

public class ProxyHandlerimplements InvocationHandler {

     private Object obj;// 被代理对象

     private AOP aop;// 方面代码

     public ProxyHandler(Object obj, AOP aop) {

         super();

         this.obj =obj;

         this.aop =aop;

     }

     @Override

     public Object invoke(Object proxy, Method method, Object[] args)

              throws Throwable {

         try {

              aop.before();

              Object o = method.invoke(obj, args);

              aop.after();

              return o;

         } catch (Exception e) {

              e.printStackTrace();

              aop.execption();

              throw e;

         } finally {

              aop.finaly();

         }

     }

}

     public staticvoid main(String[]args) {

         GoodsService goodsService = new GoodsService();

         TranAOP tranAOP = new TranAOP();

 

         Service proxyService = (Service) Proxy.newProxyInstance(goodsService

                   .getClass().getClassLoader(), goodsService.getClass()

                   .getInterfaces(), new ProxyHandler(goodsService,tranAOP));

        

         boolean bool = proxyService.save();

         System.out.println(bool);

     }

12.3 基于JDK动态代理的Spring整合

     public staticvoid main(String[]args) {

         // TODO Auto-generated method stub

         ApplicationContext applicationContext =new ClassPathXmlApplicationContext(

                   "applicationContext.xml");

        

         Service proxyService = (Service) applicationContext.getBean("proxy");

         boolean bool = proxyService.save(3,"有钱人组员");

         System.out.println(bool);

     }

     <!-- GoodsService goodsService = new GoodsService();-->

     <bean id="goodsService" class="com.no8.proxy.no6.GoodsService"/>

     <!-- TranAOP tranAOP = new TranAOP(); -->

     <bean id="tranAOP" class="com.no8.proxy.no6.TranAOP"/>

     <bean id="logAOP" class="com.no8.proxy.no6.LogAOP"/>

     <!-- ProxyHandler proxyHandler = new ProxyHandler(goodsService, tranAOP); -->

     <bean id="proxyHandler" class="com.no8.proxy.no6.ProxyHandler">

         <constructor-argname="obj"ref="goodsService"/>

         <constructor-argname="aop"ref="logAOP"/>

     </bean>

     <!-- 使用实例类的实例方法创建对象 -->

     <!-- Class objClass = goodsService.getClass(); -->

     <bean id="objClass" factory-bean="goodsService" factory-method="getClass" />

     <!-- ClassLoader objClassLoader = objClass.getClassLoader(); -->

     <bean id="objClassLoader" factory-bean="objClass" factory-method="getClassLoader" />

     <!-- Class[] objInterfaces = objClass.getInterfaces(); -->

     <bean id="objInterfaces" factory-bean="objClass" factory-method="getInterfaces"/>

     <!-- 使用静态方法创建对象 -->

     <!-- Service proxy = (Service) Proxy.newProxyInstance(objClassLoader,

                   objInterfaces, proxyHandler); -->

     <bean id="proxy" class="java.lang.reflect.Proxy" factory-method="newProxyInstance">

         <constructor-argindex="0"ref="objClassLoader"/>

         <constructor-argindex="1"ref="objInterfaces"/>

          <constructor-argindex="2"ref="proxyHandler"/>

     </bean>

12.4 基于CGLIB动态代理

     1因为CGLIB是第三方的一个组件 ,所以我们想要使用时必须导入CGLIB的jar文件

     2使用Enhancer类的create静态方法创建动态代理类的对象

public static Object create(Class type,Callback callback);

Class type : 被代理的类的Class对象。CGLIB是可以实现对类进行代理

Callback callback : 回调函数。这里编写代理的规则代码。

     3Callback 回调函数,子接口。

     4MethodInterceptor : 这是回调函数Callback的一个子接口。表示是方法拦截器

public Object intercept(Object arg0, Method arg1, Object[] arg2,

                       MethodProxy arg3) throws Throwable

Object arg0 : 被代理对象

Method arg1 本次拦截的方法

Object[] arg2 本次拦截的方法执行时的参数

MethodProxy arg3 方法代理对象

     5先调用被代理方法的原功能

public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3)

     throws Throwable {

     Object o = arg3.invokeSuper(arg0, arg2);

     return o;

}

     6测试类

     public staticvoid main(String[]args) {

         // TODO Auto-generated method stub

         GoodsService goodsService = new GoodsService();

         GoodsService proxyGoodsService = (GoodsService) Enhancer.create(

                   goodsService.getClass(),new MethodInterceptor() {

                       @Override

                       public Object intercept(Objectarg0, Methodarg1,

                                 Object[] arg2, MethodProxyarg3)throws Throwable {

                            try {

                                 System.out.println("事务开始");

                                 Object o =arg3.invokeSuper(arg0,arg2);

                                 System.out.println("事务提交");

                                 return o;

                            } catch (Exceptione) {

                                 System.out.println("事务回滚");

                                 throw e;

                            } finally {

 

                            }

                       }

                   });

         proxyGoodsService.save(4, "郑春玲");

     }

12.5 基于CGLIB动态代理的结构设计

public class MyMethodInteceptoerimplements MethodInterceptor {

     private AOP aop;

     public MyMethodInteceptoer(AOP aop) {

         super();

         this.aop =aop;

     }

     @Override

     public Object intercept(Object arg0, Method arg1, Object[] arg2,

              MethodProxy arg3) throws Throwable {

         try{

              aop.before();

              Object obj = arg3.invokeSuper(arg0,arg2);

              aop.after();

              return obj;

         }catch(Exception e){

              aop.execption();

              throw e;

         }finally{

              aop.finaly();

         }

     }

}

     public staticvoid main(String[]args) {

         // TODO Auto-generated method stub

         GoodsService goodsService = new GoodsService();

         GoodsService proxyGoodsService = (GoodsService) Enhancer

                   .create(goodsService.getClass(),new MyMethodInteceptoer(

                            new TranAOP()));

         proxyGoodsService.save(4, "郑春玲");

 

     }

12.6 基于CGLIB动态代理的Spring整合

     <bean id="goodsService7" class="com.no8.proxy.no7.GoodsService"/>

     <bean id="tranAOP7" class="com.no8.proxy.no7.TranAOP"/>

     <bean id="methodInterceptor" class="com.no8.proxy.no7.MyMethodInteceptoer">

         <constructor-argname="aop"ref="tranAOP7"/>

     </bean>

     <bean id="objClass7" factory-bean="goodsService7"factory-method="getClass"/>

     <bean id="proxy7" class="net.sf.cglib.proxy.Enhancer"factory-method="create">

         <constructor-argindex="0"ref="objClass7"/>

         <constructor-argindex="1"ref="methodInterceptor"/>

     </bean>

     public staticvoid main(String[]args) {

         // TODO Auto-generated method stub

         ApplicationContext applicationContext =new ClassPathXmlApplicationContext(

                   "applicationContext.xml");

        

         GoodsService proxyService = (GoodsService)applicationContext.getBean("proxy7");

         boolean bool = proxyService.save(3,"有钱人组员");

         System.out.println(bool);

     }

 

13 Spring的基于AspectJ的Spring AOP配置

13.1 术语:

连接点(Joinpoint):在Spring中基本上都是一个方法。就是我们要做代理的方法。

通知(Advices):方面代码。

切入点(Pointcut):匹配连接点的断言。

13.2 通知类型:方面代码。

1前置通知(Beforeadvice @Before):在某连接点之前执行的通知,但这个通知不能阻止连接点之前的执行流程(除非它抛出一个异常)。

2后置通知(After returning advice @AfterReturning):在某连接点正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回。

3异常通知(After throwing advice @AfterThrowing):在方法抛出异常退出时执行的通知。

4最终通知(After(finally) advice @After):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。

5环绕通知(Around Advice @Around):包围一个连接点的通知,如方法调用。这是最强大的一种通知类型。环绕通知可以在方法调用前后完成自定义的行为。它也会选择是否继续执行连接点或直接返回它自己的返回值或抛出异常来结束执行。

13.3 创建工程导入AspectJ的AOP

13.4 编写被代理类,并导入Spring

配置文件的命名空间导入Context和aop

配置注解的后台处理类,和扫描的包

     <context:annotation-config/>

     <context:component-scan base-package="com.no8.service"/>

在类上加注解

@Service("GoodsService")

public class GoodsService  {

     public boolean save(intgoodsId,StringgoodsName)  {

         System.out.println("save业务方法");

         return false;

     }

 

     public void update(){

         System.out.println("update业务方法");

         throw new RuntimeException();

     }

}

13.5 编写一个切面类

     这就是一个普通的类。但是要加入一个注解@Aspect。

@Aspect

@Component("aop")

public class AOP {

 

}

13.6 编写一个切入点(pointcut)

在我们的类中就是一个方法。

     @Pointcut("execution (* com.no8.service..*.*(..))")

     public void pointCut(){}

execution 就是断言。表达式,表示在哪些类的哪些方法上可以有切面

* com.no8.service..*.*(..)

第一个*:表示任意类型的返回值

第一个.. 表示 com.no8.service这个包和所有子包

com.no8.service..*.* :表示 com.no8.service这个包和所有子包的所有类的所有方法

*.*(..) 表示所有类的所有方法中的所有参数类型

13.7 在Sprint为每一种通知都编写一个注解

编写一个前置通知的方面代码。

方面代码就是一个普通方法。

     @Before("pointCut()")

     public void before(){

         System.out.println("这是一个前置通知!");

     }

13.8 在ApplicationContext.xml文件中注册AspectJ的后台处理类

     <!-- 注册使用aspectj的注解方式实现动态代理的后台类

         proxy-target-class="true" 表示使用CGLIB方式完成代理 -->

     <aop:aspectj-autoproxy proxy-target-class="true"/>

13.9 测试

     public staticvoid main(String[]args) {

         // TODO Auto-generated method stub

         ApplicationContext context = new ClassPathXmlApplicationContext(

                   "applicationContext.xml");

        

         GoodsService goodsService =

                   (GoodsService) context.getBean("GoodsService");

 

         boolean bool = goodsService.save(1, "");

         System.out.println(bool);

        

         goodsService.update();

     }

13.10 连接点对象: joinPoint和ProceedingJoinPoint

     这个可能做为通知方法的参数。前,后,异常,最终通知都使用joinPoint

     环绕通知:ProceedingJoinPoint

 

14 使用Spring整合Hibernate

14.1 创建工程并导入框架

     我们推荐先导入Spring --> hibernate

     这个过程中也有二种情况:1 、保留hibernate.cfg.xml文件和2 不保留hibernate.cfg.xml文件

导入Spring框架时,选中ORM支持

导入Hibernate时。

放弃自己的HibernateSessionFactory,让Spring管理Hibernate中Session的创建。

14.2 使用Spring整合Hibernate第一个核心动作:抢session工厂。

以后Hibernate的session对象应该由Spring容器创建,管理,维护

在整合时HibernateSessionFactory这个类再也看不到了。

applicationContext.xml文件:

<beans>

     <bean id="sessionFactory"

         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

         <propertyname="configLocation"value="file:src/hibernate.cfg.xml">

         </property>

     </bean>

     <bean id="transactionManager"

         class="org.springframework.orm.hibernate4.HibernateTransactionManager">

         <propertyname="sessionFactory"ref="sessionFactory"/>

     </bean>

     <tx:annotation-driventransaction-manager="transactionManager"/>

</beans>

14.3 反向生成实体类与DAO(Spring整合时DAO要使用SpringDAO)

@Transactional

public class GoodsDAO {

     private staticfinal Loggerlog = LoggerFactory.getLogger(GoodsDAO.class);

     // property constants

     public staticfinal StringGOODSNAME ="goodsname";

     public staticfinal StringGOODSPRICE ="goodsprice";

     public staticfinal StringGOODSNUM ="goodsnum";

     private SessionFactory sessionFactory;

     public void setSessionFactory(SessionFactorysessionFactory) {

         this.sessionFactory =sessionFactory;

     }

     private Session getCurrentSession() {

         return sessionFactory.getCurrentSession();

     }

     //其他代码...

}

14.4 编写service业务类

在Service业务类中有依赖关系。

     <context:annotation-config/>

     <context:component-scan base-package="com.no8.service"/>

@Service("GoodsService")

public class GoodsService {

     @Autowired@Qualifier("GoodsDAO")

     private GoodsDAO goodsDAO ;

     public GoodsDAO getGoodsDAO() {

         return goodsDAO;

     }

     public void setGoodsDAO(GoodsDAOgoodsDAO) {

         this.goodsDAO =goodsDAO;

     }

     public List<Goods> findAll(){

         return this.goodsDAO.findAll();

     }

}

14.5 在保存Hibernate配置文件时修改

在applicationContext.xml文件中加入datasource的配置

 

     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

         <propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

         <propertyname="url"value="jdbc:mysql://localhost:3306/goodsdb"/>

         <propertyname="username"value="root"/>

         <propertyname="password"value="root"/>

     </bean>

 

     <bean id="sessionFactory"

         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

         <propertyname="configLocation"value="file:src/hibernate.cfg.xml">

         </property>

         <propertyname="dataSource"ref="dataSource"/>

     </bean>

在hibernate.cfg.xml文件中删除四个参数

     <session-factory>

         <property name="dialect">

              org.hibernate.dialect.MySQLDialect

         </property>

         <property name="myeclipse.connection.profile">goodsdb</property>

         <mapping class="com.no8.domain.Types" />

         <mapping class="com.no8.domain.Goods" />

     </session-factory>

 

15 使用Spring整合struts2和Hibernate(SSH)

15.1 三个框架的基本结构

struts2负责接收请求,调用业务,页面导航。

Hibernate负责CRUD

Spring负责对象的生命周期,依赖关系,AOP。

     Spring整合Hibernate时,1 抢Factory,2抢DAO

     Spring整合struts2时,抢Action

15.2 创建工程并导入SSH框架

推荐先导入Spring框架。整合Hibernate时,不保留Hibernate.cfg.xml文件。

web.xml文件:要有struts2框架的核心控制器,和Spring框架的监听器

     <display-name>ssh_no8_1117</display-name>

     <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>

     <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>*.action</url-pattern>

     </filter-mapping>

applicatonContext.xml文件中应该有Hibernate的配置信息

     <!-- 创建一个数据源对象。四个参数 -->

     <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">

         <propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

         <propertyname="url"value="jdbc:mysql://localhost:3306/goodsdb"/>

         <propertyname="username"value="root"/>

         <propertyname="password"value="root"/>

     </bean>

     <!-- 创建了一个生成Hibernate中Session的工厂 -->

     <bean id="sessionFactory"

         class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

         <propertyname="dataSource">

              <refbean="dataSource"/>

         </property>

         <propertyname="hibernateProperties">

              <props>

                   <propkey="hibernate.dialect">

                       org.hibernate.dialect.MySQLDialect

                   </prop>

                   <propkey="connection.useUnicode">true</prop>

                   <propkey="connection.characterEncoding">utf-8</prop>

              </props>

         </property>

     </bean>

     <!-- 事务管理器,Spring已经将Hibernate应该中的事务做好了。 -->

     <bean id="transactionManager"

         class="org.springframework.orm.hibernate4.HibernateTransactionManager">

         <propertyname="sessionFactory"ref="sessionFactory"/>

     </bean>

     <!-- 支持事务的注解方式,事务管理器的注解后台处理类 -->

     <tx:annotation-driventransaction-manager="transactionManager"/>

15.3 反向生成实体类和DAO

生成SpringDAO中可以直接获得Hibernate的Session对象。与只使用Hibernate时操作没有区别 。

applicationContext.xml文件:

     <bean id="TypesDAO" class="com.no8.dao.TypesDAO">

         <propertyname="sessionFactory">

              <refbean="sessionFactory"/>

         </property>

     </bean>

     <bean id="GoodsDAO" class="com.no8.dao.GoodsDAO">

         <propertyname="sessionFactory">

              <refbean="sessionFactory"/>

         </property>

     </bean>

15.4 创建工程的结构

     <context:annotation-config/>

     <context:component-scan base-package="com.no8.service,com.no8.controller"/>

15.5 编写业务层

     1查询所有商品类型

@Service("TypesService")

public class TypesService {

     @Autowired @Qualifier("TypesDAO")

     private TypesDAO typesDAO;

     public List<Types> findAll() {

         return this.typesDAO.findAll();

     }

     public TypesDAO getTypesDAO() {

         return typesDAO;

     }

     public void setTypesDAO(TypesDAOtypesDAO) {

         this.typesDAO =typesDAO;

     }

}

     2保存商品

@Service("GoodsService")

public class GoodsService {

     @Autowired@Qualifier("GoodsDAO")

     private GoodsDAO goodsDAO;

     public GoodsDAO getGoodsDAO() {

         return goodsDAO;

     }

     public void setGoodsDAO(GoodsDAOgoodsDAO) {

         this.goodsDAO =goodsDAO;

     }

     public boolean save(Goodsgoods){

         try{

              this.goodsDAO.save(goods);

              return true;

         }catch(Exception e){

              e.printStackTrace();

              return false;

         }

     }

}

15.6 编写控制器

     1查询所有商品类型

@Controller("TypesController")

@ParentPackage("struts-default")

@Namespace("/types")

public class TypesControllerextends ActionSupport {

     @Autowired@Qualifier("TypesService")

     private TypesService typesService;

     @Action("findall")

     public String findAll() throws Exception {

         List<Types> typesList = this.typesService.findAll();

         Map<String, Object> reqMap = (Map<String, Object>) ActionContext

                   .getContext().get("request");

         reqMap.put("typesList",typesList);

         return null;

     }

     public TypesService getTypesService() {

         return typesService;

     }

     public void setTypesService(TypesServicetypesService) {

         this.typesService =typesService;

     }

}

     2保存商品

@ParentPackage("struts-default")

@Namespace("/goods")

@Controller("GoodsController")

@Scope("prototype")

public class GoodsControllerextends ActionSupport{

     private Goods goods;

     @Autowired@Qualifier("GoodsService")

     private GoodsService goodsService;

     @Action(value="save",results={

              @Result(location="/show.jsp"),

              @Result(name=ERROR,location="/save.jsp")

     })

     public String save(){

         boolean bool = this.goodsService.save(goods);

         if(bool){

              return SUCCESS;

         }else{

              return ERROR;

         }

     }

     public GoodsService getGoodsService() {

         return goodsService;

     }

     public void setGoodsService(GoodsServicegoodsService) {

         this.goodsService =goodsService;

     }

}

 

15.7 编写JSP页

15.7.1 save.jsp:加载所有商品类型

     <form action="goods/save.action" method="post">

         商品名称:<inputname="goods.goodsname"value=""><br>

         商品价格:<inputname="goods.goodsprice"value=""><br>

         商品数量:<inputname="goods.goodsnum"value=""><br>

         <s:actionname="findall"namespace="/types"/>

         商品类型:<s:selectname="types.typeId"list="#request.typesList"

              listKey="typeId" listValue="typename" theme="simple"/>

         <br>

         <inputtype="submit"value="保存商品">

     </form>

15.7.2 实现保存商品功能

     @Action(value="save",results={

              @Result(type="redirectAction",location="findall"),

              @Result(name=ERROR,location="/save.jsp")

     })

     public String save(){

         goods.setTypes(types);

         boolean bool = this.goodsService.save(goods);

         if(bool){

              returnSUCCESS;

         }else{

              returnERROR;

         }

     }

15.7.3 show.jsp:显示所有商品信息

 

15.8 针对MySql数据库的中文乱码处理

<property name="url"

value="jdbc:mysql://localhost:3306/goodsdb?useUnicode=true&amp;characterEncoding=utf8"/>

15.9 处理异常,延迟加载。

异常:LazyInitializationException: could not initialize proxy - noSession

处理:OpenSessionInViewFilter(在使用Hibernate时自己写,Spring框架本身就有。)

     Spring框架时,这个类写好了。

<filter>

     <filter-name>opensession</filter-name>

     <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>

</filter>

<filter-mapping>

     <filter-name>opensession</filter-name>

     <url-pattern>/*</url-pattern>

</filter-mapping>

15.10 事务处理-声明式事务处理,基于注解

applicationContext.xml:有事务管理器的对象,和事务注解的注册

     <!-- 事务管理器,Spring已经将Hibernate应该中的事务做好了。 -->

     <bean id="transactionManager"

          class="org.springframework.orm.hibernate4.HibernateTransactionManager">

         <propertyname="sessionFactory"ref="sessionFactory"/>

     </bean>

     <!-- 支持事务的注解方式,事务管理器的注解后台处理类 -->

     <tx:annotation-driventransaction-manager="transactionManager"/>

在使用时,类或方法上加入事务的注解。

事务一般在哪一层处理?service层。业务层。

@Service("GoodsService")

public class GoodsService {

     @Autowired@Qualifier("GoodsDAO")

     private GoodsDAO goodsDAO;

     public GoodsDAO getGoodsDAO() {

         return goodsDAO;

     }

     public void setGoodsDAO(GoodsDAOgoodsDAO) {

         this.goodsDAO =goodsDAO;

     }

     @Transactional(propagation=Propagation.REQUIRED,rollbackFor={Exception.class} )

     public boolean save(Goodsgoods){

         try{

              this.goodsDAO.save(goods);

              return true;

         }catch(Exception e){

              e.printStackTrace();

              return false;

         }

     }

     @Transactional(propagation=Propagation.REQUIRED, readOnly=true )

     public List<Goods> findAll(){

         return this.goodsDAO.findAll();

     }

}

执行增删改时使用:

@Transactional(propagation=Propagation.REQUIRED,rollbackFor={Exception.class} )

REQUIRED:表示一定要有事务,如果有就使用,如果没有就创建一个。

rollbackFor={Exception.class} : 当发生任意异常时,回滚事务

执行查询时使用:

@Transactional(propagation=Propagation.REQUIRED, readOnly=true )

readOnly=true : 表示只读

15.11 实现验证商品名称是否存在

GoodsService

     @Transactional(propagation=Propagation.REQUIRED, readOnly=true )

     public booleanisExists(Stringgoodsname){

         if(this.goodsDAO.findByGoodsname(goodsname).isEmpty()){

              return false;

         }else{

              return true;

         }

     }

GoodsController

     @Action(value = "save", results = {

              @Result(type = "redirectAction", location = "findall"),

              @Result(name = ERROR, location = "/save.jsp"),

              @Result(name = INPUT, location = "/save.jsp") })

     public String save() {

         if (this.goodsService.isExists(goods.getGoodsname())) {

              ActionContext context = ActionContext.getContext();

              Map<String, Object> reqMap = (Map<String, Object>)context.get("request");

              reqMap.put("goodsnameerror","用户名已经存在!");

              return INPUT;

         } else {

              goods.setTypes(types);

              boolean bool = this.goodsService.save(goods);

              if (bool) {

                   return SUCCESS;

              } else {

                   return ERROR;

              }

         }

     }

15.12 处理异常,包冲突

异常:NoSuchMethodError: antlr.collections.AST.getLine()I

解决:删除包冲突,antlr.(Hibernate和struts2)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

原创粉丝点击