一、集成Struts2,
1.1、导入struts2与Spring的集成的jar struts2-spring-plugin-2.3.33.jar
1.2、设置Struts.xml让Spring管理Action.
参考:struts-2.5.12-all/struts-2.5.12/docs/docs/spring-and-struts-2.html
1.2.1、创建一个Action, 为Spring所管理
package com.chb.spring_hibernate.action;
import org.springframework.stereotype.Controller;
import com.chb.spring_hibernate.model.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
/**
* 相当于使用Spring来创建userAction, 在Struts.xml中不能够配置类的全路径
* 将
*
* 改为
*
*/
@Controller("userAction")
public class UserAction extends ActionSupport implements ModelDriven {
private static final long serialVersionUID = 1L;
@Override
public User getModel() {
return null;
}
}
1.2.2、修改Struts.xml中的Action配置, class不在使用全路径类, 而是Spring定义的Action。
/WEB-INF/jps/{1}/{2}.jsp
/WEB-INF/jsp/{1}/{2}Input. jsp
/${url}
1.3、在web.xml中配置获取BeanFactory的操作。
1.3.1、配置Spring的监听器
org.springframework.web.context.ContextLoaderListener
当servlet容器启动应用程序时,上面的代码将激活Spring框架。默认情况下,Spring将寻找一个applicationContext.xml的配置文件在WEB-INF(你可以查看Spring的文档, 你可以改变从哪儿查找配置文件,以及配置文件的filename)。
1.3.2、监听器 监听什么东西, 在下面就定义初始化的参数, 配置文件的路径
contextConfigLocation
classpath*:SpringBean.xml
1.3.3、配置Struts2的过滤器
struts2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
struts2
/*
1.4、创建GroupAction
1.4.1、 Service使用@Service
, Dao使用@Repository
, 那么Action使用什么?
//为Spring所管理,使用@Controller,
@Controller("groupAction")
1.4.2、Action应该使用多例
//多例
@Scope("prototype")
1.4.3、继承ActionSupport, 实现ModelDriven
java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
,
我为了辨别哪个jar是哪个的,在WEB-INF/lib下建立一个个目录, 然后build to path,
spring-web-4.3.8.RELEASE.jar明明加入path, 但是报错, 没有org.springframework.web.context.ContextLoaderListener
, 将jar包移除来就可以了, 如下:.
Could not open ServletContext resource [/jdbc.properties]
为什么找不到jdbc.properties?
改为
问题4: 中文乱码
?id=${id}
${id }--->${groupName }
3.2、在GroupAction中提供一个方法list()
//用于接收组id,
private int id;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
3.4、显示结果,出现组名为空
, 由于group中有id, 所以此时设置的id是Group的id
,所以导致, 在show界面, id显示为5,
当执行list() ,加载id,是GroupAction的id, 为0, 所以groupname显示为空
/**
*当点击一个组,查看组内信息
*/
public String show() {
//接收组id,
System.out.println(gid);
//注意此处,group
group = groupService.load(gid);
return SUCCESS;
}
3.6、显示加载问题
expression="execution(* com.chb.spring_hibernate.dao.*.*(..))"
3.7.2、由于Hibernate存在延时加载的问题, 当Dao层事务提交之后,* session就关闭*, 此时到显示层, 就无法获取session对象。
如果将事务放到Action管理呢, 不建议这样做, 因为这样事务周期他长了。
3.8、解决方法: OpenSessionInViewer
解决思路:
3.8.1、在表示层开启Session
在表示层获取Spring的工厂, 以此获取Hibernate的SessionFactory。
3.8.2、在Dao层获取表示层的Session
如果想在Dao层获取表示层的数据, 应该将需要的数据放到ThreadLocal
3.8.3、当整个过程执行完毕之后,关闭Session
我们需要思考的几个问题
问题1: 什么时候开启Session, 什么时候关闭Session, 如果确定过程执行完毕。
借助Filter
Filter一执行, 开始就会执行, doFilter让流程继续执行 , doFilter执行完了之后, 后面的东西就是doFilter调完之后返回的东西, 所以需要借助Filter解决问题
3.9、创建一个OpenSessionFilter
3.10、在web.xml中创建自定义过滤器
openSessionViewFilter
com.chb.spring_hibernate.filter.OpenSessionFilter
openSessionViewFilter
/*
3.10 、修改load方法,使用自定义OpenSessionFilter获取表示层Session,
/**
* hibernate的load, 存在延时加载
*/
public T load(int id) {
//return this.getHibernateTemplate().load(getClz(), id);
//换成自定义Filter获取session, 在Dao层获取表示层的Session
return new OpenSessionFilter().getSession().load(getClz(), id);
}
测试:
报错:
java.lang.NullPointerException
com.chb.spring_hibernate.dao.BaseDao.load(BaseDao.java:59)
line59 : return new OpenSessionFilter().getSession().load(getClz(), id);
最有可能就是没有获取到session
因为Session的开启是在doFilter(), 所以做一下排除测试
仍然报错空指针异常, 这说OpenSessionFilter没有起作用。
改为
${group.id}--->${group.groupName}
4、Spring提供了org.springframework.orm.hibernate5.support.OpenSessionInViewFilter实现此功能。
web.xml
openSessionViewFilter
org.springframework.orm.hibernate5.support.OpenSessionInViewFilter
load()
/**
* hibernate的load, 存在延时加载
*/
public T load(int id) {
//使用Spring的org.springframework.orm.hibernate5.support.OpenSessionInViewFilter,可以通过原来方法获取
return this.getHibernateTemplate().load(getClz(), id);
/*//换成自定义Filter获取session, 在Dao层获取表示层的Session
return new OpenSessionFilter().getSession().load(getClz(), id);*/
}