欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SSH框架之Spring+Struts2+Hibernate整合篇

程序员文章站 2022-03-10 16:17:07
回顾 -Hibernate框架 ORM: 对象关系映射.把数据库表和JavaBean通过映射的配置文件映射起来, 操作JavaBean对象,通过映射的配置文件生成SQL语句,自动执行.操作数据库. 1: 类名.hbm.xml 映射配置文件. 2: hibernate.cfg.xml 核心配置文件. ... ......
回顾 -hibernate框架
        orm: 对象关系映射.把数据库表和javabean通过映射的配置文件映射起来,
        操作javabean对象,通过映射的配置文件生成sql语句,自动执行.操作数据库. 
    1: 类名.hbm.xml 映射配置文件.
    2: hibernate.cfg.xml 核心配置文件.
    3: 使用hibernate提供的api操作.

    struts2框架 : 和客户端进行交互
    1. 在web.xml配置过滤器.
    2. struts.xml配置文件.
    
    spring框架
    1. applicationcontext.xml配置
    2. 核心ioc和aop
    3. 事务管理.
    customeraction类    在struts.xml配置中配置的
    1. action对象由struts2框架创建的.
        customeraction:创建customeraction对象,由struts2框架创建的    --->    spring的ioc容器中对象,找customerservice对象,默认按名称找的.
        
    2. action对象也可以由spring框架类创建
        <bean id="customeraction" class="com.baidu.customer.action.customeraction" scope="prototype">
            <property name="customerservice" ref="customerservice"/>
        </bean>
        
        <action name="customeraction_*" class="customeraction" method="{1}">
            <result name="initsave">/jsp/customer/add.jsp</result>
        </action>
        
