• 框架学习之Spring 第五节 SSH整合开发[Spring2.5+Hibernate3.3+Struts2]


    1.首先整合Spring和Hibernate

    ①引入jar包:

    hibernate核心安装包下的:

    hibernate3.jar

    lib\required\*.jar

    lib\optional\ehcache-1.2.3.jar

    hibernate 注解安装包下的

    lib\test\slf4j-log4j12.jar

    Spring安装包下的:

    dist\spring.jar

    dist\modules\spring-webmvc-struts.jar

    lib\jakarta-commons\commons-logging.jar、commons-dbcp.jar、commons-pool.jar

    lib\aspectj\aspectjweaver.jar、aspectjrt.jar

    lib\cglib\cglib-nodep-2.1_3.jar

    lib\j2ee\common-annotations.jar

    lib\log4j\log4j-1.2.15.jar

    数据库使用mysql:

    添加 Mysql 驱动包  mysql-connector-java-5.1.16-bin.jar

    后面还要进行单元测试,所以还有引入 junit4.jar,当然这个可以在后面由 Myeclipse 来进行,安装时已经有了这个jar包,Myeclipse会自动引入

    ②数据源配置的文件: jdbc.properties (放在src目录下)

    driverClassName=org.gjt.mm.mysql.Driver
    url=jdbc\:mysql\://localhost/hibernate
    username=root
    password=yinger
    initialSize=1
    maxActive=500
    maxIdle=2
    minIdle=1

    ③Spring中的beans.xml (示例的最终版,放在src目录下)

    <?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:context="http://www.springframework.org/schema/context"
        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-2.5.xsd
             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
    
        <!-- 开启注解方式进行bean的管理和依赖注入 -->
        <context:annotation-config/>
        
        <!-- 数据源配置的文件的位置 -->
        <context:property-placeholder location="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>
    
        <!-- 定义sessionFactory -->
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="mappingResources">
                <list>
                    <value>com/yinger/domain/Person.hbm.xml</value>
                </list>
            </property>
            <property name="hibernateProperties">
                <value>
                    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
                    hibernate.hbm2ddl.auto=update
                    hibernate.show_sql=true
                    hibernate.format_sql=false
              </value>
            </property>
        </bean>
        
        <!-- 定义事务管理器:此处的含义就是下面的事务管理器管理由sessionFactory创建的session -->
        <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
        </bean>
        
         <!--  开启注解方式使用事务  -->
        <tx:annotation-driven transaction-manager="txManager" />
        
        <!-- Spring管理的bean -->
        <bean id="personService" class="com.yinger.service.impl.PersonServiceBean"></bean>
        
    </beans>

    ④测试 Spring 和 Hibernate  的整合是否成功

    新建domain对象:Person

    package com.yinger.domain;
    
    public class Person {
    
        private int id;
        private String name;
        
        public Person(){}
        
        public Person(String name){
            this.name = name;
        }
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
    }

    新建Person的映射文件:Person.hbm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="com.yinger.domain">
    
        <class name="Person">
            <id name="id">
                <generator class="native" />
            </id>
            <property name="name" />
        </class>
    
    </hibernate-mapping>

    新建业务层接口:PersonService

    package com.yinger.service;
    
    import java.util.List;
    
    import com.yinger.domain.Person;
    
    public interface PersonService {
    
        public void save(Person p);
        
        public void update(Person p);
        
        public void delete(int personid);
        
        public Person getPerson(int personid);
        
        public List<Person> getPersons();
        
    }

    新建上面的接口的实现类:PersonServiceBean

    package com.yinger.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 com.yinger.domain.Person;
    import com.yinger.service.PersonService;
    
    @Transactional
    public class PersonServiceBean implements PersonService{
        
        private SessionFactory sessionFactory;
        
        @Resource //属性的setter方法注入对象
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
        }
        //保存
        public void save(Person p) {//建议使用persist方法,而不是save方法
            sessionFactory.getCurrentSession().persist(p);
        }
        //更新
        public void update(Person p) {//建议使用merge方法(把对游离态的对象的更新与数据库同步),而不是update方法
            sessionFactory.getCurrentSession().merge(p);
        }
        //删除
        public void delete(int personid) {//建议得到对象的方法使用load,免去数据封装的过程
            sessionFactory.getCurrentSession().delete(sessionFactory.getCurrentSession().load(Person.class, personid));
        }
        //得到指定id的person
        @Transactional(propagation=Propagation.NOT_SUPPORTED)
        public Person getPerson(int personid) {
            return (Person)sessionFactory.getCurrentSession().get(Person.class, personid);
        }
        //得到所有的person
        @Transactional(propagation=Propagation.NOT_SUPPORTED)
        @SuppressWarnings("unchecked")
        public List<Person> getPersons() {
            return (List<Person>)sessionFactory.getCurrentSession().createQuery("from Person").list();
        }
    
    }

    基于PersonServiceBean 进行单元测试,编写测试类

    package junit.test;
    
    import java.util.List;
    
    import org.junit.BeforeClass;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.yinger.domain.Person;
    import com.yinger.service.PersonService;
    
    public class SSHTest {
    
        public static PersonService personService;
        
        @BeforeClass  //这个方法是在单元测试实例生成之后就会执行的方法,可以在里面写上一些初始化操作
        public static void setUpBeforeClass() throws Exception {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
            personService = (PersonService)ctx.getBean("personService");
        }
    
        @Test
        public void testSave() {
            for(int i=0;i<5;i++){
                Person person = new Person("personname"+(i+1));
                personService.save(person);        
            }
        }
    
        @Test
        public void testUpdate() {
            Person person = personService.getPerson(2);
            person.setName("yinger");
            personService.update(person);
        }
    
        @Test
        public void testDelete() {
            personService.delete(3);
        }
    
        @Test
        public void testGetPerson() {
            personService.getPerson(4);
        }
    
        @Test
        public void testGetPersons() {
            List<Person> list = personService.getPersons();
            for(Person person:list){
                System.out.println(person.getName());
            }
        }
    }

    首先测试第一个方法,输出结果:

    log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
    log4j:WARN Please initialize the log4j system properly.
    Hibernate: insert into Person (name) values (?)
    Hibernate: insert into Person (name) values (?)
    Hibernate: insert into Person (name) values (?)
    Hibernate: insert into Person (name) values (?)
    Hibernate: insert into Person (name) values (?)

    数据库中的数据

    18

    测试delete方法:

    Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from Person person0_ where person0_.id=?
    Hibernate: delete from Person where id=?

    19

    测试update方法: 【我不清楚为什么这里会有两条select语句,应该是一条就可以了的啊,是不是merge方法的原因呢?望高手指点!】

    Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from Person person0_ where person0_.id=?
    Hibernate: select person0_.id as id0_0_, person0_.name as name0_0_ from Person person0_ where person0_.id=?
    Hibernate: update Person set name=? where id=?
    20

    测试getPersons方法(getPerson就不用了)

    Hibernate: select person0_.id as id0_, person0_.name as name0_ from Person person0_
    personname1
    yinger
    personname4
    personname5

    数据库数据保持不变

    从上面的测试中,我们可以看出,Spring 和 Hibernate 整合成功了!

    接下来做 Hibernate中二级缓存的配置

    在beans.xml中关于sessionFactory的配置中添加以下设置,最后如下所示:(假设二级缓存使用的是EhCacheProvider )

            <property name="hibernateProperties">
                <value>
                    hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
                    hibernate.hbm2ddl.auto=update
                    hibernate.show_sql=true
                    hibernate.format_sql=false
                    hibernate.cache.use_second_level_cache=true
                    hibernate.cache.use_query_cache=false
                    hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
                </value>
            </property>

    然后,自然要在Hibernate下载包中找到与EhCache缓存相关的jar包, 添加进去,然后找到EnCache的配置文件:encache.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 
        defaultCache节点为缺省的缓存策略
         maxElementsInMemory 内存中最大允许存在的对象数量
         eternal 设置缓存中的对象是否永远不过期
         overflowToDisk 把溢出的对象存放到硬盘上
         timeToIdleSeconds 指定缓存对象空闲多长时间就过期,过期的对象会被清除掉
         timeToLiveSeconds 指定缓存对象总的存活时间
         diskPersistent 当jvm结束是是否持久化对象
         diskExpiryThreadIntervalSeconds 指定专门用于清除过期对象的监听线程的轮询时间
     -->
    <ehcache>
        <diskStore path="D:\cache"/>
        <defaultCache  maxElementsInMemory="1000" eternal="false" overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="180"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="60"/>
        <cache name="com.yinger.domain.Person" maxElementsInMemory="100" eternal="false"
        overflowToDisk="true" timeToIdleSeconds="300" timeToLiveSeconds="600" diskPersistent="false"/>
    </ehcache>

    如上所示,cache标签中就可以添加需要使用二级缓存的类了

    当然,也可以在类的映射文件中添加,例如在 Person.hbm.xml 中添加:

        <class name="Person">
            <cache usage="read-write" region="com.yinger.domain.Person"/>
            <id name="id">
                <generator class="native" />
            </id>
            <property name="name" />
        </class>

    region的解释:Hibernate为每个实体类创建一个Region作为缓存区, 默认情况下使用类的全路径名做为这个Region的名称

    这样同样可以使得Person可以使用二级缓存

    2.整合Spring 和 Struts2

    ①引入jar包:

    使用到struts2的lib目录下所有不带-plugin结尾的jar文件,但除了struts2-spring-plugin-2.0.11.1.jar

    ②在web容器中实例化spring容器和配置struts2

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
        <!-- 指定spring的配置文件,默认从web根目录寻找配置文件,我们可以通过spring提供的classpath:前缀指定从类路径下寻找 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:beans.xml</param-value>
        </context-param>
        <!-- 对Spring容器进行实例化 -->
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
    
        <!-- 配置struts2:注意struts1和struts2中的filter-class配置是不同的 -->
        <filter>
            <filter-name>struts2</filter-name>
            <!-- 
            <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
             -->
             <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>struts2</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
    </web-app>

    ③配置struts2,编写struts.xml,我这里是包含了另外两个xml文件:

    struts.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    
    <struts>
    
        <include file="strutsconstant.xml"></include>
        <include file="strutspackage.xml"></include>
        
    </struts>

    strutsconstant.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    
    <struts>
    
        <!-- 配置一些常量值 constant -->
        <!-- 通常,struts2按如下搜索顺序加载struts2常量:
            struts-default.xml
            struts-plugin.xml
            struts.xml
            struts.properties
            web.xml
            如果在多个文件中配置了同一个常量,则后一个文件中配置的常量值会覆盖前面文件中配置的常量值.
         -->
        <!-- 指定默认编码集,作用于HttpServletRequest的setCharacterEncoding方法 和freemarker 、velocity的输出 -->
        <constant name="struts.i18n.encoding" value="UTF-8"/>
        <!-- 该属性指定需要Struts 2处理的请求后缀,该属性的默认值是action,即所有匹配*.action的请求都由Struts2处理
            如果用户需要指定多个请求后缀,则多个后缀之间以英文逗号(,)隔开 -->
        <constant name="struts.action.extension" value="action,do"/>
        <!-- 设置浏览器是否缓存静态内容,默认值为true(生产环境下使用),开发阶段最好关闭 -->
        <constant name="struts.serve.static.browserCache" value="false"/>
        <!-- 当struts的配置文件修改后,系统是否自动重新加载该文件,默认值为false(生产环境下使用),开发阶段最好打开 -->
        <constant name="struts.configuration.xml.reload" value="true"/>
        <!-- 开发模式下使用,这样可以打印出更详细的错误信息 -->
        <constant name="struts.devMode" value="true" />
        <!-- 默认的视图主题 -->
        <constant name="struts.ui.theme" value="simple" />
        <!-- 与spring集成时,指定由spring负责action对象的创建 -->
        <constant name="struts.objectFactory" value="spring" />
         <!-- 该属性设置Struts 2是否支持动态方法调用,该属性的默认值是true。如果需要关闭动态方法调用,则可设置该属性为false --> 
        <constant name="struts.enable.DynamicMethodInvocation" value="false"/>
        
    </struts>

    strutspackage.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">
    
    <struts>
    
        <package name="person" namespace="/person" extends="struts-default">
            <global-results>
                <result name="message">/WEB-INF/page/message.jsp</result>
            </global-results>
    <!-- 这里使用了通配符,调用的方法名正是通配符中的字符串,class是交给Spring管理的bean(class名是bean的name或者id) -->
            <action name="action_*" class="personAction" method="{1}">
                <result name="list">/WEB-INF/page/persons.jsp</result>
            </action>
        </package>
    
    </struts>

    ④在Spring的bean管理中添加一个新的bean:

    <bean id="personAction" class="com.yinger.web.action.PersonAction"></bean>

    注意:这个bean的id 对应struts中定义的action中的class名称

    以下是测试:

    ⑤新建action:PersonAction

    package com.yinger.web.action;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    
    import com.yinger.domain.Person;
    import com.yinger.service.PersonService;
    
    public class PersonAction {
        
        //由于这个类已经交给了Spring管理,所以可以使用Spring的依赖注入功能注入personService
        //并且personService也已经交给了Spring管理
        @Resource private PersonService personService;
        private String message;
        private List<Person> persons;
        
        public String list(){
            this.persons = personService.getPersons();
            return "list";
        }
        
        public String getMessage() {
            return message;
        }
        public void setMessage(String message) {
            this.message = message;
        }
        public List<Person> getPersons() {
            return persons;
        }
        public void setPersons(List<Person> persons) {
            this.persons = persons;
        }    
    
    }

    ⑥新建两个jsp,在WEB-INF目录下的page文件夹中

    message.jsp:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>My JSP 'message.jsp' starting page</title>
      </head>
      
      <body>
        <s:property value="message"/>
      </body>
    </html>

    persons.jsp:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib uri="/struts-tags" prefix="s"%>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>人员列表</title>
      </head>
      
      <body>
        <s:iterator value="persons">
            id=<s:property value="id"/>---name=<s:property value="name"/><br/>
        </s:iterator>
      </body>
    </html>

    好了,一切OK!部署应用,然后启动Tomcat服务器(我的是Tomcat 6.0),最好要保证控制台没有报错,不然就要检查!

    2011-8-26 21:59:00 org.apache.catalina.core.AprLifecycleListener init
    信息: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: 
    D:\Program Files\MyEclipse Blue Edition\Common\binary\com.sun.java.jdk.win32.x86_1.6.0.013\bin;D:\Program Files\Tomcat 6.0\bin
    2011-8-26 21:59:00 org.apache.coyote.http11.Http11Protocol init
    信息: Initializing Coyote HTTP/1.1 on http-8080
    2011-8-26 21:59:00 org.apache.catalina.startup.Catalina load
    信息: Initialization processed in 1408 ms
    2011-8-26 21:59:00 org.apache.catalina.core.StandardService start
    信息: Starting service Catalina
    2011-8-26 21:59:00 org.apache.catalina.core.StandardEngine start
    信息: Starting Servlet Engine: Apache Tomcat/6.0.16
    2011-8-26 21:59:04 org.apache.catalina.core.StandardContext addApplicationListener
    信息: The listener "org.springframework.web.context.ContextLoaderListener" is already configured for this context. The duplicate definition has been ignored.
    log4j:WARN No appenders could be found for logger (org.springframework.core.CollectionFactory).
    log4j:WARN Please initialize the log4j system properly.
    2011-8-26 21:59:05 org.apache.catalina.core.ApplicationContext log
    信息: Initializing Spring root WebApplicationContext
    2011-8-26 21:59:19 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
    信息: Parsing configuration file [struts-default.xml]
    2011-8-26 21:59:19 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
    信息: Unable to locate configuration files of the name struts-plugin.xml, skipping
    2011-8-26 21:59:19 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
    信息: Parsing configuration file [struts-plugin.xml]
    2011-8-26 21:59:19 com.opensymphony.xwork2.util.logging.commons.CommonsLogger info
    信息: Parsing configuration file [struts.xml]
    2011-8-26 21:59:21 org.apache.catalina.core.StandardContext addApplicationListener
    信息: The listener "wdlab.base.BSLoginListener" is already configured for this context. The duplicate definition has been ignored.
    2011-8-26 21:59:22 org.apache.coyote.http11.Http11Protocol start
    信息: Starting Coyote HTTP/1.1 on http-8080
    2011-8-26 21:59:22 org.apache.jk.common.ChannelSocket init
    信息: JK: ajp13 listening on /0.0.0.0:8009
    2011-8-26 21:59:22 org.apache.jk.server.JkMain start
    信息: Jk running ID=0 time=0/84  config=null
    2011-8-26 21:59:22 org.apache.catalina.startup.Catalina start
    信息: Server startup in 21866 ms

    打开IE,测试结果: 成功的输出了刚才的数据库中的数据!

    21

    SSH整合成功了!Congratulations!

    最终的项目目录结构如下图所示:

    22

  • 相关阅读:
    for循环计算
    使用for循环签到嵌套制作直角三角形
    使用if和switch制作简单的年龄生肖判断
    Echart设置x轴文字数据不隐藏
    前端可视化-表格-图形-工具
    Vue + Element 中的Echart单线图
    Vue + Element 实现多选框选项上限提示与限定
    前端网(http://www.qdfuns.com/)不能访问了
    JAVA 递归实现从n个数中选取m个数的所有组合
    前端知识点与小练习
  • 原文地址:https://www.cnblogs.com/yinger/p/2153508.html
Copyright © 2020-2023  润新知