@(Spring)[spring, struts2, hibernate, 框架整合, ssh, Spring]
该SSH整合是基于Spring4、Struts2、Hibernate5的。
标红为整合必须引入的
Struts2
Hibernate
注意:在struts2基础包和Hibernate5基础包中javassist-x.jar这个包会有冲突,搭环境时请使用Hibernate中的高版本javassist的包
如果使用有hibernate配置文件的ssh整合,使用c3p0连接池,需要使用hibernate中c3p0可选包中的三个jar包;
如果使用没有hibernate配置文件的ssh整合,使用c3p0连接池,需要使用spring整合c3p0连接池中的jar包。
两者不可同用,否则会有冲突。
<filter>
<filter-name>struts2filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilterfilter-class>
filter>
<filter-mapping>
<filter-name>struts2filter-name>
<url-pattern>/*url-pattern>
filter-mapping>
<struts>
struts>
<hibernate-configuration>
<session-factory>
session-factory>
hibernate-configuration>
<hibernate-mapping package="">
hibernate-mapping>
<context-param>
<param-name>contextConfigLocationparam-name>
<param-value>classpath:applicationContext.xmlparam-value>
context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
listener>
<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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
beans>
### 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
package com.pc.crm.domain;
import java.io.Serializable;
/**
* 客户实体类
* @author Switch
*/
public class Customer implements Serializable {
private static final long serialVersionUID = 8501538130746309236L;
}
package com.pc.crm.web.action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.pc.crm.domain.Customer;
/**
* 客户Action
* @author Switch
*/
public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
private static final long serialVersionUID = 7878143682430064108L;
Customer customer = new Customer();
@Override
public Customer getModel() {
return this.customer;
}
}
package com.pc.crm.service;
/**
* 客户服务接口
* @author Switch
*/
public interface CustomerService {
}
package com.pc.crm.service.impl;
import com.pc.crm.service.CustomerService;
/**
* 客户服务实现类
* @author Switch
*/
public class CustomerServiceImpl implements CustomerService {
}
package com.pc.crm.dao;
/**
* 客户持久层接口
* @author Switch
*/
public interface CustomerDao {
}
package com.pc.crm.dao.impl;
import com.pc.crm.dao.CustomerDao;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl implements CustomerDao {
}
<bean id="customerService" class="com.pc.crm.service.impl.CustomerServiceImpl">
bean>
<bean id="customerDao" class="com.pc.crm.dao.impl.CustomerDaoImpl">
bean>
这里只给出一个访问链接,基于JSP的。
<a href="${pageContext.request.contextPath}/customer/listCustomer">客户列表a>
<a href="${pageContext.request.contextPath}/customer/list_Customer.action">客户列表a>
package com.pc.crm.web.action;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.pc.crm.domain.Customer;
import com.pc.crm.service.CustomerService;
/**
* 客户Action
* @author Switch
*/
public class CustomerAction extends ActionSupport implements ModelDriven<Customer> {
private static final long serialVersionUID = 7878143682430064108L;
// 客户服务类
CustomerService customerService;
// 用于使用值栈特性,在页面中使用
List customers = null;
public List getCustomers() {
return customers;
}
public void setCustomers(List customers) {
this.customers = customers;
}
// 模型驱动
Customer customer = new Customer();
@Override
public Customer getModel() {
return this.customer;
}
/**
* 显示客户列表
* @return
*/
public String listCustomer() {
// 从数据库中获客户列表
customers = customerService.findAllCustomer();
// 转发到客户列表视图
return "list";
}
}
该jar包下有一个struts-plugin.xml
的文件,在该文件中开启了Spring工厂对Action中的属性按照名称自动装配等功能。
<constant name="struts.objectFactory" value="spring" />
该常量在struts2核心包的default.properties
文件中,有如下配置
### if specified, the default object factory can be overridden here
### Note: short-hand notation is supported in some cases, such as "spring"
### Alternatively, you can provide a com.opensymphony.xwork2.ObjectFactory subclass name here
# struts.objectFactory = spring
### specifies the autoWiring logic when using the SpringObjectFactory.
### valid values are: name, type, auto, and constructor (name is the default)
struts.objectFactory.spring.autoWire = name
### indicates to the struts-spring integration if Class instances should be cached
### this should, until a future Spring release makes it possible, be left as true
### unless you know exactly what you are doing!
### valid values are: true, false (true is the default)
struts.objectFactory.spring.useClassCache = true
### ensures the autowire strategy is always respected.
### valid values are: true, false (false is the default)
struts.objectFactory.spring.autoWire.alwaysRespect = false
### By default SpringObjectFactory doesn't support AOP
### This flag was added just temporally to check if nothing is broken
### See https://issues.apache.org/jira/browse/WW-4110
struts.objectFactory.spring.enableAopSupport = false
当struts.objectFactory
常量启用时,开启对Spring的一系列支持。比如说按名自动装配。
// 注入客户服务类
CustomerService customerService;
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
/**
* customerService未优化
*/
/* public CustomerAction() {
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(ServletActionContext.getServletContext());
customerService = context.getBean("customerService", CustomerService.class);
}
*/
<package name="customer" extends="struts-default" namespace="/customer">
<action name="*_*" class="com.pc.crm.web.action.CustomerAction" method="{1}{2}">
<result name="list" type="dispatcher">/jsp/customer/list.jspresult>
action>
package>
引入Struts2和Spring整合的插件包
将Action交给Spring创建
<bean id="customerAction" class="com.pc.crm.web.action.CustomerAction" scope="prototype">
<property name="customerService" ref="customerService" />
bean>
注意的事项
struts.xml
文件中对应action
的class
属性为bean
的id
属性
<package name="customer" extends="struts-default" namespace="/customer">
<action name="*_*" class="customerAction" method="{1}{2}">
<result name="list" type="dispatcher">/jsp/customer/list.jspresult>
action>
package>
package com.pc.crm.service.impl;
import java.util.List;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
import com.pc.crm.service.CustomerService;
/**
* 客户服务实现类
* @author Switch
*/
public class CustomerServiceImpl implements CustomerService {
// 注入客户Dao
private CustomerDao customerDao;
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
@Override
public List findAllCustomer() {
// 查找客户列表
return customerDao.findAllCustomer();
}
}
<bean id="customerService" class="com.pc.crm.service.impl.CustomerServiceImpl">
<property name="customerDao" ref="customerDao"/>
bean>
Customer.hbm.xml
package com.pc.crm.domain;
import java.io.Serializable;
/**
* 客户实体类
* @author Switch
*/
public class Customer implements Serializable {
private static final long serialVersionUID = 8501538130746309236L;
private Long custId;
private String custName;
private String custSource;
private String custIndustry;
private String custLevel;
private String custAddress;
private String custPhone;
......
}
<hibernate-mapping package="com.pc.crm.domain">
<class name="Customer" table="cst_customer" lazy="true" batch-size="3">
<id name="custId" column="cust_id" type="java.lang.Long">
<generator class="native"/>
id>
<property name="custName" column="cust_name" type="java.lang.String" length="32"/>
<property name="custSource" column="cust_source" type="java.lang.String" length="32"/>
<property name="custIndustry" column="cust_industry" type="java.lang.String" length="32"/>
<property name="custLevel" column="cust_level" type="java.lang.String" length="32"/>
<property name="custAddress" column="cust_address" type="java.lang.String" length="128"/>
<property name="custPhone" column="cust_phone" type="java.lang.String" length="64"/>
class>
hibernate-mapping>
hibernate.cfg.xml
配置文件
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driverproperty>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mycrmproperty>
<property name="hibernate.connection.username">rootproperty>
<property name="hibernate.connection.password">123456property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialectproperty>
<property name="hibernate.show_sql">trueproperty>
<property name="hibernate.format_sql">trueproperty>
<property name="hibernate.hbm2ddl.auto">updateproperty>
<property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProviderproperty>
<mapping resource="com/pc/crm/domain/Customer.hbm.xml" />
<mapping resource="com/pc/crm/domain/LinkMan.hbm.xml" />
session-factory>
hibernate-configuration>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
bean>
package com.pc.crm.dao.impl;
import java.util.List;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public List findAllCustomer() {
}
}
<bean id="customerDao" class="com.pc.crm.dao.impl.CustomerDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
bean>
package com.pc.crm.dao.impl;
import java.util.List;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public List findAllCustomer() {
return (List) this.getHibernateTemplate().find("from Customer");
}
}
Customer.hbm.xml
package com.pc.crm.domain;
import java.io.Serializable;
/**
* 客户实体类
* @author Switch
*/
public class Customer implements Serializable {
private static final long serialVersionUID = 8501538130746309236L;
private Long custId;
private String custName;
private String custSource;
private String custIndustry;
private String custLevel;
private String custAddress;
private String custPhone;
......
}
<hibernate-mapping package="com.pc.crm.domain">
<class name="Customer" table="cst_customer" lazy="true" batch-size="3">
<id name="custId" column="cust_id" type="java.lang.Long">
<generator class="native"/>
id>
<property name="custName" column="cust_name" type="java.lang.String" length="32"/>
<property name="custSource" column="cust_source" type="java.lang.String" length="32"/>
<property name="custIndustry" column="cust_industry" type="java.lang.String" length="32"/>
<property name="custLevel" column="cust_level" type="java.lang.String" length="32"/>
<property name="custAddress" column="cust_address" type="java.lang.String" length="128"/>
<property name="custPhone" column="cust_phone" type="java.lang.String" length="64"/>
class>
hibernate-mapping>
hibernate.cfg.xml
中的相关内容,将其配置在spring中 db.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mycrm
jdbc.user=root
jdbc.password=123456
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
bean>
<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.MySQLDialectprop>
<prop key="hibernate.show_sql">trueprop>
<prop key="hibernate.format_sql">trueprop>
<prop key="hibernate.hbm2ddl.auto">updateprop>
props>
property>
<property name="mappingLocations" value="classpath:com/pc/crm/domain/*.hbm.xml"/>
bean>
package com.pc.crm.dao.impl;
import java.util.List;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public List findAllCustomer() {
}
}
<bean id="customerDao" class="com.pc.crm.dao.impl.CustomerDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
bean>
package com.pc.crm.dao.impl;
import java.util.List;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public List findAllCustomer() {
return (List) this.getHibernateTemplate().find("from Customer");
}
}
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut expression="execution(* com.pc.crm.service.impl.*.*(..))" id="pointcut1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
aop:config>
PS:如果需要配置基于注解的事务,请参考之前的博文《Spring事务管理》。
package com.pc.crm.dao.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public void save(Customer customer) {
this.getHibernateTemplate().save(customer);
}
@Override
public void update(Customer customer) {
this.getHibernateTemplate().update(customer);
}
@Override
public void delete(Customer customer) {
this.getHibernateTemplate().delete(customer);
}
}
package com.pc.crm.dao.impl;
import java.util.List;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.orm.hibernate5.support.HibernateDaoSupport;
import com.pc.crm.dao.CustomerDao;
import com.pc.crm.domain.Customer;
/**
* 客户持久层接口实现类
* @author Switch
*/
public class CustomerDaoImpl extends HibernateDaoSupport implements CustomerDao {
@Override
public Customer findById(Long id) {
return this.getHibernateTemplate().load(Customer.class, id);
}
@Override
public List findAll() {
// 使用HQL查询:
// List list = (List) this.getHibernateTemplate().find("from Customer ");
// 使用QBC查询:使用DetchedCriteria
// DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
// List list = (List) this.getHibernateTemplate().findByCriteria(detachedCriteria);
// 命名查询:
List list = (List) this.getHibernateTemplate().findByNamedQuery("queryAll");
return list;
}
@Override
public List findByPage() {
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
List list = (List) this.getHibernateTemplate().findByCriteria(detachedCriteria, 0, 3);
return list;
}
}
<filter>
<filter-name>OpenSessionInViewFilterfilter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilterfilter-class>
filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilterfilter-name>
<url-pattern>*.actionurl-pattern>
filter-mapping>
PS:将该过滤器放在Struts2核心过滤器上面。
<filter>
<filter-name>CharacterEncodingFilterfilter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilterfilter-class>
<init-param>
<param-name>encodingparam-name>
<param-value>UTF-8param-value>
init-param>
<init-param>
<param-name>forceEncodingparam-name>
<param-value>trueparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>CharacterEncodingFilterfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
PS:将该过滤器放在Struts2核心过滤器上面。