• spring 2.5 基础知识和与其他框架的集成


    spring环境搭建:

      一:导入spring2.5所需的包,在classpath目录下建一个名为"beans.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"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
          
          这里写代码 </beans>

           二:spring得到实例:一:通过该类本身的构造方法(可以进行构造注入)得到实例,然后再进行setter注入。

                          二是:通过其他类的静态方法或其他bean的动态方法(可以进行构造注入)得到未知实例,未知实例再调用setter进行注入

       例如:

        <bean id="id号"  class="包名.类名"/>

       <bean id="id号"  class="包名.类名" factory-method="该类的静态方法"/>

       <bean id="id号"  factory-bean="其他的bean" factory-method="其他bean中动态方法" />

       解释:如果在"bean" 标签上加了 scope="prototype"设置,表示原型,那么spring容器开启时,不能获得实例,只有getBean()时才会得到实例,这样得到的实例不是同一个实例。加了lazy-init="true"表示懒加载,那么spring容器开启时,不能获得实例,但得到是同一个实例。同理,如果在"beans" 标签上加了 default-lazy-init="true",则是对所有bean设置的。

        如果在"bean" 标签上加了 init-method="该bean对应类中的方法"设置,则表示得到实例后就调用的方法。

        如果在"bean" 标签上加了 destroy-method="该bean对应类中的方法"设置,则表示实例销毁前调用的方法(spring 容器关闭,则实例销毁)

        A:依赖注入:

        一种方式为构造注入:<constructor-arg index="0"  type="包名.类名" value="***"/>         //基本类型和String类型可以不用写type

         一种方式为setter方法注入:

            <property name=" setter方法名的关键字"   value=""/>          //适用于基本类型和String类型

            <property name="setter方法名的关键字" [ref=""|local=""]/>         //其中local表示本地的bean,就是该xml文件中bean,

            <property name="setter方法名的关键字"><bean class="包名.类名"/></property>

           如果bean中的属性是集合类型,那么一般采用setter方式进行注入:

              对于Set集合:

    <property name="sets">
                  <set>
                      <value>李鹏生</value>
                      <value>李小龙</value>
                      <value>李嘉城</value>
                      <value>李鹏</value>
                  </set>
              </property>

              对于List集合和数组:

    <property name="list">
                      <list>
                          <value>秦始皇</value>
                          <value>李世民</value>
                          <value>李自成</value>
                      </list>
              </property>

              对于Map集合:

    <property name="map">
                  <map>
                      <entry key="key1" value="one"/>
                      <entry key="key2" value="two"/>
                      <entry key="key3" value="three"/>
                  </map>
              </property>

              对于Properties集合:

     <property name="prop">
                  <props>
                      <prop key="key1">第一个</prop>
                      <prop key="key2">第二个</prop>
                      <prop key="key3">第三个</prop>
                  </props>
              </property>
     <property name="hibernateProperties">
                <value>
                    hibernate.dialect=org.hibernate.dialect.MySQLDialect
                    hibernate.hbm2ddl.auto=update
                    hibernate.show_sql=false
                </value>
             </property>

    B:采用注解方式进行依赖注入:

      在beans.xml中加入代码:

     xmlns:context=http://www.springframework.org/schema/context
     
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-2.5.xsd

               打开注解配置项:

        <context:annotation-config/> 

      两种注解:一是:@Autowired    是按类型装配     二是:@Resource  默认是按名称装配,就是根据id名称装配,如果找不到,会按类型装配。

        下面举两个例子说明下:  如:@Resource PersonDao  personDao; 其中PersonDao是一个接口,如果PersonDaoImpl是PersonDao接口的实现类。它是怎么装配的呢,首先它是找到名称为"personDao"id的bean,如果找到,但并不是PersonDao接口的实现类,则出异常;如果找不到名称为"personDao"id的bean,则按类型找,找PersonDao接口的实现类,如果实现类是多个,那么就会异常。

    所以说接口的实现类为多个的话,就按名称装配。同样的道理,如果一个类有它的子类,而我们想得到子类的实例,然后进行向上转型,那么就要按照名称装配,而不是类型装配了。

      例子:@Resource private Ni  n,或者这样:private Ni n; @Resource  public void setNi(Ni n){this.n=n;}  方法名可以是任意名称,不一定是"setNi",本质是调用这个方法而已,只是容易见名思义。

        建议:使用@Resource 注解;变量名称为bean的id名称;使用"setNi"这种格式的方法名。本质是调用这个方法而已,只是容易见名思义。

     三:spring容器的实例化:

        例如:

        ApplicationContext  ctx=new ClassPathXmlApplicationContext(new String[]{"beans.xml"});  --可以实例化多个.xml文件。

        得到bean的实例,得到之后要进行相应的转型,如:类名,父类,接口。

        (类名,父类,接口)  引用名=(类名,父类,接口) ctx.getBean("该bean相应的id名"); 

                              四:spring 容器自动扫描和管理bean(代替了在beans.xml配置的<bean id="" class=""/>):

      在beans.xml中加入代码:<context:component-scan base-package="com.itcast">(可以删掉之前的<context:annotation-config/> ) --其 中"com.itcast"也包括该包下的子包下类。

      然后在该包及该包的子包下的类加上@Service(服务层组件)或@Controller(控制层组件)或@Repository(DAO层组件)或@Component(泛指组件)表示该类由

    spring容器实例。

      那么我们又是怎样得到哪些bean的实例呢,默认是这样得到的:该类的首字母小写。如:类名为:PersonServiceImpl,那么它的id为:personServiceImpl。

    当然我们也可以更改bean的id.如:@Service("所要更改的id名称")。

      我们也可以设置bean的作用域:没设置,默认是单例,也就是@Scope("singleton"),@Scope("[singleton|prototype|request|session|global session]")。

      如果在类的某方法前面加上@PostConstruct 注解,表示该bean类实例后将执行该方法,通常命名为"init";如果在类的某方法前面加上@PreDestroy 注解,表示该bean类实例后将执行该方法,通常命名为"destroy".

      总结:一种.xml中有bean标签,一种.xml中没有bean标签(即自动扫描和注解)。一种是.xml中依赖注入,一种是注解方式的依赖注入。

      建议:使用@Resource 注解;变量名称为bean的id名称;使用"setNi"这种格式的方法名。本质是调用这个方法而已,只是容易见名思义。

      spring管理的bean是怎么完成该bean父类的依赖注入的。如果父类是采用的是注解注入,则它按照装配原则自动完成的。

      如果父类是采用的是在.xml中依赖注入,则需要在管理的bean中的bean标签中加入parent="父类bean所对应的id名称"。

                五:spring集成jdbc和spring集成hibernate

          步骤:一:配置数据源  二:配置SessionFactory(如果是集成hibernate的就会配置)  三:配置事务管理器  四:配置事务。

        其中一、二步骤用于数据库连接方面的,三、四步骤用于Service层方面的,利用AOP技术对DAO层中的方法进行事务管理

        配置数据源:

        代码列子:

        这里用到了.properties文件,当然你也可以不用,不过这样修改起来方便。

      例子:

        classpath下的jdbc.properties文件的代码:

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/itcast?useUnicode=true&characterEncoding=UTF-8
    username=root
    password=admin
    initialSize=1
    maxActive=500
    maxIdle=2
    minIdle=1

        相应beans.xml下的代码:

     <context:property-placeholder location="classpath:jdbc.properties"/>
         <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <property name="driverClassName" value="${driverClassName}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
             <!-- 连接池启动时的初始值 -->
             <property name="initialSize" value="${initialSize}"/>
             <!-- 连接池的最大值 -->
             <property name="maxActive" value="${maxActive}"/>
             <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
             <property name="maxIdle" value="${maxIdle}"/>
             <!--  最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
             <property name="minIdle" value="${minIdle}"/>
         </bean>

        <context:property-placeholder location="classpath:jdbc.properties"/>        指明.properties文件。

      配置SessionFactory(将数据源注入到SessionFactory中):

        例子一:

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
             <property name="dataSource" ref="dataSource"/>
             <property name="mappingResources">
                <list>
                  <value>cn/itcast/bean/Person.hbm.xml</value>
                 </list>
             </property>
             <property name="hibernateProperties">
                <value>
                    hibernate.dialect=org.hibernate.dialect.MySQLDialect
                    hibernate.hbm2ddl.auto=update
                    hibernate.show_sql=false
                </value>
             </property>
        </bean>

      例子二(数据源和SessionFactory都用到了.properties 文件):

          classpath下jdbc.properties文件代码:

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/cms?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true
    jdbc.username=root
    jdbc.password=123456
    jdbc.maxActive=300
    jdbc.maxWait=5000
    hibernate.dialect=org.hibernate.dialect.MySQLDialect
    hibernate.show_sql=true
    hibernate.hbm2ddl.auto=update
    hibernate.format_sql=true
    hibernate.connection.autocommit=false
    hibernate.order_updates=true
    hibernate.jdbc.use_scrollable_resultset=true
    hibernate.use_sql_comments=true
    hibernate.connection.release_mode=after_transaction
    hibernate.current_session_context_class=thread

        相应的beans.xml代码(这里就省略不写数据源了,当然也要指明.properties文件,这里也省略了):

    <bean id="sessionFactory"
            class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource">
            </property>
              <!-- 映射所有实体 -->
            <property name="packagesToScan">
                <list>
                    <value>com.yojosources.admin.po</value>
                    <value>com.yojosources.business.po</value>
                    <value>com.yojosources.member.po</value>
                    <value>com.yojosources.privilege.po</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <props>
                    <prop key="javax.persistence.validation.mode">none</prop>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
       <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
    
                    <!-- 输出所有SQL语句到控制台 -->
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
    
                    <!-- 在log和console中打印出更漂亮的SQL -->
                    <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
    
    
                    <!-- 允许被缓存的JDBC 连接开启自动提交 -->
                    <prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}</prop>
    
                    <!-- 强制Hibernate按照被更新数据的主键,为SQL更新排序。 -->
                    <prop key="hibernate.order_updates">${hibernate.order_updates}</prop>
    
                    <!-- 允许Hibernate使用JDBC2的可滚动结果集。 -->
                    <prop key="hibernate.jdbc.use_scrollable_resultset">${hibernate.jdbc.use_scrollable_resultset}</prop>
    
    
                    <!-- hibernate将在SQL中生成有助于调式的注解信息 -->
                    <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
    
                    <!-- 指定Hibernate在何时释放 JDBC 连接 -->
                    <prop key="hibernate.connection.release_mode">${hibernate.connection.release_mode}</prop>
    
                    <!-- 同一个事务用一个session -->
    <!--                <prop key="hibernate.current_session_context_class">${hibernate.current_session_context_class}</prop>-->
    
                </props>
            </property>
    
        </bean>

       解释:这里用到了packagesToScan属性,它是指定要扫描哪些包里的数据库映射类,是mappingResource属性对立的又一种方式。先说说packagesToSan的用法:

    1.  <property name="packagesToScan" value="com.xxx.entity" />, 会解析成"classpath*:com/xxx/entity**/*.class",这个路径可以找出com/xxx/entity根目录下的类文件 

    2. <property name="packagesToScan" value="com.xxx.entity.*" />, 会解析成"classpath*:com/xxx/entity/***/*.class",这个路径可以找出com/xxx/entity根目录下一级子目录中的类文件,如com/xxx/entity/son/Hi.class ,而不能找出com/xxx/entity目录下的类文件。

    3.  <property name="packagesToScan" value="com.xxx.entity." />(注意最后的点) , 会转换成"classpath*:com/xxx/entity/**/*.class",这个路径可以找出com/xxx/entity根目录下及其子孙目录下所有的类文件. 一般来讲,这些就是我们要的文件。

     数据库映射类(它没有配置文件hbm.xml,全部采用注解的方式),例子:
    package com.yojosources.admin.po;
    
    import java.util.Date;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Lob;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    
    import org.springframework.stereotype.Repository;
    
    /**
     * 文章实体
     * @author Beamstar
     */
    @Entity
    @Repository(value="t_article")
    @Table(name="t_article")
    public class Article {
        
        /**
         * 主键
         * 文章 id
         */
        private Integer ar_id;
        
        /**
         * 文章 标题
         */
        private String ar_name;
        /**
         * 文章发布人
         */
        private String ar_author;
        /**
         * 文章内容
         */
        private String ar_content;
        /**
         * 发布日期
         */
        private Date ar_date;
        
        /**
         * 浏览次数
         */
        private Integer ar_readCount;
        
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name = "article_id", unique = true, nullable = false)
        public Integer getAr_id() {
            return ar_id;
        }
        public void setAr_id(Integer arId) {
            ar_id = arId;
        }
        
        
        @Column(name="headline")
        public String getAr_name() {
            return ar_name;
        }
        public void setAr_name(String arName) {
            ar_name = arName;
        }
        @Column(name="author")
        public String getAr_author() {
            return ar_author;
        }
        public void setAr_author(String arAuthor) {
            ar_author = arAuthor;
        }
        
        @Lob
        @Column(name="article_contents", columnDefinition="TEXT", nullable=true)
        public String getAr_content() {
            return ar_content;
        }
        public void setAr_content(String arContent) {
            ar_content = arContent;
        }
        
        @Column(name="artcleues_date")
        @Temporal(TemporalType.TIMESTAMP)
        public Date getAr_date() {
            return ar_date;
        }
        public void setAr_date(Date arDate) {
            ar_date = arDate;
        }
        
        
        @Column(name="page_view")
        public Integer getAr_readCount() {
            return ar_readCount;
        }
        
        public void setAr_readCount(Integer arReadCount) {
            ar_readCount = arReadCount;
        }
        public Article() {
            super();
            // TODO Auto-generated constructor stub
        }
        public Article(Integer arId, String arName, String arAuthor,
                String arContent, Date arDate, Integer arReadCount) {
            super();
            ar_id = arId;
            ar_name = arName;
            ar_author = arAuthor;
            ar_content = arContent;
            ar_date = arDate;
            ar_readCount = arReadCount;
        }
        
        
        
    
    }

         配置事务管理器:

        jdbc:

     <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
             <property name="dataSource" ref="dataSource"/>  
     </bean> 

         hibernate:

    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
              <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

         配置事务(利用了AOP技术。主要是拦截方法(建议不管是注解方式还是.xml方式,最好是拦截类中的方法,而不是接口);配置事务(主要指事务的传播性);调用方法时,那么它生成的是代理对象):

       首先要引入命名空间,在beans.xml中插入代码:

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

     http://www.springframework.org/schema/aop //引入AOP命名空间
    http://www.springframework.org/schema/aop/spring-aop-2.5.xsd



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

    http://www.springframework.org/schema/tx                   //引入事务命名空间
    http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

       在.xml里配置事务:

        例子一:

     <aop:config proxy-target-class="true">              //proxy-target-class="true"表示允许实现了接口的类,生成的代理对象可以是类的对象。
              <aop:pointcut id="transactionPointcut" expression="execution(* cn.itcast.service.PersonService.*(..))"/>
              <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut" />
     </aop:config> 
     <tx:advice id="txAdvice" transaction-manager="txManager">
              <tx:attributes>
                <tx:method name="save" propagation="REQUIRED"/>
              </tx:attributes> 
     </tx:advice>

           例子二:

        <aop:config proxy-target-class="true">
            <aop:pointcut expression="execution(public * com.yojosources.service.impl.*.*(..))"
                id="bussinessService" />
            <aop:pointcut expression="execution(public * com.yojosources..*Service.*(..))"
                id="service" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="bussinessService" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="service" />
        </aop:config>
    
        <tx:advice id="txAdvice" transaction-manager="transactionManager">               
            <tx:attributes>
                <tx:method name="save*" propagation="REQUIRED" />                       
                <tx:method name="add*" propagation="REQUIRED" />
                <tx:method name="create*" propagation="REQUIRED" />
                <tx:method name="insert*" propagation="REQUIRED" />
                <tx:method name="update*" propagation="REQUIRED" />
                <tx:method name="merge*" propagation="REQUIRED" />
                <tx:method name="del*" propagation="REQUIRED" />
                <tx:method name="remove*" propagation="REQUIRED" />
                <tx:method name="put*" propagation="REQUIRED" />
                <tx:method name="get*" propagation="SUPPORTS" read-only="true" />         //read-only="true"表示该方法只执行读取数据操作
                <tx:method name="count*" propagation="SUPPORTS" read-only="true" />
                <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
                <tx:method name="query*" propagation="SUPPORTS" read-only="true" />
                <tx:method name="list*" propagation="SUPPORTS" read-only="true" />
                <tx:method name="*" propagation="SUPPORTS" read-only="true" />              "*" 表示其他的方法
                <tx:method name="batchSaveOrUpdate" propagation="REQUIRES_NEW" />
            </tx:attributes>
        </tx:advice>

          注解方式配置事务:

         在beans.xml加上代码:<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />

         例子:

    package cn.itcast.service.impl;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import org.hibernate.SessionFactory;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import cn.itcast.bean.Person;
    import cn.itcast.service.PersonService;
    
    @Transactional
    public class PersonServiceBean implements PersonService {
        @Resource private SessionFactory sessionFactory;
        
        @Transactional(readOnly=true)
        public void save(Person person){
            sessionFactory.getCurrentSession().persist(person);
        }
        
        public void update(Person person){
            sessionFactory.getCurrentSession().merge(person);
        }
        @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
        public Person getPerson(Integer personid){
            return (Person)sessionFactory.getCurrentSession().get(Person.class, personid);
        }
    
        public void delete(Integer personid){
            sessionFactory.getCurrentSession().delete(
                    sessionFactory.getCurrentSession().load(Person.class, personid));
        }
        @Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
        @SuppressWarnings("unchecked")
        public List<Person> getPersons(){        
            return sessionFactory.getCurrentSession().createQuery("from Person").list();
        }
        
    }

         事务的传播性:

    常用的传播性主要是 REQUIRED,NOT_SUPPORTED,SUPPORTS。

                           spring集成struts

      spring容器实例化交给web.xml:

        <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 -->
        <context-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:beans.xml</param-value>           //多个.xml文件用逗号隔开
        </context-param>
        <!-- 对Spring容器进行实例化 -->
        <listener>
              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

        web容器实例化spring容器,详细见:http://blog.csdn.net/yangxueyong/article/details/6579700

      当然spring也提供了方法让我们得到spring容器的实例,从而得到想要的bean。

               集成struts1.x(其实就是让struts1.x中的action交给spring管理)

        代码例子:

      beans.xml中的代码:

      struts-config.xml中的代码:

                集成struts2.x(其实就是让struts2.x中的action交给spring管理)

      beans.xml中的代码:

      struts.xml中代码:

    <constant name="struts.objectFactory" value="spring" />     //将action交给spring管理。

         注意其中的class="".

    这里采用了在.xml中,当然也可以采用注解方式.

    struts.xml默认放在classpath路径的根目录下。web容器会找到,如果要改变路径,那么要在web.xml中配置,详细见:http://blog.163.com/wunan_23/blog/static/1955623202011102105925798/

  • 相关阅读:
    Google API 详解
    Why should I use SASS?
    Google Maps and ASP.NET
    IP摄像机
    解决母版页报错“内容控件必须是内容页中的顶级控件,或是引用母版页的嵌套母版页。”
    sass服务
    C#中操作符的重载(Time类)
    第一次面试
    单链表(C++)
    指针和引用的区别(C++)
  • 原文地址:https://www.cnblogs.com/lipengsheng-javaweb/p/4011899.html
Copyright © 2020-2023  润新知