一、ContextMap
1、概述
- 它是OGNL上下文对象,是struts2中封装数据最大的对象
- 我们一次请求中所有用到的信息都可以在它里面找到
- 它是一个Map结构的对象,其中key是字符串,value是一个Object
2、ContextMap中封装的数据
Map的key(类型是String) |
Map的Value (类型是Object) |
说明信息 |
application |
Java.util.Map<String,Object> |
封装的应用域中的所有数据 |
session |
Java.util.Map<String,Object> |
封装的会话域中的所有数据 |
request |
Java.util.Map<String,Object> |
封装的请求域中的所有数据 |
valueStack(特殊) |
com.opensymphony.xwork2.ognl.OgnlValueStack |
它是List结构 |
parameters |
Java.util.Map<String,String[]> |
封装的是请求参数 |
attr |
Java.util.Map<String,Object> |
封装的是四大域的组合数据,从最小的域开始搜索 |
action |
com.opensymphony.xwork2.ActionSupport |
当前执行的动作类对象 |
用颜色把它区分开,目的是让我们明确一件事:
蓝色的:是我们已经会了的
四大域对象在jsp那天就已经学过了
绿色的:是我们不用管的。
parameters:现在我们已经会用模型驱动了,所以再也不用自己取了
attr:由于ContextMap中已经包含了三大域,page域的范围又太小了
action:在后面我们讲的值栈中,会提供这个当前执行的动作类
红色的:它是我们第一次接触的,以前不会。而且是struts2中经常用的,所以它是重点!
3、ContextMap的结构
二、ActionContext
1.什么是ActionContext
它是一个工具类,是struts2框架提供给我们的,可以让我们调用其中的方法,快速的操作ContextMap。用它操作OGNL上下文对象,比直接操作ContextMap要方便很多。
2.ActonContext和ContextMap的关系
ActionContext就相当于对ContextMap进行了一次再封装。
3.ActionContext什么时候创建
由于ActionContext是操作的ContextMap,而ContextMap中封了我们一次请求的所有数据,所以它的创建应该是每次请求访问Action时,即核心控制器(StrutsPrepareAndExecuteFilter)的doFilter方法执行时
4.ActionContext是线程安全的吗?
是线程安全的
5.获取ContextMap中的数据
package com.itheima.web;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class Demo01Action extends ActionSupport {
public String execute() {
// ServletActionContext.getRequest().getSession().setAttribute("sess",
// "session1");
ActionContext context = ActionContext.getContext();
// 1.给定的方法
// Map<String, Object> session = context.getSession();
// 2.原生的代码
Map<String, Object> session = (Map<String, Object>) context.get("session");
session.put("sess", "向session域中存值");
return SUCCESS;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 开启开发者模式 -->
<constant name="struts.devMode" value="true" />
<!-- 开启静态方法调用 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
<package name="default" namespace="/" extends="struts-default">
<action name="demo1" class="com.itheima.web.Demo01Action">
<result name="success">/2.jsp</result>
</action>
</package>
</struts>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<s:debug/>
<s:property value="#session.sess"/>
</body>
</html>
结果
三、ValueStack对象(值栈)
1. ValueStack对象概述
-
ValueStack是Struts的一个接口,OgnlValueStack是ValueStack的实现类
-
客户端发起一个请求struts2架构会创建一个action实例同时创建一个OgnlValueStack值栈实例
-
OgnlValueStack贯穿整个 Action 的生命周期
-
ValueStack是ContextMap中的一部分,里面的结构是一个List,是我们可以快速访问数据一个容器
-
ValueStack的封装是由struts2框架完成的
-
在我们不操作值栈时,默认的栈顶对象是当前执行的动作类
通常情况下我们是从页面上获取数据。它实现了栈的特性(先进后出)
2. ValueStack的内部结构
在 OgnlValueStack中包含了一个CompoundRoot的对象,该对象继承了ArrayList,并且提供了只能操作集合第一个元素的方法,所以我们说它实现了栈的特性。同时,它里面定义了一个ContextMap的引用,也就是说,我们有值栈对象,也可以通过值栈来获取ContextMap
ValueStack是操作list集合的一个工具类,而当前list是一个栈结构
把数据存储到值栈,struts2框架自动(自动)操作栈顶元素
3.获取值栈中的数据
值栈中有什么?
值栈中存的都是对象。因为它本质就是一个List,List中只能存对象
在我们不操作值栈时,默认的栈顶对象是当前执行的动作类
从值栈中获取什么?
一般情况下,我们都是根据debug标签中显示的Property Name来获取Property Value
案例
package com.itheima.web;
import com.itheima.domain.User;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
/**
* @ClassName: Demo02Action
* @Description:操作值栈数据
* @author jsz
* @date 2018年8月25日
*/
public class Demo02Action extends ActionSupport {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
private String username = "jack";
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String execute() {
// 获取ActionContext对象
ActionContext context = ActionContext.getContext();
// 获取值栈对象
ValueStack valueStack = context.getValueStack();
User user1 = new User();
user1.setUsername("jerry");
// 压栈
valueStack.push(user1);
return SUCCESS;
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 开启开发者模式 -->
<constant name="struts.devMode" value="true" />
<!-- 开启静态方法调用 -->
<constant name="struts.ognl.allowStaticMethodAccess" value="true"/>
<package name="default" namespace="/" extends="struts-default">
<action name="demo2" class="com.itheima.web.Demo02Action">
<result name="success">/2.jsp</result>
</action>
</package>
</struts>
页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 获取成员变量的值 -->
<s:property value="[0].user.username"/>
<s:property value="user.username"/>
<!-- 获取局部变量中的值 -->
<s:property value="username"/>
<s:property value="[1].username"/>
<s:debug />
</body>
</html>
Struts2中使用EL表达式
EL表达式原来的搜素顺序:
pageScope——>requestScope——>sessionScope——>applicationScope
struts2中EL表达式改变后的搜索顺序:
pageScope—>requestScope—>valueStack—>contextMap->sessionScope—>applicationScope
struts2框架对request对象进行了包装,并且对getAttribute方法进行了增强,代码如下:
${username} == PageContext.findAttribute(“username”);
符号总结
#:
获取大Map中数据,把后面的内容看成是key。
在使用struts2标签,创建Map对象时使用
<s:radio list="#{}">
%:
使用%{''}把OGNL表达式强制看成是普通字符串
$:
使用EL表达式的标识
<input type="text" name="username" value="${username}"/>