动作类的生命周期
明确:动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的。与Struts1的区别是,struts1的动作类是单例的。
请求动作的数据存放
在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter
都会创建一个ActionContext
和ValueStack
对象。且每次动作访问都会创建。
这两个对象存储了整个动作访问期间用到的数据。并且把数据绑定到了线程局部变量(ThreadLocal)上了。所以是线程安全的。
contextMap:存储数据
Key | Value | 说明 |
---|---|---|
value stack (root) | java.util.List | 没有root这个key。它是一个list。 |
application | java.util.Map |
ServletContext中的所有属性。 |
session | java.util.Map |
HttpSession中的所有属性。 |
request | java.util.Map |
ServletRequest中的所有属性。 |
parameters | java.util.Map | 参数 |
attr | java.util.Map | 把页面、请求、会话、应用范围内的所有属性放到一起。 |
Struts2的官方文档对contextMap的说明:
Key | Value | 说明 |
---|---|---|
value stack (root) | java.util.List | 没有root这个key。它是一个list。 |
application | java.util.Map |
ServletContext中的所有属性。 |
session | java.util.Map |
HttpSession中的所有属性。 |
request | java.util.Map |
ServletRequest中的所有属性。 |
parameters | java.util.Map | 参数 |
attr | java.util.Map | 把页面、请求、会话、应用范围内的所有属性放到一起。 |
注意:
除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又封装的Map。(很像dbutils中KeyedHandler封装数据的结构,只是封装数据的结构)
查看contextMap中的数据:
在页面上使用
contextMap中的数据操作
1、存数据
- 利用ActionContext存数据
public String execute() throws Exception {
ActionContext context = ActionContext.getContext();
context.put("contextMap","hello contextMap");//把数据存到大map中
// 往session中存数据
//第一种,获取key为session的map
Map session = context.getSession();
session.put("sessionMap", "hello sessionMap");
//第二种
HttpSession session1 = ServletActionContext.getRequest().getSession();
session1.setAttribute("sessionMap1","hello sessionMap1");
//往servletContext域中存数据
//第一种
Map application = context.getApplication();
application.put("servletContext", "hello servletContext");
//第二种
ServletContext servletContext = ServletActionContext.getServletContext();
servletContext.setAttribute("servletContext1","hello servletContext1");
return SUCCESS;
}
- 利用ValueStack存数据
public class ValueStackDemo extends ActionSupport {
private String username = "ljb2";
@Override
public String execute() throws Exception {
//第一种,获取HttpServletRequest对象,通过对象的getAttribute方法
HttpServletRequest request = ServletActionContext.getRequest();
ValueStack vs1 = (ValueStack) request.getAttribute("struts.valueStack");
System.out.println(vs1.hashCode());
//第二种
ActionContext context = ActionContext.getContext();
Map request1 = (Map) context.get("request");
ValueStack vs2 = (ValueStack) request1.get("struts.valueStack");
System.out.println(vs2.hashCode());
//第三种
ValueStack valueStack = context.getValueStack();
System.out.println(valueStack.hashCode());
Student student = new Student();
student.setUsername("ljb");
//压栈操作
valueStack.push(student);
//其他方法
valueStack.setValue("#username","bobo");//带#数据存到contextMap中
valueStack.setValue("username","哈哈");//把valueStack中第一个username属性的值换成哈哈,如果没有一个username属性,会报错
return SUCCESS;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
2、取数据:用Struts2的标签(OGNL表达式)在JSP上(用的最多)
使用OGNL表达式来去,struts2的OGNL表达式必须写在struts2标签中。
- 使用s:property取数据
取数据
获取大Map中数据
获取小map中的数据
- 取contextMap里面ValueStack中对象的属性:直接写属性名
OGNL的使用总结:
1.取根中对象的属性,不使用#。
2.取contextMap中key的值,要使用#。