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 (?)
数据库中的数据
测试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=?
测试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 20](https://i-blog.csdnimg.cn/blog_migrate/1fe8772a040d3e9f2c51480b607802b0.png)
测试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,测试结果: 成功的输出了刚才的数据库中的数据!
SSH整合成功了!Congratulations!
最终的项目目录结构如下图所示: