1. 导包
hibernate包
required包:hibernate-release/lib/required/*
jpa包:hibernate-release/lib/jpa/*
数据库驱动包:如mysql-connector
struts2包
struts2/apps/struts-blank.war/WEB-INF/lib/*
strtus整合spring插件包:struts-spring-plugin-xxx.jar(导入后spring自动找该包,找不到会报错)
spring包
基本4(Beans+Core+Context+Expression)+2(logging+log4j(老版本需要))
整合web:1(spring-web)
整合aop:4(aop包:aop+aspect)+(第三方aop包:aopalliance+weaving)
整合Hibernate和jdbc事务:4(spring-jdbc+spring-tx+[JDBC驱动]+c3p0连接池)+1(spring-orm)[JDBC驱动hibernate已导入]
整合junit4测试:1(spring-test)
JSTL标签库
stand.jar+jstl-xx.jar
去掉重复的低版本包javassist.xxx.GA.jar
2. web.xml配置
//让spring随web启动而创建的监听器
org.springframework.web.context.ContextLoaderListener
// 配置spring配置文件位置参数
contextConfigLocation
classpath:applicationContext.xml
/* 扩大session作用范围
注意: 任何filter一定要在struts的filter之前调用,因为交由struts后struts是不会放行的*/
openSessionInView
org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
//struts2核心过滤器
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
openSessionInView
/*
struts2
/*
3. 导入约束
spring与struts2整合
就是将Action对象交给spring容器负责创建
struts2配置文件(struts.xml)
//常量配置:将action的创建交给spring容器
<constant name="struts.objectFactory" value="spring"></constant>
/*struts.objectFactory.spring.autoWire =name spring负责装配Action依赖属性(默认)
也就是说spring帮我们装配Action依赖属性,不然得先获取spring容器
,然后在从容器中获得action依赖属性(如Service层的注入)*/
<package name="crm" namespace="/" extends="struts-default" >
//RuntimeException异常处理配置
<global-exception-mappings>
<exception-mapping result="error" exception="java.lang.RuntimeException"></exception-mapping>
</global-exception-mappings>
/*整合方案1:class属性上仍然配置action的完整类名(class="cn.it.userAction")
struts2自己创建action,由spring负责组装Action中的依赖属性
不推荐:最好由spring完整管理action的生命周期,spring功能才能应用到Action上*/
/*整合方案2:class属性上填写spring中action对象的BeanName
完全由spring管理action生命周期,包括Action的创建(推荐)
注意:需要在applicationContext(bean中)中手动组装依赖属性*/
<action name="UserAction_*" class="userAction" method="{1}" >
<result name="toHome" type="redirect" >/index.htm</result>
<result name="error" >/login.jsp</result>
</action>
</package>
spring容器(ApplicationContext.xml)
// action
// 注意:Action对象作用范围一定是多例的.这样才符合struts2架构
<bean name="userAction" class="cn.itcast.web.action.UserAction" scope="prototype" >
<property name="userService" ref="userService" ></property>
</bean>
// service
<bean name="userService" class="cn.itcast.service.impl.UserServiceImpl" >
<property name="ud" ref="userDao" ></property>
</bean>
// dao
<bean name="userDao" class="cn.itcast.dao.impl.UserDaoImpl" >
// 注入sessionFactory 在下方spring与hibernate整合中有配置sessionFactory
<property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
spring与hibernate整合
就是将sessionFactory交给spring来负责维护,session的维护以及aop事务
spring容器(ApplicationContext.xml)
// 读取db.properties文件
<context:property-placeholder location="classpath:db.properties" />
// 配置c3p0连接池
<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
<property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property>
<property name="driverClass" value="${jdbc.driverClass}" ></property>
<property name="user" value="${jdbc.user}" ></property>
<property name="password" value="${jdbc.password}" ></property>
</bean>
// 核心事务管理器HibernateTransactionManager,无事务操作数据库只能只读模式
<bean name="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" >
<property name="sessionFactory" ref="sessionFactory" ></property>
</bean>
// 配置通知
<tx:advice id="txAdvice" transaction-manager="transactionManager" >
<tx:attributes>
<tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" />
<tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
/* 配置将通知织入目标对象
配置切点
配置切面 */
<aop:config>
<aop:pointcut expression="execution(* cn.itcast.service.impl.*ServiceImpl.*(..))" id="txPc"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" />
</aop:config>
<!-- ============================================================= -->
//开启注解事务
/* */
<!-- ============================================================= -->
//将SessionFactory配置到spring容器中
//加载配置方案1:仍然使用外部的hibernate.cfg.xml配置信息(不推荐)
<!-- <bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<property name="configLocation" value="classpath:hibernate.cfg.xml" ></property>
</bean> -->
//加载配置方案2:在spring配置中放置hibernate配置信息(推荐)
<bean name="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
// 将连接池注入到sessionFactory, hibernate会通过连接池获得连接
<property name="dataSource" ref="dataSource" ></property>
// 配置hibernate基本信息
<property name="hibernateProperties">
<props>
// 必选配置
/* com.mysql.jdbc.Driver
jdbc:mysql:///crm_32
root
1234 */
<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>
//引入orm元数据,指定orm元数据所在的包路径,spring会自动读取包中的所有配置
<property name="mappingDirectoryLocations" value="classpath:cn/itcast/domain" ></property>
</bean>
web层
public class UserAction extends ActionSupport implements ModelDriven<User> {
private User user = new User();
//由spring负责组装Action的依赖属性(Service层的对象)
private UserService userService ;
public void setUserService(UserService userService) {
this.userService = userService;
}
public String login() throws Exception {
//1 调用Service执行登陆逻辑
User u = userService.getUserByCodePassword(user);
//2 将返回的User对象放入session域
ActionContext.getContext().getSession().put("user", u);
//3 重定向到项目首页
return "toHome";
}
@Override
public User getModel() {
return user;
}
}
Dao层
/*HibernateDaoSupport(封装的都是session的操作),为dao注入sessionFactory
通过getHibernateTemplate()方法获得自动创建的hibernateTemplate模板对象*/
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
@Override
public User getByUserCode(final String usercode) {
//HQL
return getHibernateTemplate().execute(new HibernateCallback<User>() {
@Override
public User doInHibernate(Session session) throws HibernateException {
String hql = "from User where user_code = ? ";
Query query = session.createQuery(hql);
query.setParameter(0, usercode);
User user = (User) query.uniqueResult();
return user;
}
});
//Criteria方式
/*DetachedCriteria dc = DetachedCriteria.forClass(User.class);
dc.add(Restrictions.eq("user_code", usercode));
List list = (List) getHibernateTemplate().findByCriteria(dc);
if(list != null && list.size()>0){
return list.get(0);
}else{
return null;
}*/
/*Criteria其他查询方法:
//查询分页列表数据
List getPageList(DetachedCriteria dc,Integer start,Integer pageSize);*/
}
@Override
public void save(User u) {
getHibernateTemplate().save(u);
}
}
解决懒加载的no-session问题:扩大session作用范围(filter)
为什么no-session:因为使用懒加载的话,是使用对象时才执行sql语句。而session是Serive层调用时打开,service层结束时关闭。而一般是在页面才执行对象的,此时session已经关闭。
openSessionInView
org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
openSessionInView
/*