一、导入jar包
1、数据库驱动和连接池
2、SSH框架
二、整合spring和hibernate
创建实体类:
配置hibernate核心配置文件和实体类映射文件
当运行测试类的testHibernate方法时,会加载spring容器,实例化id为sessionFactory的bean时会加载hibernate的核心配置文件
设置hibernate配置参数自动创建表person。测试成功。
编写dao、service、action,整合struts2
注意struts2的核心配置文件名称sturts.xml和位置:src下这两点不能变。
action标签中的class属性不再写action类的全路径,该bean交由spring管理,class中写spring中对应的action类的bean的id值
tx:annotation-driven可以增强被@Transactional注解修饰的类的所有方法,用于service层中的实现类。
@Autowired注解若用在接口类型上,spring会自动寻找他的实现类注入。若用在具体类上则依赖类型的全路径找到bean注入,该注入方式不依赖于bean的id
component-scan会扫描指定包下的所有类中的所有注解,包括类注解和属性注解,要扫描多个包可用英文半角逗号隔开。
另一种事务声明方法为
声明式事务的配置:
1、配置增强细节:读方法的增强和写方法的增强
2、配置要进行事务控制的方法(切点)
3、将增强用到切点上
Spring和web整合,让tomcat在启动加载web容器时加载spring的bean容器。ContextLoaderListener默认会到WEB-INFO/路劲下寻找
spring的核心配置文件applicationContext.xml
Struts2需配置核心拦截器拦截访问action的路径、创建action的代理对象、返回结果页面。
ContextLoaderListener源码跟踪:
该监听器在初始化时(web容器创建该监听器后)执行该方法,跟踪进去有
查看标蓝色部分可知,加载了spring容器:
1、将所有单例(scope=singleton)的bean实例化放入容器(多例的bean在获取时才被创建)
2、加载spring的配置文件,如properties、import等导入的
StrutsPrepareAndExecuteFilter(struts2核心拦截器)源码跟踪
该过滤器的初始化方法:
第一根红线:该行代码会加载一下配置文件:
1、struts2核心包中的struts-default.xml,所有package标签都要继承struts-default就是因为该配置文件中默认加载了很多有用的拦截器
如编码处理、模型驱动(ModelDriven)、文件上传、result标签的name值等。
2、struts-spring-plugin包中的struts-plugin.xml,该文件的存在即解决了struts中action的创建交给spring
3、你编写的struts.xml
4、struts核心包中的default.properties,里面设置了一些方便开发者调试代码的参数,如struts.devMode
,我们可以再struts.xml中配置struts.devMode=true以方便开发。
第二根红线:静态注入了配置文件中的bean。
跟踪action的创建
在用户发送访问action的请求后,核心拦截器会拦截url,到依次配置文件struts-default.xml、struts-plugin.xml、
struts-default.xml中找到参数struts.objectFactory对应的值,原则是后面找到的覆盖前面找到的。若我们没有再struts.xml中
配置struts.objectFactory对应的值,则将以struts-plugin.xml中的struts.objectFactory=spring为准。如此
struts、spring整合后action就由spring来创建了。创建方式不难想到,struts会拿action标签中的name属性值到spring容器中
找对应的id拿到action实例(多例)。因此不难理解action的name属性值必须与spring中对应action类的bean的id一致。
关于no Session的异常
对于事务方法,在方法的开始到结束期间session均为开启状态。
对于HibernateTemplate,由于向HibernateDaoSupport中注入了sessionFactory,因此在调用hibernateTemplate
对象的方法期间,session是开启的。
因此如果采用hibernate的懒加载,如调用hibernateTemplate的load方法而不是get方法时,方法返回的对象并不是
从数据库查询返回的对象,只有访问方法的属性时才会到发送SQL语句查询并返回。这时若没有处于事务方法内,而是在前台
页面调用实体类的get方法访问属性会出现no session的异常。
OpenSessionInView,这个过滤器可以解决此问题。将过滤的url写为*.action则可在用户请求action时打开session,在
response返回(即jsp解析完毕后)再关闭session。由过滤器链的特性可知该过滤器一定要方法struts2核心过滤器StrutsPrepareAndExecuteFilter
的后面,否则等StrutsPrepareAndExecuteFilter执行doFilter方法时,action已经执行完毕返回结果页。这样就起不到任何作用。
源码如下
创建ActionContext(在ActionProxy创建之前创建)做的工作
* 在actionContext中存在一个Map<String, Object>
* ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
通过静态注入创建ValueStack的实现类:OgnlValueStack,也就意味着在创建actionContext的时候,值栈就被创建了
* ValueStack中的map栈和ActionContext中的Map是一样的
* 通过ActionContext.setContext(ctx);就把actionContext放入到ThreadLocal中,这样数据就安全了
ActionProxy的创建
* ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
namespace, name, method, extraContext, true, false);
* 在createActionProxy的时候
ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
创建了DefaultActionInvocation
在创建ActionProxy的时候,就已经执行invocation的init方法
invocation的init方法做的事情:
action的创建和所有的拦截器的创建
执行invocation中的inovke方法
* 执行了所有的拦截器
* 执行了当前请求的action
* 执行了结果集