day67_spring_05
            第1章整合前的准备
        1.1整合说明
        a.独立式整合指的是三个框架都使用自己的配置文件。
        b.引入式整合指的是hibernate主配置文件中的内容都配置到spring配置文件中
        c.在整合过程中,确保每步都运行成功,然后在继续往下做。
        d.整合中使用的案例是客户的保存和列表查询操作。
        e.后面的三种整合方式都基于1.2中的环境准备。
        1.2环境准备
        1.2.1第一步:创建java web工程
        此处使用servlet2.5规范。
        1.2.2第二步:创建数据库和表结构
        create database crm;
        use crm;

        /*创建客户表*/
        create table `cst_customer` (
          `cust_id` bigint(32) not null auto_increment comment '客户编号(主键)',
          `cust_name` varchar(32) not null comment '客户名称(公司名称)',
          `cust_source` varchar(32) default null comment '客户信息来源',
          `cust_industry` varchar(32) default null comment '客户所属行业',
          `cust_level` varchar(32) default null comment '客户级别',
          `cust_address` varchar(128) default null comment '客户联系地址',
          `cust_phone` varchar(64) default null comment '客户联系电话',
          primary key (`cust_id`)
        ) engine=innodb auto_increment=1 default charset=utf8;
        1.2.3第三步:编写实体类
        /**
         * 客户的实体类(数据模型)
         */
        public class customer implements serializable {

            private long custid;
            private string custname;
            private string custsource;
            private string custindustry;
            private string custlevel;
            private string custaddress;
            private string custphone;
            public long getcustid() {
                return custid;
            }
            public void setcustid(long custid) {
                this.custid = custid;
            }
            public string getcustname() {
                return custname;
            }
            public void setcustname(string custname) {
                this.custname = custname;
            }
            public string getcustsource() {
                return custsource;
            }
            public void setcustsource(string custsource) {
                this.custsource = custsource;
            }
            public string getcustindustry() {
                return custindustry;
            }
            public void setcustindustry(string custindustry) {
                this.custindustry = custindustry;
            }
            public string getcustlevel() {
                return custlevel;
            }
            public void setcustlevel(string custlevel) {
                this.custlevel = custlevel;
            }
            public string getcustaddress() {
                return custaddress;
            }
            public void setcustaddress(string custaddress) {
                this.custaddress = custaddress;
            }
            public string getcustphone() {
                return custphone;
            }
            public void setcustphone(string custphone) {
                this.custphone = custphone;
            }
            @override
            public string tostring() {
                return "customer [custid=" + custid + ", custname=" + custname + ", custsource=" + custsource
                        + ", custindustry=" + custindustry + ", custlevel=" + custlevel + ", custaddress=" + custaddress
                        + ", custphone=" + custphone + "]";
            }    
        }
        1.2.4第四步:编写业务层接口和实现类
        /**
         * 客户的业务层接口
         */
        public interface icustomerservice {

            /**
             * 查询所有客户
             * @return
             */
            list<customer> findallcustomer();
            
            /**
             * @param customer
             */
            void savecustomer(customer customer);
        }

        /**
         * 客户的业务层实现类
         */
        public class customerserviceimpl implements icustomerservice {

            private icustomerdao customerdao;

            public void setcustomerdao(icustomerdao customerdao) {
                this.customerdao = customerdao;
            }

            @override
            public list<customer> findallcustomer() {
                return customerdao.findallcustomer();
            }

            @override
            public void savecustomer(customer customer) {
                customerdao.savecustomer(customer);
            }
        }
        1.2.5第六步:创建持久层接口
        /**
         * 客户的持久层接口
         */
        public interface icustomerdao {
            
            /**
             * 查询所有客户
             * @return
             */
            list<customer> findallcustomer();
            
            /**
             * 保存客户
             * @param customer
             */
            void savecustomer(customer customer);
        }

        注意:做上述操作时,并不需要导入任何jar包。
        第2章基于xml的独立式整合
        2.1保证spring框架在web工程中独立运行
        2.1.1第一步:拷贝spring的ioc,aop和事务控制三组jar包

        2.1.2第二步:编写spring配置文件并导入约束
        <?xml version="1.0" encoding="utf-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
                xmlns:aop="http://www.springframework.org/schema/aop"
                xmlns:tx="http://www.springframework.org/schema/tx" 
                xsi:schemalocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/tx 
                        http://www.springframework.org/schema/tx/spring-tx.xsd
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop.xsd">
        </beans>
        2.1.3第三步:把业务层和持久层配置到文件中
        <!-- 把资源交给spring来管理 -->
        <!-- 配置dao -->
        <bean id="customerdao" class="com.baidu.dao.impl.customerdaoimpl"></bean>
            
        <!-- 配置service -->
        <bean id="customerservice" class="com.baidu.service.impl.customerserviceimpl">
            <!-- 注入dao -->
            <property name="customerdao" ref="customerdao"></property>
        </bean>

        持久层实现类代码:
            此时不要做任何操作,就输出一句话。目的是测试spring框架搭建的结果。
        /**
         * 客户的持久层实现类
         */
        public class customerdaoimpl implements icustomerdao {

            @override
            public list<customer> findallcustomer() {    
                system.out.println("查询了所有用户");
                return null;
            }

            @override
            public void savecustomer(customer customer) {
                system.out.println("保存了用户");
            }

        }
        2.1.4第四步:测试spring能否独立运行
        /**
         * 测试类,测试spring框架可以独立运行
         */
        public class spring01test {

            public static void main(string[] args) {
                //1.获取spring容器
                applicationcontext ac = new classpathxmlapplicationcontext("bean.xml");
                //2.跟id获取bean对象
                icustomerservice customerservice = (icustomerservice) ac.getbean("customerservice");
                customerservice.findallcustomer();
            }
        }

        2.2保证hibernate框架能够在web工程中独立运行
        2.2.1第一步:拷贝hibernate必备jar包到工程的lib目录
         
        2.2.2第二步:编写实体类的映射文件
        <?xml version="1.0" encoding="utf-8"?>
        <!doctype hibernate-mapping public 
            "-//hibernate/hibernate mapping dtd 3.0//en"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        <hibernate-mapping package="com.baidu.domain">
            <class name="customer" table="cst_customer">
                <id name="custid" column="cust_id">
                    <generator class="native"></generator>
                </id>
                <property name="custname" column="cust_name"></property>
                <property name="custsource" column="cust_source"></property>
                <property name="custindustry" column="cust_industry"></property>
                <property name="custlevel" column="cust_level"></property>
                <property name="custaddress" column="cust_address"></property>
                <property name="custphone" column="cust_phone"></property>
            </class>
        </hibernate-mapping>

        2.2.3第三步:编写hibernate主配置文件
        <?xml version="1.0" encoding="utf-8"?>
        <!doctype hibernate-configuration public
            "-//hibernate/hibernate configuration dtd 3.0//en"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
        <hibernate-configuration>
            <session-factory>
                <!-- 1.连接数据库的信息 -->
                <property name="hibernate.connection.driver_class">com.mysql.jdbc.driver</property>
                <property name="hibernate.connection.url">jdbc:mysql:///crmroperty>
                <property name="hibernate.connection.username">root</property>
                <property name="hibernate.connection.password">1234</property>
                <!-- 2.hibernate的基本配置 -->
                <!-- 数据库的方言-->
                <property name="hibernate.dialect">org.hibernate.dialect.mysqldialect</property>
                <!-- 是否显示sql语句-->
                <property name="hibernate.show_sql">true</property>
                <!-- 是否格式化sql语句-->
                <property name="hibernate.format_sql">false</property>
                <!-- 采用何种方式生成数据库表结构 -->
                <property name="hibernate.hbm2ddl.auto">update</property>
                <!-- 配置使用c3p0数据源 -->
                <property name="hibernate.connection.provider_class">org.hibernate.connection.c3p0connectionprovider</property>
                <!--把session绑定到当前线程上的配置-->
                <property name="hibernate.current_session_context_class">thread</property>
                <!-- 3.映射文件的位置 -->
                <mapping resource="com/baidu/domain/customer.hbm.xml"/>
            </session-factory>
        </hibernate-configuration>
        2.2.4第四步:编写测试类-测试保存客户
        /**
         * hibernate的测试类
         *         保证hibernate框架可以独立运行
         */
        public class hibernate02test {

            @test
            public void testfindall(){
                //1.读取配置文件
                configuration cfg = new configuration();
                cfg.configure();
                //2.根据配置文件获取sessionfactory
                sessionfactory factory = cfg.buildsessionfactory();
                //3.根据sessionfactory获取一个session
                session s = factory.getcurrentsession();
                //4.开启事务
                transaction tx = s.begintransaction();
                //5.执行操作
                query query = s.createquery("from customer");
                list list = query.list();
                for(object o : list){
                    system.out.println(o);
                }
                //6.提交事务
                tx.commit();
                //7.释放资源
                factory.close();
            }
            
            @test
            public void testsave(){
                customer c = new customer();
                c.setcustname("传智专修学院");
                //1.读取配置文件
                configuration cfg = new configuration();
                cfg.configure();
                //2.根据配置文件获取sessionfactory
                sessionfactory factory = cfg.buildsessionfactory();
                //3.根据sessionfactory获取一个session
                session s = factory.getcurrentsession();
                //4.开启事务
                transaction tx = s.begintransaction();
                //5.执行操作
                s.save(c);
                //6.提交事务
                tx.commit();
                //7.释放资源
                factory.close();
            }
        }
        2.3整合spring和hibernate框架
        2.3.1明确
        a.spring和hibernate的整合就是spring接管sessionfactory的创建
        b.spring针对hiberante的操作有一个封装的对象hibernatetemplate
        c.和jdbctemplate一样,hibernatetemplate也有一个hibernatedaosupport
        d.hibernatetemplate和hibernatedaosupport都在spring-orm-4.2.4.release.jar中
        e.我们dao采用继承hiberantedaosupport的方式编写,它一样不能用于注解配置。
        2.3.2整合步骤
        2.3.2.1第一步:在spring配置文件中配置sessionfactory
        <!-- 配置sessionfactory -->
        <bean id="sessionfactory" 
                    class="org.springframework.orm.hibernate5.localsessionfactorybean">
        <!-- 使用的是hibernate主配置文件中的内容,我们只需要指定hibernate主配置文件的所在位置 -->
            <property name="configlocation" value="classpath:hibernate.cfg.xml"/>
        </bean>
        2.3.2.2第二步:改造dao继承hibernatedaosupport
        /**
         * 客户的持久层实现类
         */
        public class customerdaoimpl extends hibernatedaosupport implements icustomerdao {

            @override
            public list<customer> findallcustomer() {    
                return (list<customer>) gethibernatetemplate().find("from customer");
            }

            @override
            public void savecustomer(customer customer) {
                gethibernatetemplate().save(customer);
            }
        }
        2.3.2.3第三步:在spring配置文件中给dao注入sessionfactory
        <!-- 配置dao -->
        <bean id="customerdao" class="com.baidu.dao.impl.customerdaoimpl">
            <property name="sessionfactory" ref="sessionfactory"></property>
        </bean>
        2.3.2.4第四步:测试
        /**
         * 整合spring和hibernate的测试类
         * spring整合junit
         *     第一步:拷贝jar包
         *         spring-junit-4.2.4.jar
         *  第二步:使用注解替换运行器(原来junit的main方法)
         *      @runwith(支持spring的main方法)
         *      @contextconfiguration(指定spring的配置文件位置)
         */
        @runwith(springjunit4classrunner.class)
        @contextconfiguration(locations={"classpath:bean.xml"})
        public class springhibernate03test {
            
            @autowired
            private icustomerservice customerservice;

            @test
            public void testfindall(){
                list list = customerservice.findallcustomer();
                for(object o : list){
                    system.out.println(o);
                }
            }
            
            @test
            public void testsave(){
                customer c = new customer();
                c.setcustname("传智学院test");        
                customerservice.savecustomer(c);
            }
        }
        测试结果:
            无论保存还是查询都运行失败!
            按常理来说,我们没有配置事务,保存失败是可以理解的。为什么查询也会失败呢?
        分析原因:
            是由于spring的hibernatetemplate对象在使用session时,spring创建了session的代理对象,在这个过程中,spring对hibernate绑定session到当前线程的配置不认识了,所以运行失败。
        2.3.2.5第五步:修改把session绑定到当前线程上
        <!-- 是hibernate把session绑定到当前线程上的配置 
        <property name="hibernate.current_session_context_class">thread</property>-->
        <!-- 是spring把sesion绑定到当前线程上的配置 -->
        <property name="hibernate.current_session_context_class">
            org.springframework.orm.hibernate5.springsessioncontext
        </property>

        此时再运行刚才的测试:
                查询可以使用了。保存不能使用,原因是没有事务。
        2.3.3配置spring的事务
        2.3.3.1第一步:配置事务管理器并注入sessionfactory
        <!-- 配置事务管理器 -->
        <bean id="transactionmanager" 
                class="org.springframework.orm.hibernate5.hibernatetransactionmanager">
            <!-- 注入sessionfactory -->
            <property name="sessionfactory" ref="sessionfactory"></property>
        </bean>
        2.3.3.2第二步:配置事务的通知及通知的属性
        <!-- 配置事务的通知 -->
        <tx:advice id="txadvice" transaction-manager="transactionmanager">
            <!-- 配置事务的属性 -->
            <tx:attributes>
                <tx:method name="*" read-only="false" propagation="required"/>
                <tx:method name="find*" read-only="true" propagation="supports"/>
            </tx:attributes>
        </tx:advice>
        2.3.3.3第三步:配置aop建立切入点表达式和事务通知的关系
        <!-- 配置aop -->
        <aop:config>
            <!-- 配置通用切入点表达式 -->
            <aop:pointcut expression="execution(* com.baidu.service.impl.*.*(..))" id="pt1"/>
            <!-- 建立事务通知和切入点表达式的对应关系 -->
            <aop:advisor advice-ref="txadvice" pointcut-ref="pt1"/>
        </aop:config>

        再次测试:
            此时保存和查询都可以正常使用了。
        2.4保证struts2框架能够在web工程中独立运行
        2.4.1第一步:拷贝struts2的必备jar包
        要把画红线的jar包删掉,因为hibernate中有个高版本的。
        2.4.2第二步:在类的类的根路径下编写struts.xml文件并导入约束
        <?xml version="1.0" encoding="utf-8"?>
        <!doctype struts public
            "-//apache software foundation//dtd struts configuration 2.3//en"
            "http://struts.apache.org/dtds/struts-2.3.dtd">
        <struts>
            <!-- 开启开发者模式 -->
            <constant name="struts.devmode" value="true"></constant>
        </struts>
        2.4.3第三步:在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>
        2.4.4第四步:导入jsp页面

        2.4.5第五步:修改menu.jsp
        <a class=style2 
            href="${pagecontext.request.contextpath}/customer/adduicustomer.action"  
            target=main>
            - 新增客户
        </a>
        2.4.6第六步:在struts.xml中配置action
        <!--  获取添加客户页面 -->
        <action name="adduicustomer" class="com.baidu.web.action.customeraction" 
                    method="adduicustomer">
            <result name="adduicustomer">/jsp/customer/add.jsp</result>
        </action>
        2.4.7第七步:编写动作类和方法
        /**
         * 客户的动作类
        */
        public class customeraction extends actionsupport implements modeldriven<customer> {
            private customer customer = new customer();

            @override
            public customer getmodel() {
                return customer;
            }
            
            /**
             * 获取添加客户页面
             * @return
             */
            public string adduicustomer(){
                return "adduicustomer";
            }
        }
        2.4.8第八步:测试
        运行结果:通过点击【新增客户】可以跳转到客户添加页面
        2.5整合spring和struts2
        2.5.1明确
        a.spring整合struts2就是让spring接管action的创建
        b.action是多例的,配置到spring中需要设置scope属性为多例
        2.5.2整合步骤
        2.5.2.1第一步:拷贝struts2-spring-plugin-2.3.24.jar到lib目录

        2.5.2.2第二步:在action中使用构造函数获取service对象
        public customeraction(){
            applicationcontext ac = webapplicationcontextutils.getwebapplicationcontext(
                                    servletactioncontext.getservletcontext());
                //由于动作类是多例的,每次都会创建容器,导致资源的浪费。一个应用应该只有一个容器
                system.out.println(ac);
                customerservice = (icustomerservice) ac.getbean("customerservice");
            }
        2.5.2.3第三步:测试
        运行结果:查询客户列表测试通过。保存测试通过。
        2.6优化配置
        2.6.1配置spring的监听器
        在上面2.5.2.2小节中有这么一句:
            由于动作类是多例的,每次都会创建容器,导致资源的浪费。一个应用应该只有一个容器
        问题:
            如何解决呢?
        答案:
            只要让容器在应用加载时创建,应用卸载时销毁就可以。
        问题:
            我们怎么知道应用何时加载了呢?
        答案:
            servletcontext对象创建了,就表示当前应用已经被服务器加载了。
        问题:
            我们怎么知道servletcontext对象创建了呢?
        答案:
            servletcontextlistener监听器可以监听到servletcontext对象的创建和销毁。

        spring框架为我们提供了一个监听器:contextloaderlistener。
        它是servletcontextlistener接口的实现类,负责监听servletcontext对象的创建,为我们创建容器,监听servletcontext对象的销毁,销毁容器。
        我们只需要配置上即可。
        contextloaderlistener在spring-web-4.2.4.release.jar中
        所以我们要先导入这个jar包。
        ,在web.xml中配置监听器:
        <listener>
            <listener-class>
                org.springframework.web.context.contextloaderlistener
            </listener-class>
        </listener>

        当配置了此监听器后,就不需要使用action的构造函数了,可以把构造函数那段删除了。
        此监听器只能读取web-inf目录中的名称为applicationcontext.xml的配置文件。这显然限制了我们的配置。
        我们可以通过配置全局初始化参数的方式,指定spring配置文件的位置.
        2.6.2配置指定spring配置文件的位置
        我们把spring配置文件放到此处,需要配置全局初始化参数:
        <context-param>
            <param-name>contextconfiglocation</param-name>
            <param-value>classpath:config/spring/applicationcontext.xml</param-value>
        </context-param>
        2.6.3分文件编写spring配置
        我们写到这里,其实搭建环境已经基本结束了,但是发现spring的配置文件杂乱无章,使我们在找配置的时候,很难一下找到。所以我们采用分配置文件编写的方式。
        2.6.3.1编写主配置文件引入其他配置文件
        <?xml version="1.0" encoding="utf-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
                xmlns:aop="http://www.springframework.org/schema/aop"
                xmlns:tx="http://www.springframework.org/schema/tx" 
                xsi:schemalocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx.xsd
                    http://www.springframework.org/schema/aop 
                    http://www.springframework.org/schema/aop/spring-aop.xsd">
            <!-- 引入其他spring配置文件 -->
            <import resource="applicationcontext-customer.xml"/>
            <import resource="applicationcontext-jdbc.xml"/>
            <import resource="applicationcontext-tx.xml"/>
        </beans>
        2.6.3.2编写针对需求的配置文件applicationcontext-customer.xml
        <?xml version="1.0" encoding="utf-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
                xmlns:aop="http://www.springframework.org/schema/aop"
                xmlns:tx="http://www.springframework.org/schema/tx" 
                xsi:schemalocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx.xsd
                    http://www.springframework.org/schema/aop 
                    http://www.springframework.org/schema/aop/spring-aop.xsd">
            <!-- 把资源交给spring来管理 -->
            <!-- 配置dao -->
            <bean id="customerdao" class="com.baidu.dao.impl.customerdaoimpl">
                <property name="sessionfactory" ref="sessionfactory"></property>
            </bean>
            
            <!-- 配置service -->
            <bean id="customerservice" 
                            class="com.baidu.service.impl.customerserviceimpl">
                <!-- 注入dao -->
                <property name="customerdao" ref="customerdao"></property>
            </bean>
        </beans>
        2.6.3.3编写数据库连接的配置文件applicationcontext-jdbc.xml
        <?xml version="1.0" encoding="utf-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
                xmlns:aop="http://www.springframework.org/schema/aop"
                xmlns:tx="http://www.springframework.org/schema/tx" 
                xsi:schemalocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx.xsd
                    http://www.springframework.org/schema/aop 
                    http://www.springframework.org/schema/aop/spring-aop.xsd">
            
            <!-- 配置sessionfactory -->
            <bean id="sessionfactory" 
                    class="org.springframework.orm.hibernate5.localsessionfactorybean">
            <!-- 使用的是hibernate主配置文件中的内容,我们只需要指定hibernate配置文件的位置 -->
                <property name="configlocation" 
                           value="classpath:config/hibernate/hibernate.cfg.xml">/>
            </bean>
        </beans>
        2.6.3.4编写事务控制的配置文件applicationcontext-tx.xml
        <?xml version="1.0" encoding="utf-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
                xmlns:aop="http://www.springframework.org/schema/aop"
                xmlns:tx="http://www.springframework.org/schema/tx" 
                xsi:schemalocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans.xsd
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx.xsd
                    http://www.springframework.org/schema/aop 
                    http://www.springframework.org/schema/aop/spring-aop.xsd">

            
            <!-- 配置事务管理器 -->
            <bean id="transactionmanager" 
                class="org.springframework.orm.hibernate5.hibernatetransactionmanager">
                <!-- 注入sessionfactory -->
                <property name="sessionfactory" ref="sessionfactory"></property>
            </bean>
            
            <!-- 配置事务的通知 -->
            <tx:advice id="txadvice" transaction-manager="transactionmanager">
                <!-- 配置事务的属性 -->
                <tx:attributes>
                    <tx:method name="*" read-only="false" propagation="required"/>
                    <tx:method name="find*" read-only="true" propagation="supports"/>
                </tx:attributes>
            </tx:advice>
            
            <!-- 配置aop -->
            <aop:config>
                <!-- 配置通用切入点表达式 -->
                <aop:pointcut expression="execution(* com.baidu.service.impl.*.*(..))" 
                                id="pt1"/>
                <!-- 建立事务通知和切入点表达式的对应关系 -->
                <aop:advisor advice-ref="txadvice" pointcut-ref="pt1"/>
            </aop:config>
        </beans>
        2.6.4配置指定struts2配置文件位置
        我们的spring和hibernate配置文件都存到了src/config/的对应包中了,只有struts2配置文件还在类的根路径下,它也可以通过配置的方式指定struts.xml的位置。配置的是过滤器的初始化参数。初始化参数的name和value都是固定写法。

        <filter>
            <filter-name>struts2</filter-name>
            <filter-class>
                org.apache.struts2.dispatcher.ng.filter.strutsprepareandexecutefilter
            </filter-class>
            <init-param>
                <param-name>config</param-name>
                <param-value>
                    struts-default.xml,struts-plugin.xml,config/struts/struts.xml
                </param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        2.6.5分文件编写struts2配置文件
        当我们后面做的模块越来越多,struts2一个配置文件写起来也会杂乱无章,所以我们也可以把struts2的配置文件分开编写。
        2.6.5.1编写struts2的主配置文件struts.xml
        <?xml version="1.0" encoding="utf-8"?>
        <!doctype struts public
            "-//apache software foundation//dtd struts configuration 2.3//en"
            "http://struts.apache.org/dtds/struts-2.3.dtd">
        <struts>
            <!-- 开启开发者模式 -->
            <constant name="struts.devmode" value="true"></constant>
            
            <package name="mydefault" extends="struts-default" abstract="true">
                <!--  有公共的配置就写在此处,没有就空着 -->
            </package>

            <!--引入其他struts2配置文件 -->
            <include file="config/struts/struts-customer.xml"></include>
        </struts>
        2.6.5.2针对不同模块编写不同的配置文件struts-customer.xml
        <?xml version="1.0" encoding="utf-8"?>
        <!doctype struts public
            "-//apache software foundation//dtd struts configuration 2.3//en"
            "http://struts.apache.org/dtds/struts-2.3.dtd">
        <struts>
            <package name="customer" extends="mydefault" namespace="/customer">
                <!--  获取添加客户页面 -->
                <action name="adduicustomer" 
                        class="com.baidu.web.action.customeraction" 
                        method="adduicustomer">
                    <result name="adduicustomer">/jsp/customer/add.jsp</result>
                </action>
                
                <!--  查询客户列表 -->
                <action name="findallcustomer" 
                        class=" com.baidu.web.action.customeraction" 
                        method="findallcustomer">
                    <result name="findallcustomer">/jsp/customer/list.jsp</result>
                </action>
            </package>
        </struts>
        2.6.6管理action的两种方式
        2.6.6.1第一种方式:让struts2自己来管理
        此种方式就是在action标签的class属性中提供动作类的全限定类名。

        <action name="adduicustomer" 
                class="com.baidu.web.action.customeraction" 
                method="adduicustomer">
            <result name="adduicustomer">/jsp/customer/add.jsp</result>
        </action>
        2.6.6.2第二种方式:让spring来管理(实际开发中采用的方式)
        此种方式就是在spring配置文件中配置action,在struts2配置文件action标签的class属性里写bean的id。

        spring配置文件:
        <!-- 配置action -->
        <bean id="customeraction" class="com.baidu.web.action.customeraction" 
                scope="prototype">
            <!-- 注入service -->
            <property name="customerservice" ref="customerservice"></property>
        </bean>    

        struts2配置文件:
        <!--  获取添加客户页面 -->
        <action name="adduicustomer" class="customeraction" method="adduicustomer">
            <result name="adduicustomer">/jsp/customer/add.jsp</result>
        </action>

        第3章基于xml的引入式整合
        3.1明确
        引入式整合就是把hibernate.cfg.xml中的配置都挪到spring的配置文件中
        3.2配置方式
        <!-- 配置sessionfactory -->
        <bean id="sessionfactory" 
                class="org.springframework.orm.hibernate5.localsessionfactorybean">
                <!-- 1、连接数据库的信息 -->
                <property name="datasource" ref="datasource"></property>
                <!-- 2、hibernate的基本配置 -->
                <property name="hibernateproperties">
                    <props>
                        <!-- 数据库的方言-->
                        <prop key="hibernate.dialect">
                                org.hibernate.dialect.mysqldialect
                        </prop>
                        <!-- 是否显示sql语句-->
                        <prop key="hibernate.show_sql">true</prop>
                        <!-- 是否格式化sql语句-->
                        <prop key="hibernate.format_sql">false</prop>
                        <!-- 采用何种方式生成数据库表结构 -->
                        <prop key="hibernate.hbm2ddl.auto">update</prop>
                        <!-- 是spring把sesion绑定到当前线程上的配置 -->
                        <prop key="hibernate.current_session_context_class">
                            org.springframework.orm.hibernate5.springsessioncontext
                        </prop>
                    </props>
                </property>
                <!-- 3、映射文件的位置 
                    mappingresources:配置映射文件的位置,需要写映射文件名称。
                                      并且有几个映射文件,就要写几个<value></value>。
                    mappinglocations:配置映射文件的位置,需要写映射文件名称。可以使用通配符。
                    mappingdirectorylocations:配置映射文件的位置,直接写到包的目录即可。
                -->
                <property name="mappinglocations">
                    <array>
                        <value>classpath:com/baidu/domain/*.hbm.xml</value>
                    </array>
                </property>
            </bean>

        <!-- 配置数据源 -->
        <bean id="datasource" class="com.mchange.v2.c3p0.combopooleddatasource">
            <property name="driverclass" value="com.mysql.jdbc.driver"></property>
            <property name="jdbcurl" value="jdbc:mysql:///crm"></property>
            <property name="user" value="root"></property>
            <property name="password" value="1234"></property>
        </bean>
        第4章基于注解的整合
        4.1明确
        a.注解整合仍然使用上面的环境,就是把xml的配置全部换成注解
        b.spring的注解整合有两种方式,一种是用xml文件,一种是纯注解。
        c.hibernate注解整合是把实体类映射改为jpa注解映射
        4.2整合步骤-spring使用xml文件
        4.2.1spring配置使用注解实现
        4.2.1.1第一步:导入spring的必备jar包
        之前的环境已经导入。略。
        4.2.1.2第二步:在spring配置文件中导入context名称空间及约束
        <?xml version="1.0" encoding="utf-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
                xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
                xmlns:aop="http://www.springframework.org/schema/aop"
                xmlns:tx="http://www.springframework.org/schema/tx" 
                xmlns:context="http://www.springframework.org/schema/context" 
                xsi:schemalocation="http://www.springframework.org/schema/beans 
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/tx 
                        http://www.springframework.org/schema/tx/spring-tx.xsd
                        http://www.springframework.org/schema/aop 
                        http://www.springframework.org/schema/aop/spring-aop.xsd
                        http://www.springframework.org/schema/context 
                        http://www.springframework.org/schema/context/spring-context.xsd">
        </beans>
        4.2.1.3第三步:在spring配置文件中配置要扫描的包
        <!-- 配置spring运行要扫描的包 -->
        <context:component-scan base-package="com.baidu"></context:component-scan>
        4.2.1.4第四步:把action,service和dao都用注解配置
        /**
         * 客户的动作类
         */
        @controller("customeraction")
        @scope("prototype")
        public class customeraction extends actionsupport implements modeldriven<customer> {
            @autowired
            private icustomerservice customerservice;
            //action中的方法不变
        }

        /**
         * 客户的业务层实现类
         */
        @service("customerservice")
        public class customerserviceimpl implements icustomerservice {
            @autowired
            private icustomerdao customerdao;
            //service中的方法不变
        }

        /**
         * 客户的持久层实现类
         */
        @repository("customerdao")
        public class customerdaoimpl implements icustomerdao {
            //dao中必须自己定义hibernatetemplate,不能继承hibernatedaosupport了
            @autowired
            private hibernatetemplate hibernatetemplate;
            //dao中的方法不变
        }
        4.2.1.5第五步:在spring配置文件中配置hiernatetemplate
        <!-- 配置hibernatetemplate -->
        <bean id="hibernatetemplate" 
                class="org.springframework.orm.hibernate5.hibernatetemplate">
            <!-- 注入sessionfactory -->
            <property name="sessionfactory" ref="sessionfactory"></property>
        </bean>
        4.2.1.6第六步:在spring配置文件中配置事务管理器
        <!-- 配置事务管理器 -->
        <bean id="transactionmanager" 
                class="org.springframework.orm.hibernate5.hibernatetransactionmanager">
            <!-- 注入sessionfactory -->
            <property name="sessionfactory" ref="sessionfactory"></property>
        </bean>
        4.2.1.7第七步:在spring配置文件中开启spring对注解事务的支持
        <!-- 开启spring对注解事务的支持 -->
        <tx:annotation-driven transaction-manager="transactionmanager"/>
        4.2.1.8第八步:在客户的业务层实现类上使用@transactional注解
        /**
         * 客户的业务层实现类
         */
        @service("customerservice")
        @transactional(readonly=false,propagation=propagation.required)
        public class customerserviceimpl implements icustomerservice {
            
            @autowired
            private icustomerdao customerdao;

            @override
            @transactional(readonly=true,propagation=propagation.supports)
            public list<customer> findallcustomer() {
                return customerdao.findallcustomer();
            }

            @override
            public void savecustomer(customer customer) {
                customerdao.savecustomer(customer);
            }
        }
        4.2.2hibernate映射使用注解配置实现
        4.2.2.1实体类映射注解配置
        /**
         * 客户的实体类
         *  jpa规范:java 持久化规范
         *  注解全都是jpa规范的。
         *  导包都需要导入javax.persistence包下的
         *
         */
        @entity
        @table(name="cst_customer")
        public class customer implements serializable {
            
            @id
            @generatedvalue(strategy=generationtype.identity)
            @column(name="cust_id")
            private long custid;
            @column(name="cust_name")
            private string custname;
            @column(name="cust_source")
            private string custsource;
            @column(name="cust_industry")
            private string custindustry;
            @column(name="cust_level")
            private string custlevel;
            @column(name="cust_address")
            private string custaddress;
            @column(name="cust_phone")
            private string custphone;
            public long getcustid() {
                return custid;
            }
            public void setcustid(long custid) {
                this.custid = custid;
            }
            public string getcustname() {
                return custname;
            }
            public void setcustname(string custname) {
                this.custname = custname;
            }
            public string getcustsource() {
                return custsource;
            }
            public void setcustsource(string custsource) {
                this.custsource = custsource;
            }
            public string getcustindustry() {
                return custindustry;
            }
            public void setcustindustry(string custindustry) {
                this.custindustry = custindustry;
            }
            public string getcustlevel() {
                return custlevel;
            }
            public void setcustlevel(string custlevel) {
                this.custlevel = custlevel;
            }
            public string getcustaddress() {
                return custaddress;
            }
            public void setcustaddress(string custaddress) {
                this.custaddress = custaddress;
            }
            public string getcustphone() {
                return custphone;
            }
            public void setcustphone(string custphone) {
                this.custphone = custphone;
            }
            @override
            public string tostring() {
                return "customer [custid=" + custid + ", custname=" + custname + ", custsource=" + custsource
                        + ", custindustry=" + custindustry + ", custlevel=" + custlevel + ", custaddress=" + custaddress
                        + ", custphone=" + custphone + "]";
            }    
        }
        4.2.2.2spring中sessionfactory配置修改
        <!-- 配置sessionfactory -->
        <bean id="sessionfactory" 
                class="org.springframework.orm.hibernate5.localsessionfactorybean">
            <!-- 1、连接数据库的 -->
            <property name="datasource" ref="datasource"></property>
            <!-- 2、hibernate基本配置的 -->
            <property name="hibernateproperties">
                <props>
                    <!-- 数据库的方言-->
                    <prop key="hibernate.dialect">
                        org.hibernate.dialect.mysqldialect
                    </prop>
                    <!-- 是否显示sql语句-->
                    <prop key="hibernate.show_sql">true</prop>
                    <!-- 是否格式化sql语句-->
                    <prop key="hibernate.format_sql">false</prop>
                    <!-- 采用何种方式生成数据库表结构 -->
                    <prop key="hibernate.hbm2ddl.auto">update</prop>
                    <!-- 是spring把sesion绑定到当前线程上的配置 -->
                    <prop key="hibernate.current_session_context_class">
                        org.springframework.orm.hibernate5.springsessioncontext
                    </prop>
                </props>
            </property>
            <!-- 3、指定扫描映射注解的包-->
            <property name="packagestoscan">
                <array>
                    <value>com.baidu.domain</value>
                </array>
            </property>
        </bean>
        4.2.3struts2配置使用注解实现
        4.2.3.1导入struts2注解的jar包

        4.2.3.2使用注解配置action
        /**
         * 客户的动作类
         */
        @controller("customeraction")
        @scope("prototype")
        //-------以下都是struts2的注解-----------
        @parentpackage("struts-default")//指定当前包的父包
        @namespace("/customer")//指定名称空间,访问当前action的所有方法都需要有名称空间
        public class customeraction extends actionsupport implements modeldriven<customer> {
            private customer customer = new customer();
            
            @autowired
            private icustomerservice customerservice;    
            
            @override
            public customer getmodel() {
                return customer;
            }
            
            /**
             * 查询所有客户
             * @return
             */
            private list<customer> customers;
            //用于配置动作名称
            @action(value="findallcustomer",results={
                    @result(name="findallcustomer",
                            type="dispatcher",
                            location="/jsp/customer/list.jsp")
            })
            public string findallcustomer(){
                customers = customerservice.findallcustomer();
                return "findallcustomer";
            }
            
            /**
             * 获取添加客户页面
             * @return
             */
            @action(value="adduicustomer",results={
                    @result(name="adduicustomer",
                            location="/jsp/customer/add.jsp")
            })
            public string adduicustomer(){
                return "adduicustomer";
            }
            
            /**
             * 添加客户
             * @return
             */
            @action(value="addcustomer",results={
                    @result(name="addcustomer",
                            type="redirect",
                            location="/jsp/success.jsp")
            })
            public string addcustomer(){
                customerservice.savecustomer(customer);
                return "addcustomer";
            }
            
            public list<customer> getcustomers() {
                return customers;
            }
            public void setcustomers(list<customer> customers) {
                this.customers = customers;
            }
spring整合struts2的底层实现原理,由spring来创建action对象 (原理在包struts2-spring-plugin-2.3.24.jar中)
        package com.baidu.customer.action;

        import com.baidu.customer.domain.customer;
        import com.baidu.customer.service.customerservice;
        import com.opensymphony.xwork2.actionsupport;
        import com.opensymphony.xwork2.modeldriven;

        /**
         * 客户模块
         * @author administrator
         */
        public class customeraction extends actionsupport implements modeldriven<customer>{
            
            private customer customer = new customer();
            public customer getmodel() {
                return customer;
            }
            
            /**
             * 跳转到新增页面
             * @return
             * @throws exception
             */
            public string initsave() throws exception {
                return "initsave";
            }
            这种方式是ation对象由struts2创建的
            // 对象工厂,通过name自动装配对象  customerservice(底层通过jar包用常量覆盖struts2的默认配置,开启spring的对象工厂,当浏览器访问的时候
            ,访问到action以后再创建customerservice对象时,用名称name在springioc容器里面找,找到以后返回到action的set方法的customerservice里面,给customerservice赋一个实现类对象值)
            private customerservice customerservice;
            public void setcustomerservice(customerservice customerservice) {
                this.customerservice = customerservice;
            }

            public string save() throws exception {
                system.out.println("web层:保存客户...");
                customerservice.save(customer);
                return none;
            }

        }