以前有做过S2SH框架的开发,但一直没有去弄清楚整个配置的过程,最近需要做相关的开发,借着这次机会好好的整理了一下,并记录下来方便如后翻查使用。
在配置的过程中参考了很多文章,若本文最后提到的参考文章中有遗漏,望见谅。
S2SH框架整合配置
1. 开发环境
Eclipse、JDK、Tomcat7、Struts2、Spring、Hibernate
2. 下载包
Struts
http://struts.apache.org/download.cgi#struts216
Spring
Hibernate
http://hibernate.org/orm/downloads/
3. 在Eclipse中搭建开发环境,首先是Struts部分
打开Eclipse,new->project->Dynamic Web Project,弹出如下窗框,按要求填写,然后下一步到finish
3.1首先要配置Struts,引入struts2的包
3.2在web.xml中配置struts
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<!-- 定义Struts2的FilterDispathcer的Filter -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<!-- FilterDispatcher用来初始化struts2并且处理所有的WEB请求。 -->
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
3.3在src目录下添加struts.xml,并写入如下内容
<?xml version="1.0"encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD StrutsConfiguration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!--<package name="struts2"extends="struts-default">
<action name="struts2Test"class="org.acm.ccmap.TestAction" method="test">
<result name="success">/index1.jsp</result>
</action>
</package> -->
</struts>
至此Struts框架配置完毕
4. Hibernate部分
4.1 在项目中导入所需JAR包
根据官方文档的描述The lib/required/
directorycontains all the JARs Hibernate requires. All the jars in this directory mustalso be included in your project's classpath.于是,把从官网下载得的hibernate-release-4.2.8.Final中的lib/required/
下的所有
jar
包都导入项目中
4.2在项目的src目录下创建hibernate的配置文件,hibernate.cfg.xml,此配置文
要因应项目所使用的数据库进行不同的配置,由于在下的项目是使用Mysql的,因此配置如下
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/testsql
</property>
<property name="myeclipse.connection.profile">MySQL</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="show_sql">true</property>
<!-- 将User.hbm.xml加入到配置文件中 -->
<mapping resource="org/acm/ccmap/domain/User.hbm.xml" />
</session-factory>
</hibernate-configuration>
4.3创建实体类,
package org.acm.ccmap.domain;
public class User {
private String id;
private String userName;
private int age;
private String address;
private String phone;
。。。忽略setter、getter
}
4.4接着需要给实体类和数据库做一个映射,使用User.hbm.xml文件进行映射
<id name=”id”>这个属性的意思为主键,标签中的name代表实体类中的属性名
<?xml version="1.0"encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/HibernateMapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="org.acm.ccmap.domain.User">
<!-- 标签中的name代表实体类中的名字 -->
<id name="id">
<generator class="uuid"/>
</id>
<property name="userName"/>
<property name="age"/>
<property name="address"/>
<property name="phone"/>
</class>
</hibernate-mapping>
4.5将User.hbm.xml加入到hibernate的配置文件中,通过mapping标签引入
<!-- 将User.hbm.xml加入到配置文件中 -->
<mapping resource="org/acm/ccmap/domain/User.hbm.xml" />
4.6至此,配置完成,由于Hibernate实质上是对JDBC进行封装,在连接数据库的时候,也需要引入数据库厂商提供的驱动,这里使用的是mysql,引入mysql-connector-java-5.1.6-bin.jar包。
然后,可以写一个工具类,通过写好的实体类,用Hibernate生成数据库的表
public class TestHibernate {
public static void main(String[] args) {
Configuration con = newConfiguration().configure();
SchemaExport export = newSchemaExport(con);
export.create(true, true);
}
}
既然可以单独使用Hibernate的代码操作数据库,那么,在实际开发时,可以独立的测试某一个层的代码(Hibernate属于数据访问层)
Hibernate部分配置基本完成,项目结构如下:
Hibernate部分配置完毕
5. Spring部分
5.1导入Spring包,把spring-framework-3.2.6.RELEASE中lib里的jar包都放到项目中(这样做是不太好的,后续必须搞清楚每个包起什么作用),到此,项目中的lib如图
5.2在webl.xml文件,配置Spring
<!--
* 从类路径下加载spring的配置文件, 多个配置文件可以用逗号和空格区分
* classpath: 关键字特指类路径下加载-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:spring/applicationContext*.xml
</param-value>
</context-param>
在这里,指定了spring配置文件的路径,即WEB-INF/classes/spring目录下的所有以applicationContext开头命名的xml文件。
5.3在src目录下新建applicationContext.xml文件,并加上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-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
</beans>
注意:标头是2.5的不要引入2.0,错了可能Spring就不能正确加载。
5.4示例测试Spring
到此,Spring基本配置完成,下面将会建个示例测试。
建两个类,TUser.java/SpringTest.java
package org.acm.ccmap.testspring;
public class TUser implements java.io.Serializable {
private String username;
private String allname;
private String address;
此处忽略setter、getter
}
package org.acm.ccmap.service;
import org.acm.ccmap.testspring.TUser;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringTest {
public static void main(String[] args) {
// 加载spring配置文件,初始化IoC容器
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
// 从容器 接管Bean
TUser user = (TUser) ac.getBean("TUser");
// 输出欢迎信息
System.out.println("Hello:" + user.getUsername() +";u is in "
+ user.getAddress() + " ; and u is " + user.getAllname());
}
}
创建完毕后,在applicationContext.xml中配置一个bean,增加代码如下
<bean id="TUser"class="org.acm.ccmap.testspring.TUser">
<property name="username"value="小张"></property>
<property name="allname"value="张三"></property>
<property name="address"value="青岛市"></property>
</bean>
接着,右击SpringTest.java选择run as JavaApplication,得出结果如下
若出现异常,根据异常信息,自行解决。如果解决跟上图一样,则说明Spring部分配置完成。
Spring部分配置完毕
经过上面的步骤,已经把Struts、Hibernate、Spring各自配置完成,接下来是重点,Spring和Struts、Hibernate的整合配置。
6. Spring整合Struts
Spring与Struts的整合其实就是把Struts的Action类交给Spring管理
6.1导入jar包,在struts-2.3.15.1的lib找到struts2-spring-plugin-2.3.15.1.jar,引入工程
6.2配置web.xml,在web.xml中添加如下代码
<!-- 用于初始化Spring容器的Listener -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
6.3然后就是实现如何把Struts的action交给Spring。以上述Struts示例中的struts2Test.action(TestAction.java)为例。
首先,在applicationContext.xml中创建TestAction.java类的Bean,
<!-- Action -->
<bean id="TestAction" class="org.acm.ccmap.action.TestAction"
scope="prototype"></bean>
这里,我们把这个bean的id设为TestAction(对应Struts.xml中class属性的值)。Scope设为prototype,含义是每一次请求创建一个TestAction.java类的实例,Scope还有另一个值“singleton”意为“单例模式”
接着,修改struts.xml文件,
把
<action name="struts2Test"class="org.acm.ccmap.action.TestAction" method="test">
<result name="success" >/index1.jsp</result>
</action>
改为
<action name="struts2Test"class="TestAction" method="test">
<result name="success" >/index1.jsp</result>
</action>
请仔细观察上两段代码的区别,class值设为TestAction,即TestAction类的bean的id值。这样Struts的TestAction类就交给了Spring管理,具体是怎么处理,秘密在于struts2-spring-plugin-2.3.15.1.jar,想要了解更多,就自行研究吧,现在首要是学会怎么用。
7. Spring整合Hibernate
Spring整合Hibernate主要是对hibernate的Session进行管理,包括Session的创建、提交、关闭的整个生命周期。Spring对事物的管理应用了AOP技术,配置前请先了解AOP的知识。由于在练习配置的过程中发现,Spring是不可以访问Hibernate配置的数据源的,因此,最终采用的配置方法是丢弃hibernate.cfg.xml配置文件,把数据源的配置移到Spring中
7.1在applicationContext中配置数据源bean,使用C3P0数据源实现,增加如下代码
<!-- 定义数据源Bean,使用C3P0数据源实现 –>
<!-- C3p0数据源,做成了单例模式 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"value="org.gjt.mm.mysql.Driver" />
<property name="jdbcUrl"
value="jdbc:mysql://localhost:3306/testsql?useUnicode=true&characterEncoding=UTF-8"/>
<property name="user"value="root" />
<property name="password"value="123456" />
<!-- <propertyname="idleConnectionTestPeriod" value="120" /> -->
<!-- 初始化时获取的链接数,取值应在minPoolSize与maxPoolSize之间。Default:3 -->
<property name="initialPoolSize"value="2" />
<!-- 连接池中保留的最小连接数 -->
<property name="minPoolSize"value="1" />
<!-- 连接池中保留的最大连接数。Default:15 -->
<property name="maxPoolSize"value="20" />
<!-- 最大空闲时间,120秒内未使用则连接被丢弃。右为0则永不丢弃。Default:0 -->
<property name="maxIdleTime"value="120" />
<!-- 当连接池中的连接耗尽时,c3p0一次同时获取的连接数。Default:3 -->
<property name="acquireIncrement"value="5" />
<!-- 每60秒检查所有连接池中的空闲连接。Default:0 -->
<property name="idleConnectionTestPeriod"value="60" />
</bean>
因为使用了C3P0数据源,因而需要导入相应的包,在hibernate-release-4.2.8.Final\lib\optional\c3p0下能够找到需要的包
7.2 配置sessionFactory,让Spring来创建SessionFactory,applicationContext.xml增加代码如下:
<!-- 定义数据源Bean,使用C3P0数据源实现 -->
<!-- 设置连接数据库的驱动、URL、用户名、密码
连接池最大连接数、最小连接数、初始连接数等参数 -->
<!-- C3p0数据源,做成了单例模式 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass"value="org.gjt.mm.mysql.Driver" />
<property name="jdbcUrl"
value="jdbc:mysql://localhost:3306/testsql?useUnicode=true&characterEncoding=UTF-8"/>
<property name="user"value="root" />
<property name="password"value="123456" />
<!-- <propertyname="idleConnectionTestPeriod" value="120" /> -->
<!-- 初始化时获取的链接数,取值应在minPoolSize与maxPoolSize之间。Default:3 -->
<property name="initialPoolSize"value="2" />
<!-- 连接池中保留的最小连接数 -->
<property name="minPoolSize"value="1" />
<!-- 连接池中保留的最大连接数。Default:15 -->
<property name="maxPoolSize"value="20" />
<!-- 最大空闲时间,120秒内未使用则连接被丢弃。右为0则永不丢弃。Default:0 -->
<property name="maxIdleTime"value="120" />
<!-- 当连接池中的连接耗尽时,c3p0一次同时获取的连接数。Default:3 -->
<property name="acquireIncrement"value="5" />
<!-- 每60秒检查所有连接池中的空闲连接。Default:0 -->
<property name="idleConnectionTestPeriod"value="60" />
</bean>
7.3配置事务管理器,增加代码如下
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
这里创建了一个id为transactionManager的事务管理器,它匹配一个session工厂,<refbean="sessionFactory"/>这个sessionFactory是指session工厂的ID。
以下7.4、7.5是未经测试的
7.4对事务管理器进行事务设置,增加代码如下
<tx:advice id="smAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="del*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
这里创建了一个advice(通知),对事务管理器进行事务设置,这里意思是指,对于以save、del、update开头的方法应用事务。
7.5 下面就把事务应用到具体的类。看如下代码:
<aop:config>
<aop:pointcut id="smMethod"
expression="execution(* test.service.impl.*.*(..))"/>
<aop:advisor pointcut-ref="smMethod" advice-ref="smAdvice"/>
</aop:config>
这里配置的作用是把我们上面创建的advice应用到具体的类中。以上代码的意思指,给test.service.impl下的所有类的所有方法应用smAdvice。
完成步骤7.3的配置,Spring和Hibernate的整合已经基本完成,接下来就测试以下是否配置成功。
创建一个类,代码如下:
import org.acm.ccmap.domain.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
//import org.hibernate.cfg.Configuration;
//import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
public class TestHibernate {
public static void main(String[] args){
// ---start
// 这里是测试Hibernate框架是否配置成功的代码
// Configuration con = newConfiguration().configure();
// SchemaExport export = new SchemaExport(con);
//
// export.create(true, true);
// ---end
// ---start
// 测试Spring和Hibernate整合是否成功
// 加载spring配置文件,初始化IoC容器
ApplicationContext ac = new ClassPathXmlApplicationContext(
"applicationContext.xml");
//通过Spring的Bean,实例化SessionFactory
SessionFactory sf = (SessionFactory)ac.getBean("sessionFactory");
//实例化Session
Session sess = sf.openSession();
//开始事务
Transaction tx = sess.beginTransaction();
//
User user = new User();
//
user.setId(0);
user.setUserName("haha");
user.setPhone("135720377392");
user.setAge(14);
user.setAddress("番禺区大学城外环西路");
//保存消息
sess.save(user);
//提交事务
tx.commit();
//关闭session
sess.close();
// ---end
}
}
由于懒得新建一个类,这里直接在上面测试Hibernate配置情况的类中修改代码进行测试了。
注意:Transaction 这个类引用的包是org.hibernate.Transaction;别选错了,否则会报错的
参考文章
http://blog.csdn.net/kingson_wu/article/details/9108471
http://blog.csdn.net/okmntf/article/details/8683537