SSH 框架整合
前言: 有人说, 现在还是流行主流框架, SSM 都出来很久了, 更不要说 SSH. 我不以为然. 现在许多公司所用的老项目还是 ssh, 如果改成主流框架, 需要成本. 再说比如金融 IT 这一块, 数据库 dao 层还是推荐使用的是 hibernate, 因为能够快速开发上手, 除非是互联网, 因涉及到高并发, dao 层用的是 mybatis, 数据交互效率较快. 所以, SSH 不容忽略.
一, 什么是 SSH
SSH 是 struts+spring+hibernate 的一个集成框架, 是目前比较流行的一种 Web 应用程序开源框架.
集成 SSH 框架的系统从职责上分为四层: 表示层, 业务逻辑层, 数据持久层和域模块层, 以帮助开发人员在短期内搭建结构清晰, 可复用性好, 维护方便的 Web 应用程序. 其中使用 Struts 作为系统的整体基础架构, 负责 MVC 的分离, 在 Struts 框架的模型部分, 控制业务跳转, 利用 Hibernate 框架对持久层提供支持, Spring 做管理, 管理 struts 和 hibernate. 具体做法是: 用面向对象的分析方法根据需求提出一些模型, 将这些模型实现为基本的 Java 对象, 然后编写基本的 DAO(Data Access Objects) 接口, 并给出 Hibernate 的 DAO 实现, 采用 Hibernate 架构实现的 DAO 类来实现 Java 类与数据库之间的转换和访问, 最后由 Spring 做管理, 管理 struts 和 hibernate.
--------- 百度百科
二, SSH 所涉及的部分
三, 快速部署环境
这里利用保存客户的小 Demo 来演示整合 SSH
1. 导入所需 jar 包
1). Struts2 框架
* struts-2.3.24\apps\struts2-blank\WEB-INF\lib\*.jar -- Struts2 需要的所有 jar 包
* struts2-spring-plugin-2.3.24.jar ---Struts2 整合 Spring 的插件包
2). Hibernate 框架
* hibernate-release-5.0.7.Final\lib\required\*.jar -- Hibernate 框架需要的 jar 包
* slf4j-api-1.6.1.jar -- 日志接口
* slf4j-log4j12-1.7.2.jar -- 日志实现
* mysql-connector-java-5.1.7-bin.jar -- MySQL 的驱动包
3). Spring 框架
* IOC 核心包
* AOP 核心包
* JDBC 模板和事务核心包
* Spring 整合 JUnit 测试包
* Spring 整合 Hibernate 核心包
* Spring 整合 Struts2 核心包
2, 在 web.xml 中配置 spring 与 struts 的相关代码
1) 配置 struts2 核心过滤器
这里定义为拦截所有
- <!-- 配置核心过滤器 -->
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- 2) 配置 spring 的监听器
- 当服务启动时, 就会先加载 spring 的配置文件
- <!-- 配置 Spring 框架整合 WEB 的监听器 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- 3) 配置默认加载路径
- <!-- 监听器默认加载 Web-INF 文件下, 需要配置参数来加载指定文件 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:applicationContext.xml</param-value>
- </context-param>
- 总结: web.xml 全部代码为
- <!-- 配置 Spring 框架整合 WEB 的监听器 -->
- <listener>
- <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
- </listener>
- <!-- 监听器默认加载 Web-INF 文件下, 需要配置参数来加载指定文件 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:applicationContext.xml</param-value>
- </context-param>
- <!-- 配置核心过滤器 -->
- <filter>
- <filter-name>struts2</filter-name>
- <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>struts2</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
- 2,src 下编写相关配置文件
- 1)spring: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>
- 2)hibernate:hibernate.cfg.xml
- 导入相关约束, 并配置数据库
- <?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.jdbc.Driver</property>
- <property name="hibernate.connection.url">jdbc:mysql://192.168.174.130:3306/SSH</property>
- <property name="hibernate.connection.username">root</property>
- <property name="hibernate.connection.password">root</property>
- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
- <!-- 可选配置 -->
- <property name="hibernate.show_sql">true</property>
- <property name="hibernate.format_sql">true</property>
- <property name="hibernate.hbm2ddl.auto">update</property>
- <!-- 配置 C3P0 的连接池 -->
- <property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
- <!-- 不能配置绑定当前的线程的操作 -->
- <!-- 映射配置文件 -->
- <mapping resource="com/clj/domain/Customer.hbm.xml"/>
- </session-factory>
- </hibernate-configuration>
- 3) 配置 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.file=org.apache.log4j.FileAppender
- log4j.appender.file.File=c\:mylog.log
- log4j.appender.file.layout=org.apache.log4j.PatternLayout
- log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
- ### set log levels - for more verbose logging change 'info' to 'debug' ###
- log4j.rootLogger=info, stdout
- 4)struts2:struts.xml
- 导入相关约束
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
- <struts>
- </struts>
- 总结: src 所需配置文件如图
- 3, 配置 dao 层
- 定义一个接口和其实现类
- public interface CustomerDao {
- public void save(Customer customer);
- }
- public class CustomerDaoImpl implements CustomerDao {
- public void save(Customer customer) {
- }
- }
- 4, 定义业务层接口和实现类
- package com.clj.service;
- import com.clj.domain.Customer;
- public interface CustomerService {
- public void save(Customer customer);
- }
- package com.clj.service;
- import org.springframework.transaction.annotation.Transactional;
- import com.clj.dao.CustomerDao;
- import com.clj.domain.Customer;
- /**
- * 客户的业务层
- * @author Administrator
- *
- */
- public class CustomerServiceImpl implements CustomerService{// 用来保存客户
- public void save(Customer customer) {
- }
- }
- 5, 定义 pojo 类
- hibernate 通过操作 pojo 类来操作数据库表, 做到对象关系映射
- package com.clj.domain;
- public class Customer {
- private Long cust_id;
- private String cust_name;
- private Long cust_user_id;
- private Long cust_create_id;
- private String cust_source;
- private String cust_industry;
- private String cust_level;
- private String cust_linkman;
- private String cust_phone;
- private String cust_mobile;
- public Long getCust_id() {
- return cust_id;
- }
- public void setCust_id(Long cust_id) {
- this.cust_id = cust_id;
- }
- public String getCust_name() {
- return cust_name;
- }
- public void setCust_name(String cust_name) {
- this.cust_name = cust_name;
- }
- public Long getCust_user_id() {
- return cust_user_id;
- }
- public void setCust_user_id(Long cust_user_id) {
- this.cust_user_id = cust_user_id;
- }
- public Long getCust_create_id() {
- return cust_create_id;
- }
- public void setCust_create_id(Long cust_create_id) {
- this.cust_create_id = cust_create_id;
- }
- public String getCust_source() {
- return cust_source;
- }
- public void setCust_source(String cust_source) {
- this.cust_source = cust_source;
- }
- public String getCust_industry() {
- return cust_industry;
- }
- public void setCust_industry(String cust_industry) {
- this.cust_industry = cust_industry;
- }
- public String getCust_level() {
- return cust_level;
- }
- public void setCust_level(String cust_level) {
- this.cust_level = cust_level;
- }
- public String getCust_linkman() {
- return cust_linkman;
- }
- public void setCust_linkman(String cust_linkman) {
- this.cust_linkman = cust_linkman;
- }
- public String getCust_phone() {
- return cust_phone;
- }
- public void setCust_phone(String cust_phone) {
- this.cust_phone = cust_phone;
- }
- public String getCust_mobile() {
- return cust_mobile;
- }
- public void setCust_mobile(String cust_mobile) {
- this.cust_mobile = cust_mobile;
- }
- @Override
- public String toString() {
- return "Customer [cust_id=" + cust_id + ", cust_name=" + cust_name
- + ", cust_user_id=" + cust_user_id + ", cust_create_id="
- + cust_create_id + ", cust_source=" + cust_source
- + ", cust_industry=" + cust_industry + ", cust_level="
- + cust_level + ", cust_linkman=" + cust_linkman
- + ", cust_phone=" + cust_phone + ", cust_mobile=" + cust_mobile
- + "]";
- }
- }
- 6, 定义 Customer.hbm.xml
- 此配置文件关乎 Customer 这个 pojo 类, 此文件需放在 Customer pojo 类同个包下
- <?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="com.clj.domain.Customer" table="cst_customer">
- <id name="cust_id" column="cust_id">
- <generator class="native"/>
- </id>
- <property name="cust_name" column="cust_name"/>
- <property name="cust_user_id" column="cust_user_id"/>
- <property name="cust_create_id" column="cust_create_id"/>
- <property name="cust_source" column="cust_source"/>
- <property name="cust_industry" column="cust_industry"/>
- <property name="cust_level" column="cust_level"/>
- <property name="cust_linkman" column="cust_linkman"/>
- <property name="cust_phone" column="cust_phone"/>
- <property name="cust_mobile" column="cust_mobile"/>
- </class>
- </hibernate-mapping>
- 项目构建大致图
- 四, demo 之保存客户初步演示
- 这里先初略的定义持久层交给 heibernate, 业务层交个 struts2, 创建实例交给 spring
- 1, 定义一个保存客户的界面, 利用 form 表单进行数据的提交
- 根据域名可知, 这里利用的是 struts2 的通配符方式进行访问
- <FORM id=form1 name=form1
- action="${pageContext.request.contextPath }/customer_add.action"
- method=post>
- <!--table 部分省略 -->
- </FORM>
- 2, 在 struts.xml 中配置接受请求, 根据 action 名和方法跳转指定的 action, 执行指定的方法
- spring 整合 struts2 方式一: action 由 struts2 框架管理
- * 因为导入的 struts2-spring-plugin-2.3.24.jar 包自带一个配置文件 struts-plugin.xml , 该配置文件中有如下代码
- * <constant name="struts.objectFactory" value="spring" /> 开启一个常量, 如果该常量开启, 那么下面的常量就可以使用
- * struts.objectFactory.spring.autoWire = name, 该常量是可以让 Action 的类来自动装配 Bean 对象!
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE struts PUBLIC
- "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN"
- "http://struts.apache.org/dtds/struts-2.3.dtd">
- <struts>
- <!-- 配置包结构 -->
- <package name="crm" extends="struts-default" namespace="/">
- <!-- 配置客户的 Action -->
- <!-- 方式一: aciton 由 struts2 框架管理 -->
- <action name="customer_*" class="com.clj.web.action.CustomerAction" method="{1}"/>
- </package>
- </struts>
- 3, 在 spring 的 applicationContext.xml 中配置相对应的 bean 以及事务
- 这里利用 spring 中 IOC(控制反转) 的特性, 将创建实例的任务交给 spring 框架管理
- <bean id="customerService" class="com.clj.service.CustomerServiceImpl">
- <property name="customerDao" ref="customerDao">
- </property>
- </bean>
- <bean id="customerDao" class="com.clj.dao.CustomerDaoImpl">
- <property name="hibernateTemplate" ref="hibernateTemplate" />
- </bean>
- <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
- <!-- 注入 sessionFactory -->
- <property name="sessionFactory" />
- </bean>
- </beans>
- 4, 编写持久层实现类相关代码
- 这里利用 hibernate 提供的模板类, 内部封转了 session, 从而可以调用 session 中的方法
- /**
- * 持久层
- *
- * @author Administrator
- *
- */
- public class CustomerDaoImpl implements CustomerDao {
- // 将数据保存到数据库中 (调用模板类 (hibernate 提供, 内部封装了 session))
- private HibernateTemplate hibernateTemplate;
- public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
- this.hibernateTemplate = hibernateTemplate;
- }
- /**
- * 保存客户
- */
- public void save(Customer customer) {
- System.out.println("持久层: 保存客户");
- hibernateTemplate().save(customer);
- }
- }
- 5, 编写业务层实现类相关代码
- package com.clj.service;
- import org.springframework.transaction.annotation.Transactional;
- import com.clj.dao.CustomerDao;
- import com.clj.domain.Customer;
- /**
- * 客户的业务层
- * @author Administrator
- *
- */
- @Transactional
- public class CustomerServiceImpl implements CustomerService{
- private CustomerDao customerDao;
- public void setCustomerDao(CustomerDao customerDao) {
- this.customerDao = customerDao;
- }
- // 用来保存客户
- public void save(Customer customer) {
- System.out.println("业务层, 保存客户");
- customerDao.save(customer);
- }
- }
- 6, 编写 action 相关代码
- 这里通过 struts2 的模板类
- package com.clj.web.action;
- import org.apache.struts2.ServletActionContext;
- import org.springframework.web.context.WebApplicationContext;
- import org.springframework.web.context.support.WebApplicationContextUtils;
- import com.clj.domain.Customer;
- import com.clj.service.CustomerService;
- import com.opensymphony.xwork2.ActionSupport;
- import com.opensymphony.xwork2.ModelDriven;
- /**
- * 客户的控制层
- * @author Administrator
- *
- */
- public class CustomerAction extends ActionSupport implements ModelDriven <Customer> {
- // 不要忘记手动 new
- private Customer customer = new Customer();
- public Customer getModel() {
- return customer;
- }
- // 提供 service 成员属性, 提供 set 方法
- private CustomerService customerService;
- public void setCustomerService(CustomerService customerService) {
- this.customerService = customerService;
- }
- /**
- * 保存客户
- * @return
- */
- public String add() {
- System.out.println("WEB 层, 保存客户");
- // 方式一: 创建 web 的工厂 (action 由 struts2 创建)
- WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
- CustomerService cs = (CustomerService) context.getBean("customerService");
- // 调用方法
- cs.save(customer);
- return NONE;
- }
- }
- 五, 项目优化之整合
- 1, spring 整合 struts2 方式二: action 由 spring 框架管理
- 把具体的 Action 类配置文件 applicatonContext.xml 的配置文件中, 但是注意: struts.xml 需要做修改
- <struts>
- <!-- 配置包结构 -->
- <package name="crm" extends="struts-default" namespace="/">
- <!-- 配置客户的 Action -->
- <!-- 方式一: aciton 由 struts2 框架管理
- <action name="customer_*" class="com.clj.web.action.CustomerAction" method="{1}"/>-->
- <!-- 方式二: action 由 spring 管理, class 标签上只需要编写 srping 配置 bean 的 ID 值既可以 -->
- <action name="customer_*" class="customerAction" method="{1}"></action>
- </package>
- </struts>
- 2, 在 applicationContext.xml 中配置 Action 类
- 注意: 1)Spring 框架默认生成 CustomerAction 是单例的, 而 Struts2 框架是多例的. 所以需要配置 scope="prototype"
- 2) 此时没有 struts2 的自动装配, 在 action 需要手动配置 customerService 属性, 并在 action 类中生成 set 方法
- <!-- 配置客户模块 -->
- <!-- 强调: 配置的 Aciton, 必须是多列的 -->
- <bean id="customerAction" class="com.clj.web.action.CustomerAction" scope="prototype">
- <!-- 注意: struts 管理 action 时, 基于其中有个 struts-plugin 的 jar 包, 其中更改了一个
- 常量 struts.objectFactory.spring.autoWire = name 将其打开了, 可以自动装配, 只需要提供 set 方法
- 但是此时 action 由 spring 管理, 自动装配失效, 所以需要手动进行配置注入
- -->
- <property name="customerService" ref="customerService"></property>
- </bean>
- 3,. 配置事务
- spring 整合 hibernate 方式一:(带有 hibernate.cfg.xml 的配置文件. 强调: 不能加绑定当前线程的配置)
- 以前玩 hibernate 时, hibernate.cfg.xml 都是由 hibernate 框架管理, 其配置文件能生成 sessionFactory, 持久层加载此配置文件获取 sessionFactory, 从而创建工厂生成 session, 进行数据的增删改成, 此时其配置文件应该交给 spring 管理, 充分利用 spring 的 IOC 特性
- Spring 框架提供了一个 HibernateDaoSupport 的工具类, 以后 DAO 都可以继承该类!! 在引入 hibernate 核心配置文件之前, 得让 dao 层继承一个父类 HibernateDaoSupport, 此父类内部封装了事务模板
- 看源码:
- 1) 修改相对应的持久层实现类, 让他继承 HibernateDaoSupport
- package com.clj.dao;
- import org.springframework.orm.hibernate5.HibernateTemplate;
- import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
- import com.clj.domain.Customer;
- /**
- * 持久层
- * 继承 HibernateDaoSupport, 内部封装了 HibernateTemplate
- * @author Administrator
- *
- */
- public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
- // 将数据保存到数据库中 (调用模板类 (hibernate 提供, 内部封装了 session))
- /*private HibernateTemplate hibernateTemplate;
- public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
- this.hibernateTemplate = hibernateTemplate;
- }*$**
- * 保存客户
- */
- public void save(Customer customer) {
- System.out.println("持久层: 保存客户");
- this.getHibernateTemplate().save(customer);
- }
- }
2) 修改业务层让, 开启事务注解
- package com.clj.service;
- import org.springframework.transaction.annotation.Transactional;
- import com.clj.dao.CustomerDao;
- import com.clj.domain.Customer;
- /**
- * 客户的业务层
- * @author Administrator
- *
- */
- @Transactional
- public class CustomerServiceImpl implements CustomerService{
- private CustomerDao customerDao;
- public void setCustomerDao(CustomerDao customerDao) {
- this.customerDao = customerDao;
- }
- // 用来保存客户
- public void save(Customer customer) {
- System.out.println("业务层, 保存客户");
- customerDao.save(customer);
- }
- }
3) 修改 applicationContext.xml 文件
先引入 hibernate 配置文件
- <!-- 编写 bean, 名称都是固定的, 由 spring 提供, 用来加载 hibernate.cfg.xml 的配置文件 -->
- <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
- <!-- 配置路径: 当启动服务器时 , 该对象就会被创建, 从而加载 hibernate.cfg.xml 文件, 从而生成 sessionFactory 对象 -->
- <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
- </bean>
配置平台事务管理: 用来管理事务, 注意现在使用的是 Hibernate 框架, 所以需要使用 Hibernate 框架的事务管理器
- <!-- 先配置平台事务管理器 -->
- <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
- <!-- 注入事务, session 能够管理事务, 工厂能够创建 session -->
- <property name="sessionFactory" ref="sessionFactory"/>
- </bean>
开启事务注解
- <!-- 开启事务的注解 -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
去除模板类配置, 并为持久层配置 sessionFactory
- <!-- 以后, Dao 都需要继承 HibernateDaoSupport, 注入 sessionFactory -->
- <bean id="customerDao" class="com.clj.dao.CustomerDaoImpl">
- <!--<property name="hibernateTemplate" ref="hibernateTemplate"/>-->
- <!-- 这里不注入模板类, 而是注入 sessionFactory, 因为模板需要 session(封装了 session)-->
- <property name="sessionFactory" ref="sessionFactory"/>
- </bean>
全部代码如下
- <?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">
- <!-- 编写 bean, 名称都是固定的, 有 spring 提供, 用来加载 hibernate.cfg.xml 的配置文件 -->
- <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
- <!-- 配置路径: 当启动服务器时 , 该对象就会被创建, 从而加载 hibernate.cfg.xml 文件, 从而生成 sessionFactory
- 对象 -->
- <property name="configLocation" value="classpath:hibernate.cfg.xml" />
- </bean>
- <!-- 先配置平台事务管理器 -->
- <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
- <!-- 注入事务, session 能够管理事务, 工厂能够创建 session -->
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <!-- 开启事务的注解 -->
- <tx:annotation-driven transaction-manager="transactionManager" />
- <!-- 配置客户模块 -->
- <!-- 强调: 配置的 Aciton, 必须是多列的 -->
- <bean id="customerAction" class="com.clj.web.action.CustomerAction" scope="prototype">
- <!-- 注意: struts 管理 action 时, 基于其中有个 struts-plugin 的 jar 包, 其中更改了一个 常量
- struts.objectFactory.spring.autoWire=n ame 将其打开了, 可以自动装配, 只需要提供 set 方法
- 但是此时 action 由 spring 管理, 自动装配失效, 所以需要手动进行配置注入 -->
- <property name="customerService" ref="customerService">
- </property>
- </bean>
- <bean id="customerService" class="com.clj.service.CustomerServiceImpl">
- <property name="customerDao" ref="customerDao">
- </property>
- </bean>
- <bean id="customerDao" class="com.clj.dao.CustomerDaoImpl">
- <!--<property name="hibernateTemplate" ref="hibernateTemplate"/>
- -->
- <!-- 这里不注入模板类, 而是注入 sessionFactory, 因为模板需要 session(封装了 session)-->
- <property name="sessionFactory" ref="sessionFactory" />
- </bean>
- <!-- 配置模板类 (hibernate 框架提供的, 内部封装了 session), 此时交给 spring 管理, 如果持久层继承了
- HibernateDaoSupport, 则无需配置 -->
- <!-- <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
- 注入 sessionFactory
- <property name="sessionFactory"/>
- </bean>-->
- </beans>
4) 修改 action 类
因为注入了业务层实现类, 所以此时可以直接调用业务层方法, 无须加载 bean
- package com.clj.web.action;
- import org.apache.struts2.ServletActionContext;
- import org.springframework.web.context.WebApplicationContext;
- import org.springframework.web.context.support.WebApplicationContextUtils;
- import com.clj.domain.Customer;
- import com.clj.service.CustomerService;
- import com.opensymphony.xwork2.ActionSupport;
- import com.opensymphony.xwork2.ModelDriven;
- /**
- * 客户的控制层
- * @author Administrator
- *
- */
- public class CustomerAction extends ActionSupport implements ModelDriven<Customer>{
- // 不要忘记手动 new
- private Customer customer=new Customer();
- public Customer getModel() {
- return customer;
- }
- // 提供 service 成员属性, 提供 set 方法
- private CustomerService customerService;
- public void setCustomerService(CustomerService customerService) {
- this.customerService = customerService;
- }
- /**
- * 保存客户
- * @return
- */
- public String add(){
- System.out.println("WEB 层, 保存客户");
- // 方式一: 创建 web 的工厂 (action 由 struts2 创建)
- /*WebApplicationContext context=WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
- CustomerService cs=(CustomerService) context.getBean("customerService");
- // 调用方法
- cs.save(customer);*/
- customerService.save(customer);
- return NONE;
- }
- }
spring 整合 hibernate 方式二:(不带有 hibernate.cfg.xml 的配置文件)
这里准备删除 hibernate 的核心配置文件, 在删除之前, 需要将其配置文件中的相关内容配置到 spring 的 applicatioinContext.xml 文件中取
1, 查看 hibernate.cfg.xml 文件中的相关内容
* 数据库连接基本参数 (4 大参数)
* Hibernate 相关的属性
* 连接池
* 映射文件
2, 引入配置
引入连接池
- <!-- 先配置 C3p0 的连接池 -->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass" value="com.mysql.jdbc.Driver"/>
- <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/>
- <property name="user" value="root"/>
- <property name="password" value="root"/>
- </bean>
修改对应的 sessionFactory: 因为已经没有了 hibernate.cfg.xml 的配置文件, 所以需要修改该配置, 注入连接池
引入对象映射文件: 因为已经没有了 hibernate.cfg.xml 的配置文件, 不会扫描到该配置文件, 需要注入
- <!-- 编写 bean, 名称都是固定的, 有 spring 提供, 用来加载 hibernate.cfg.xml 的配置文件 -->
- <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
- <!-- 先加载连接池 -->
- <property name="dataSource" ref="dataSource"/>
- <!-- 加载方言, 加载可选项 -->
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
- <prop key="hibernate.show_sql">true</prop>
- <prop key="hibernate.format_sql">true</prop>
- <prop key="hibernate.hbm2ddl.auto">update</prop>
- </props>
- </property>
- <!-- 引入映射的配置文件 -->
- <property name="mappingResources">
- <list>
- <value>com/clj/domain/Customer.hbm.xml</value>
- </list>
- </property>
- </bean>
现在: 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">
- <!-- 先配置 C3p0 的连接池 -->
- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
- <property name="driverClass" value="com.mysql.jdbc.Driver"/>
- <property name="jdbcUrl" value="jdbc:mysql://192.168.174.130:3306/SSH"/>
- <property name="user" value="root"/>
- <property name="password" value="root"/>
- </bean>
- <!-- 编写 bean, 名称都是固定的, 有 spring 提供, 用来加载 hibernate.cfg.xml 的配置文件 -->
- <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
- <!-- 先加载连接池 -->
- <property name="dataSource" ref="dataSource"/>
- <!-- 加载方言, 加载可选项 -->
- <property name="hibernateProperties">
- <props>
- <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
- <prop key="hibernate.show_sql">true</prop>
- <prop key="hibernate.format_sql">true</prop>
- <prop key="hibernate.hbm2ddl.auto">update</prop>
- </props>
- </property>
- <!-- 引入映射的配置文件 -->
- <property name="mappingResources">
- <list>
- <value>com/clj/domain/Customer.hbm.xml</value>
- </list>
- </property>
- </bean>
- <!-- 先配置平台事务管理器 -->
- <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
- <!-- 注入事务, session 能够管理事务, 工厂能够创建 session -->
- <property name="sessionFactory" ref="sessionFactory"/>
- </bean>
- <!-- 开启事务的注解 -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
- <!-- 配置客户模块 -->
- <!-- 强调: 配置的 Aciton, 必须是多列的 -->
- <bean id="customerAction" class="com.clj.web.action.CustomerAction" scope="prototype">
- <!-- 注意: struts 管理 action 时, 基于其中有个 struts-plugin 的 jar 包, 其中更改了一个
- 常量 struts.objectFactory.spring.autoWire = name 将其打开了, 可以自动装配, 只需要提供 set 方法
- 但是此时 action 由 spring 管理, 自动装配失效, 所以需要手动进行配置注入
- -->
- <property name="customerService" ref="customerService"></property>
- </bean>
- <bean id="customerService" class="com.clj.service.CustomerServiceImpl">
- <property name="customerDao" ref="customerDao"></property>
- </bean>
- <!-- 以后, Dao 都需要继承 HibernateDaoSupport, 注入 sessionFactory -->
- <bean id="customerDao" class="com.clj.dao.CustomerDaoImpl">
- <!--<property name="hibernateTemplate" ref="hibernateTemplate"/>-->
- <!-- 这里不注入模板类, 而是注入 sessionFactory, 因为模板需要 session(封装了 session)-->
- <property name="sessionFactory" ref="sessionFactory"/>
- </bean>
- <!-- 配置模板类 (hibernate 框架提供的, 内部封装了 session), 此时交给 spring 管理, 如果持久层继承了 HibernateDaoSupport, 则无需配置 -->
- <!-- <bean id="hibernateTemplate" class="org.springframework.orm.hibernate5.HibernateTemplate">
- 注入 sessionFactory
- <property name="sessionFactory"/>
- </bean>-->
- </beans>
此时可以安心的删除 hibernate.cfg.xml 文件了
这样 SSH 整合完毕
六, Hibernate 模板常用方法
注意: 以下代码省略了接口中的演示 (偷了个懒, 相信初学者不会看不懂)
1) 插入:
持久层
- package com.clj.dao;
- import java.util.List;
- import org.hibernate.criterion.DetachedCriteria;
- import org.springframework.orm.hibernate5.HibernateTemplate;
- import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
- import com.clj.domain.Customer;
- /**
- * 持久层
- * 继承 HibernateDaoSupport, 内部封装了 HibernateTemplate
- * @author Administrator
- *
- */
- public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
- @Override
- public void update(Customer customer) {
- // TODO Auto-generated method stub
- this.getHibernateTemplate().update(customer);
- }
- }
业务层
- package com.clj.service;
- import java.util.List;
- import org.springframework.transaction.annotation.Transactional;
- import com.clj.dao.CustomerDao;
- import com.clj.domain.Customer;
- /**
- * 客户的业务层
- * @author Administrator
- *
- */
- @Transactional
- public class CustomerServiceImpl implements CustomerService{
- private CustomerDao customerDao;
- public void setCustomerDao(CustomerDao customerDao) {
- this.customerDao = customerDao;
- }
- @Override
- public void update(Customer customer) {
- // TODO Auto-generated method stub
- customerDao.update(customer);
- }
- }
测试类
- package com.clj.test;
- import java.util.List;
- import javax.annotation.Resource;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import com.clj.domain.Customer;
- import com.clj.service.CustomerService;
- /**
- * 测试 Hiberante 模板类的简单方法
- * @author Administrator
- *
- */
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration("classpath:applicationContext.xml")
- public class Demo1 {
- @Resource(name="customerService")
- private CustomerService customerService;
- /**
- * 测试插入
- */
- @Test
- public void run1(){
- Customer customer=new Customer();
- customer.setCust_id(1L);
- customer.setCust_name("测试");
- customerService.update(customer);
- }
- }
2) 以下为指定查询, 查询所有, 离线查询代码
持久层
- package com.clj.dao;
- import java.util.List;
- import org.hibernate.criterion.DetachedCriteria;
- import org.springframework.orm.hibernate5.HibernateTemplate;
- import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
- import com.clj.domain.Customer;
- /**
- * 持久层
- * 继承 HibernateDaoSupport, 内部封装了 HibernateTemplate
- * @author Administrator
- *
- */
- public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
- // 将数据保存到数据库中 (调用模板类 (hibernate 提供, 内部封装了 session))
- /*private HibernateTemplate hibernateTemplate;
- public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
- this.hibernateTemplate = hibernateTemplate;
- }*$**
- * 保存客户
- */
- public void save(Customer customer) {
- System.out.println("持久层: 保存客户");
- this.getHibernateTemplate().save(customer);
- }
- @Override
- public void update(Customer customer) {
- // TODO Auto-generated method stub
- this.getHibernateTemplate().update(customer);
- }
- /**
- * 通过主键查询
- */
- public Customer getById(Long id) {
- return this.getHibernateTemplate().get(Customer.class, id);
- }
- /**
- * 查询所有
- */
- @Override
- public List<Customer> findAll() {
- String sql="from Customer";
- List<Customer> list=(List<Customer>) this.getHibernateTemplate().find(sql);
- return list;
- }
- /**
- * QBC 离线查询
- */
- @Override
- public List<Customer> findAllByQBC() {
- DetachedCriteria criteria=DetachedCriteria.forClass(Customer.class);
- List<Customer> list=(List<Customer>) this.getHibernateTemplate().findByCriteria(criteria);
- return list;
- }
- }
业务层
- package com.clj.service;
- import java.util.List;
- import org.springframework.transaction.annotation.Transactional;
- import com.clj.dao.CustomerDao;
- import com.clj.domain.Customer;
- /**
- * 客户的业务层
- * @author Administrator
- *
- */
- @Transactional
- public class CustomerServiceImpl implements CustomerService{
- private CustomerDao customerDao;
- public void setCustomerDao(CustomerDao customerDao) {
- this.customerDao = customerDao;
- }
- // 用来保存客户
- public void save(Customer customer) {
- System.out.println("业务层, 保存客户");
- customerDao.save(customer);
- }
- @Override
- public void update(Customer customer) {
- // TODO Auto-generated method stub
- customerDao.update(customer);
- }
- @Override
- public Customer getById(Long id) {
- // TODO Auto-generated method stub
- return customerDao.getById(id);
- }
- @Override
- public List<Customer> findAll() {
- return customerDao.findAll();
- }
- @Override
- public List<Customer> findAllByQBC() {
- // TODO Auto-generated method stub
- return customerDao.findAllByQBC();
- }
- }
测试类
- package com.clj.test;
- import java.util.List;
- import javax.annotation.Resource;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
- import com.clj.domain.Customer;
- import com.clj.service.CustomerService;
- /**
- * 测试 Hiberante 模板类的简单方法
- * @author Administrator
- *
- */
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration("classpath:applicationContext.xml")
- public class Demo1 {
- @Resource(name="customerService")
- private CustomerService customerService;
- /**
- * 测试插入
- */
- @Test
- public void run1(){
- Customer customer=new Customer();
- customer.setCust_id(1L);
- customer.setCust_name("测试");
- customerService.update(customer);
- }
- /**
- * 测试查询指定的客户
- */
- @Test
- public void run2(){
- Customer customer=customerService.getById(2L);
- System.out.println(customer);
- }
- /**
- * 查询所有的客户
- */
- @Test
- public void run3(){
- List<Customer> list=customerService.findAll();
- System.out.println(list);
- }
- /**
- * QBC(离线查询)
- */
- @Test
- public void run4(){
- List<Customer> list=customerService.findAllByQBC();
- System.out.println(list);
- }
- }
七, 关于 SSH 延迟加载问题
1. 使用延迟加载的时候, 再 WEB 层查询对象的时候程序会抛出异常!
* 原因是延迟加载还没有发生 SQL 语句, 在业务层 session 对象就已经销毁了, 所以查询到的 JavaBean 对象已经变成了托管态对象!
* 注意: 一定要先删除 javassist-3.11.0.GA.jar 包 (jar 包冲突了)
2. 解决办法
Spring 框架提供了一个过滤器, 让 session 对象在 WEB 层就创建, 在 WEB 层销毁. 只需要配置该过滤器即可
* 但是: 要注意需要在 struts2 的核心过滤器之前进行, spring 监听器之后配置
- <!-- 解决延迟加载的问题 -->
- <filter>
- <filter-name>OpenSessionInViewFilter</filter-name>
- <filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>OpenSessionInViewFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
3, 演示延迟加载
持久层: 调用 load 方法, 此方法时延迟加载的
- /**
- * 延迟加载
- */
- @Override
- public Customer loadById(long id) {
- // TODO Auto-generated method stub
- return this.getHibernateTemplate().load(Customer.class, id);
- }
业务层
- @Override
- public Customer loadById(long id) {
- // TODO Auto-generated method stub
- return customerDao.loadById(id);
- }
测试类
- @Test
- public void run5(){
- Customer customer=customerService.loadById(2L);
- System.out.println(customer);
- }
来源: https://www.cnblogs.com/cailijia52o/p/8724710.html