1、整合步骤
1、建立工程
2、设置编码格式
3、设置所有的jsp的编码格式
4、导入jar包
5、写hibernate的配置文件、持久化、映射文件
6、写dao
7、写service
8、spring的配置文件
1、写sessionFactory
2、测试
3、写dao和service
4、测service
5、aop的配置
6、测试service,看service是否是代理对象
9、写action
10、把action放入到spring中
11、写action的配置文件
12、写web.xml配置文件
13、写jsp
14、测试
2、整合原理
1、当tomcat启动时,在web.xml中
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param>
ContextLoaderListener{
contextInitialized(){
this.contextLoader = createContextLoader();
会按照如下的规则加载spring的配置文件
1、如果在web.xml文件中有contextConfigLocation参数
则会按照该参数所指定的路径加载配置文件
2、如果在web.xml文件中没有配置<context-param>,则会根据默认的路径
加载配置文件(WEB-INF/applicationContext.xml)
3、在web-inf下的路径可以有如下的写法:
WEB-INF/*../application-*.xml
说明:在web-inf下的配置文件没有办法进行测试
this.contextLoader.initWebApplicationContext(event.getServletContext());
加载spring的配置文件,启动spring容器
}
}
说明:
1、当启动web容器的时候,dao层和service层所有的类全部实例化了
2、因为有aop的机制,所以目标类全部创建了代理对象
3、在service层和dao层,调用所有的set方法或者构造器进行注入
4、action层并没有创建对象,因为是多例的
5、所以当spring配置文件中写错了,web容器启动的时候报错
<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>
加载了4个配置文件
default.properties
struts-default.xml
struts-plugin.xml
多加载了一个struts2-spring-plugin-2.1.8.1.jar 包下的xml文件
<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<constant name="struts.objectFactory" value="spring" />
说明:该类改变了action的创建方式
先从spring容器中查找action,根据struts2的配置文件中的action元素的class属性的值和spring容器中的ID值做匹配
struts.xml
2、当请求一个url
当查找一个action时,去spring容器中查找,找到以后
1、创建action
2、在action中注入service(代理对象)
3、懒加载问题解决方案
1、在web.xml文件中
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
<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、执行步骤
1、
OpenSessionInViewFilter{
doFilter(){
开启session了
说明:在查找sessionFactory的时候,名称必须是"sessionFactory"
}
}
2、
执行struts2的核心流程
3、
执行struts2过滤器中的finally方法:把actionContext清空
4、
执行页面:这个时候session并没有关闭
5、
OpenSesisonInViewFilter
finally{
关闭session
}
3、说明
该模式提前打开了session,延迟了session的关闭时间,解决了懒加载的问题。因为延长了session的关闭时间,所以延长了一级缓存的生命周期,使更多的对象长时间的停留在了内存中,对内存消耗大,特别是进行批量操作的时候
4、关于spring管理的session和事务的说明
1、有OpenSessionInView模式
1、session的关闭和开启不用管
2、不管事务是否提交,session在执行OpenSessionInViewFilter的finally时才关闭
说明session的关闭和事务的提交没有什么关系了
2、没有OpenSessionInView模式
1、如果当前方法没有事务环境,则调用完this.getHibernateTemplate()的方法时,session关闭了
2、如果当前方法有事务环境,在事务环境中session是不能关闭的,但是当事务方法执行完毕以后session自动关闭了
5、扩展:如果把action当做目标类处理事务
spring是可以把action层作为目标类的,但是所有的action不能继承ActionSupport,只能采用cglib的方式生成代理对象
而struts2的核心的action就成为spring的action的代理对象了
6、关于session和事务
1、在hibernate中,如果session是由当前线程产生的,那么crud操作必须开启事务,但是在hibernate中提交事务以后自动关闭session,这点有点不安全
原因:如果在提交事务完毕以后,还存在数据库的查询操作,这个时候,就会发生no session异常。
所以个人认为hibernate的这个处理并不是特别好
2、在spring与hibernate整合的时候,这个状况得到了改善:如果有OpenSessionInView模式的情况下,当事务提交以后,session并没有关闭。