SSH整合(Struts2 + Spring + Hibernate)
SSH整合,将Struts2做为web层,Spring作为业务层,Hibernate作为持久层,大致的 情况如下图图解:
1.导入Jar包
整合的第一步,是要创建web项目,并且分别导入三个框架所需要的jar包。
-
Struts2:
Struts2的基本包:
而在Struts2中还有一些特殊的包需要注意:
//使用注解开发Struts2的时候必须要引入这个包
struts2-convention-plugin-2.3.24.jar ----Struts2的注解开发包。
struts2-json-plugin-2.3.24.jar ----Struts2的整合AJAX的开发包。
//引入这个包,可以在web层中方便引用Service层类
struts2-spring-plugin-2.3.24.jar ----Struts2的整合Spring的插件开发包。
-
Hibernate:
Hibernate的基本包:
Mysql驱动包:
日志记录包:
使用C3P0连接池,还需要引入C3P0 jar:
PS:注意:Struts2和Hibernate都引入了一个相同的jar包(javassist包)。删除一个
-
Spring:
IOC开发:
AOP开发:
JDBC模板的开发:
事务管理:
整合web项目开发:
整合单元测试开发:
整合hibernate开发:
2.引入配置文件
- Struts2的配置文件
web.xml : 配置Struts2核心过滤器
<!--Struts2核心过滤器-->
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
struts.xml:配置struts2的常量
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!--配置struts2的常量-->
<constant name="struts.action.extension" value="action"/>
</struts>
-
Hibernate的配置文件
hibernate.cfg.xml:配置数据库连接和C3P0连接池
<?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>
<!-- 连接数据库的基本参数 -->
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/an?characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false</property>
<!-- 配置Hibernate的方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 可选配置================ -->
<!-- 打印SQL -->
<property name="hibernate.show_sql">true</property>
<!-- 格式化SQL -->
<property name="hibernate.format_sql">true</property>
<!-- 自动创建表 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置C3P0连接池 -->
<property name="connection.provider_class">org.hibernate.c3p0.internal.C3P0ConnectionProvider</property>
<!--在连接池中可用的数据库连接的最少数目 -->
<property name="c3p0.min_size">5</property>
<!--在连接池中所有数据库连接的最大数目 -->
<property name="c3p0.max_size">20</property>
<!--设定数据库连接的过期时间,以秒为单位,
如果连接池中的某个数据库连接处于空闲状态的时间超过了timeout时间,就会从连接池中清除 -->
<property name="c3p0.timeout">120</property>
<!--每3000秒检查所有连接池中的空闲连接 以秒为单位-->
<property name="c3p0.idle_test_period">3000</property>
<!-- 引入映射 -->
<mapping resource="ssh/domain/Customer.hbm.xml"/>
</session-factory>
</hibernate-configuration>
映射文件:
- Spring的配置文件
web.xml:配置Spring的核心监听器,初始化的时候创建Spring工厂,并且存放到ServletContext对象中
<!--Spring的核心监听器-->
<listener>
<!--初始化的时候,就会创建一个Spring工厂,并且将其放到ServletContext对象中-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--加载Spring的配置文件路径,默认加载的是/WEB-INF/applicationContext.xml-->
<!--contextConfigLocation这个属性存放的就是配置文件的加载路径-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
applicationContext.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: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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
日志记录:log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.err
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file mylog.log ###
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
# error warn info debug trace
log4j.rootLogger= info, stdout
3.创建包结构
按照MVC三层结构建立包结构:
dao:持久层;domain:模型层
service:业务层;web.action:web层
4.创建相关类
5.引入相关的页面
6.Spring整合Strusts2方式一:Action由Struts2框架创建
引入插件包:struts-spring-plugin.jar
编写CustomerAction类,添加一个save的客户保存方法:
public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
//模型驱动使用的对象
private Customer customer = new Customer () ;
@Override
public Customer getModel() {
return customer;
}
/*
* 保存客户的方法: save
* */
public String save(){
System.out.println("Action中的save方法执行了....");
return null;
}
}
在Struts.xml中配置Action:
在struts2 2.3版本以后为了增加安全性,在action中添加了对方法访问的权限,如果要使用通配符 * 调用方法的话,需要添加额外的代码,不然将会报无法访问的错误
有以下几种解决方法
- 一.在action标签中添加< allowed-methods>标签
< allowed-methods>save< /allowed-methods>
< allowed-methods>方法1,方法2,…< /allowed-methods>
< allowed-methods >regex:*< /allowed-methods>
- 二.在package 标签中添加 global-allowed-methods 标签
< global-allowed-methods>regex:.*< /global-allowed-methods>
- 三.在package 标签上添加strict-method-invocation 属性
strict-method-invocation=“false”
<!--配置action-->
<!--第一种方式,在package上添加strict-method-invocation="false"-->
<package name="SSH1" extends="struts-default" namespace="/" strict-method-invocation="false">
<!--第二种方式,在package中添加 global-allowed-methods-->
<!--<global-allowed-methods>regex:.*</global-allowed-methods>-->
<action name="customer_*" class="ssh.web.action.CustomerAction" method="{1}">
<!--第三种方式在action中添加allowed-methods-->
<!--<allowed-methods >regex:*</allowed-methods>-->
<allowed-methods>save</allowed-methods>
</action>
</package>
在Action中引入Service:
- 传统方式:
//如果web层没有使用struts2,获取业务层的类必须使用下面的方式
WebApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
CustomerService customerService = (CustomerService) applicationContext.getBean("customerService");
-
进行Spring和Struts2的整合:
引入struts-spring-plugin.jar
在插件包的配置文件中有如下一段配置
这段配置会开启一个常量:在Struts2中只要开启这个常量就会引发下面常量生效:
也就是启动Spring的工厂,让Action可以按照名称自动注入Service
所以讲Service交给spring来管理,在applicationContext.xml中配置:
<!--配置service-->
<bean id="customerService" class="ssh.service.impl.CustomerServiceImpl">
</bean>
Action注入Service,所以在CustomerAction中写入:
// 注入service属性
private CustomerService customerService;
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
并且在CustomerAction的save方法中调用service的方法:
public String save(){
System.out.println("Action中的save方法执行了....");
//调用service的方法
customerService.save();
return NONE;
}
运行结果如下:
7.Spring整合Struts2方式二:Action交给Spring管理(推荐)
如果将Action交给spring管理,可以方便以后使用AOP对action进行增强,因为AOP只能对交给spring管理的bean进行增强。
首先也是需要先引入插件包。
-
引入插件包:struts-spring-plugin.jar
-
然后将 action 类交给 Spring 管理
在配置文件applicationContext.xml中
<!--将action交给spring 管理-->
<bean id="customerAction" class="ssh.web.action.CustomerAction" scope="prototype">
<property name="customerService" ref="customerService"/>
</bean>
由于将action交给spring管理,所以我们需要手动注入service。
PS:HIA需要注意的是,在spring 中,创建的bean默认是单例模式的,而我们的action是需要多例模式的,所以需要加上 scope=“prototype” 属性配置
-
然后配置struts.xml,将action中的class值指向spring中创建的bean的id
需要引入插件包以后,才可以这样使用
<action name="customer_*" class="customerAction" method="{1}"></action>
8.Service 调用 Dao
- 将Dao交给Spring管理
<!--配置dao-->
<bean id="customerDao" class="ssh.dao.impl.CustomerDaoImpl">
</bean>
- 同时在Service中定义一个dao,并且注入dao
ServiceImpl:
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
applicationContext.xml:
<!--配置service-->
<bean id="customerService" class="ssh.service.impl.CustomerServiceImpl">
<property name="customerDao" ref="customerDao"/>
</bean>
9.Spring整合Hibernate框架
- 创建表:customer
CREATE TABLE `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_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
`cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
- 编写实体和映射
在编写映射文件之前,还需要先进行DataSource的配置,也就是先建立项目与数据库之间的联系,建立联系的步骤参照下边链接中的原文,建立一个hibernate项目:
https://blog.youkuaiyun.com/sinat_18538231/article/details/77986020
当将项目和数据的连接建立完成以后。
在domian包下新建一个Customer.hbm.xml的映射文件,建立表和实体类的连接:
Customer.hbm.xml:
<?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>
<!-- 建立类与表的映射 -->
<class name="ssh.domain.Customer" table="customer">
<!-- 建立类中的属性与表中的主键对应 -->
<id name="cust_id" column="cust_id" >
<!-- 主键生成策略 -->
<generator class="native"/>
</id>
<!-- 建立类中的普通的属性和表的字段的对应 -->
<property name="cust_name" column="cust_name" />
<property name="cust_source" column="cust_source" />
<property name="cust_industry" column="cust_industry"/>
<property name="cust_level" column="cust_level"/>
<property name="cust_phone" column="cust_phone"/>
<property name="cust_mobile" column="cust_mobile"/>
</class>
</hibernate-mapping>
同时在hibernate的配置文件,hibernate.cfg.xml中添加映射:
<!-- 引入映射 -->
<mapping resource="ssh/domain/Customer.hbm.xml"/>
- Spring和Hibernate整合
在Spring的配置文件中,引入Hibernate的配置的信息
<!--spring整合hibernate-->
<!--引入hibernate的配置的信息-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<!--引入hibernate的配置文件-->
<property name="configLocation" value="classpath:hibernate.cfg.xml"></property>
</bean>
在Spring和Hibernate整合后,Spring提供了一个Hibernate的模板类简化Hibernate开发。
改写DAO继承HibernateDaoSupport:
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save() {
System.out.println("dao中的save方法被调用了...");
}
}
由于Dao继承了HibernateDaoSupport,所以配置的时候在Dao中直接注入SessionFactory属性
注入sessionFactory就会自动创建Hibernate模板,是在HibernateDaoSupport源码中的setsessionFactory方法中写好的。
<!--配置dao-->
<bean id="customerDao" class="ssh.dao.impl.CustomerDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
最后在dao中使用hibernate模板完成保存操作
10.配置spring的事务管理
在spring配置文件中配置事务管理器:
- 配置事务管理器
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<!--要开启事务,就要获得连接,类似于DataSource的连接池,sessionFactory-->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
- 开启注解式事务
<!--开启注解式的事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>
- 在业务层Service使用注解事务
@Transactional
public class CustomerServiceImpl implements CustomerService {
}
总结
SSH框架整合方式一:带hibernate配置文件 的步骤总结
-
创建项目,引入SSH三大框架的jar包
-
引入三个框架的配置文件(applicationContext.xml,struts.xml,hibernate.cfg.xml)
-
创建包结构
-
创建相关类
-
引入页面
-
编写Action,配置Action
-
编写Service,并交给Sprign管理
-
Spring和Strust2的整合方式一:Action由Struts2创建
- 引入一个插件包:struts2-spring-plugin-2.3.24.jar
- Action中提供Service的set方法
-
Spring和Strust2的整合方式二: Action交给Spring创建
-
引入一个插件包:struts2-spring-plugin-2.3.24.jar
-
将Action配置到Spring中
-
在struts2中配置Action的class的时候,class中写的是Spring的Action的类的id
-
注意:
- Action是多例的,要在bean标签中设置,scope=“prototype”
- 手动注入Srevice
-
-
Service调用Dao
-
Spring整合hibernate
- 编写Dao继承HibernateDaoSupport
- 编写hibernate模板
-
Spring的事务管理配置
延迟加载问题解决:将Session在web层开启和关闭。