一、集成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
报错1: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包移除来就可以了, 如下:.
报错2: Could not open ServletContext resource [/jdbc.properties]
为什么找不到jdbc.properties?
因为是通过GroupAction来查找jdbc.properties这个文件, 是找不到的,修改查找的路径:
报错3: 无法实例化groupAction, 找不到这个bean, 因为使用注解, 在SpringBean.xml中, 定义base-package只到dao包中找aAnnotation, 而groupAction在action包中, 所以无法找不到。
改为
问题4: 中文乱码
2 、测试: 显示组列表
2.1流程
3.1、显示组信息, 点击上面的组名称, 到一个显示界面
3.1、 设置跳转,将组id传过去, 使用?id=${id}
${id }--->${groupName }
3.2、在GroupAction中提供一个方法list()
3.3、GroupAction中没有id, 我们需要写一个id来存。
//用于接收组id,
private int id;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
3.4、显示结果,出现组名为空
为什么出现这个问题, 如果熟练掌握Struts2创建项目5–(传值)valueStack讲解,就不难看出。
第一:执行group_list.action请求, 将GroupAction放到CompoundRoot中
第二:实现了ModelDriven, 所以将Group放到CompoundRoot
第三:此时Group位于CompoundRoot的顶部,在设置id时, , 由于group中有id, 所以此时设置的id是Group的id,所以导致, 在show界面, id显示为5,
当执行list() ,加载id,是GroupAction的id, 为0, 所以groupname显示为空
3.5、解决:将GroupAction的id改为gid, ok
list()
/**
*当点击一个组,查看组内信息
*/
public String show() {
//接收组id,
System.out.println(gid);
//注意此处,group
group = groupService.load(gid);
return SUCCESS;
}
3.6、显示加载问题
3.7、为什么会导致这种问题
3.7.1、事务管理是在Dao层, 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没有起作用。
解决方法:将自定义的Filter放在Struts2的Filter之前, 否则, 所有请求被Strtus2的Filter所控制, 自定义Filter就不起作用。
3.11.1、在次执行,输出不对
3.11.2、但是控制台输出,group的信息正确
show.jsp有问题
改为
${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);*/
}
