1. 动作类的生命周期
明确:
- 动作类是多例的,每次访问Action,动作类都会被实例化。所以是线程安全的。
- 相比较于Servlet,Servlet是单例的,其访问地址自被实例化后就不会改变
- 与Struts1的区别是,Struts1的动作类是单例的。
2. 请求数据的存放
每次访问Action,都会实例化一次Action,那么是如何实现多例化,并且存放每个Action的相关信息的呢?
明确:
- 在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建该Action专属的ActionContext和ValueStack对象。且每次动作访问都会创建。
- 这两个对象存储了整个动作访问期间用到的数据。
- 并且把数据绑定到了线程局部变量(ThreadLocal)上了。所以是线程安全的。
3. contextMap存储数据
contextMap<=>ActionContext中可以存放的数据 | ||
Key | Value | 说明 |
value stack (root) | java.util.List | 没有root这个key。它是一个list。 |
application | java.util.Map<String,Object> | ServletContext中的所有属性。 |
session | java.util.Map<String,Object> | HttpSession中的所有属性。 |
request | java.util.Map<String,Object> | ServletRequest中的所有属性。 |
parameters | java.util.Map<String,Object> | 参数 |
attr | java.util.Map<String,Object> | 把页面、请求、会话、应用范围内的所有属性放到一起。 |
其实质就是Map里面套map(因为contextMap本身是一个map集合)
- 可以使用<s:debug></s:debug>查看contextMap的数据(在struts context区域中)
4. 往contextMap中存数据
root根:List
| ||||||||||
contextMap:Map
|
A. 利用ActionContext存数据
访问该action跳转test.jsp页面,test.jsp页面使用<s:debug>标签查看contextMap中相应的值是否存取成功
B. 利用ValueStack存数据
5. 从contextMap中读取数据
如果遇有对象属性重名,可以通过OGNL表达式,选择查找的起始位置
在action里设置了一个username,但是在ValueStack中存储的还有个username
那么这个时候当在使用ognl取值的时候需要指定其取值的位置,像下面这样
6. ValueStack的其他方法
a. setValue方法
1. key
2. #key
b. set方法
c. findValue方法
在jsp页面上调用findValue方法找到一个存在valueStack中的值
7. Struts2中对EL的取值顺序的改变
EL:
pageContext(page) > request > session > servletContext(application)
OGNL:
page –> request -> valueStack(根中)-> contextMap -> session -> application
以前要用Servlet的时候,在jsp中取数据一般从request中取
如果使用了struts2,在jsp中取数据一般从ValueStack中取
实现源码:
通过struts请求包装类StrutsRequestWrapper来实现对请求数据的封装