十五、contextMap

1、动作类的生命周期

明确:动作类是多例的,每次动作访问,动作类都会实例化。所以是线程安全的。与Struts1的区别是,struts1的动作类是单例的。

2、请求动作的数据存放

问题:

每次请求时,都会产生一些请求数据,这些数据存放到哪里去了?

 明确:

在每次动作执行前,核心控制器StrutsPrepareAndExecuteFilter都会创建一个ActionContextValueStack对象。且每次动作访问都会创建。

这两个对象存储了整个动作访问期间用到的数据。并且把数据绑定到了线程局部变量(ThreadLocal)上了。所以是线程安全的。

3、contextMap:存储数据

Struts2的官方文档对contextMap的说明:

contextMap中存放的主要内容

Key

Value

说明

value stack (root)

java.util.List

没有root这个key。contextMap中它有key,但是我们不用。它是一个list。(com.opensymphony.xwork2.util.ValueStack.ValueStack是它的key)。

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

参数

attr

java.util.Map

把页面、请求、会话、应用范围内的所有属性放到一起。

注意:

除了value stack之外,全是map,而contextMap也是一个map。其实就是Map中又封装的Map。(很像dbutils中KeyedHandler封装数据的结构,只是封装数据的结构)

查看contextMap中的数据:

在页面上使用<s:debug/>

十六、contextMap中的数据操作

1、存数据:

需要熟悉ActionContext和valueStack的API。框架为我们存数据。

1.1、利用ActionContext存数据

 public String demo1(){
//1.获取到ActionContext对象
ActionContext context = ActionContext.getContext();//从当前线程上获取
//2.往大map中存入数据
context.put("contextMap", "hello context map"); //3.往指定的小Map中存入数据(request,session,application)
//Map<String,Object> sessionMap = (Map<String, Object>) context.get("session");
//第一种方式:使用map操作
Map<String,Object> sessionMap = context.getSession();
sessionMap.put("sessionMap", "hello session map");
//第二种方式:使用原始ServletAPI存入数据
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("sessionAttr","hello session attribute"); //4.往application的map中存入数据
//第一种方式:使用map操作
Map<String,Object> applicationMap = context.getApplication();
applicationMap.put("applicationMap", "hello application map");
//第二种方式:使用原始ServletAPI对象
ServletContext application = ServletActionContext.getServletContext();
application.setAttribute("applicationAttr", "hello application attribute");
return SUCCESS;
}

1.2、利用ValueStack存数据

a、如何获取ValueStack

 /**
* 利用ValueStack存取数据操作
* 明确:
* 1、它本身是一个List结构,同时具备了栈的特点。
* 2、它里面只能存放对象,没有key,value的概念。
* @author zhy
*
*/
public class Demo2Action extends ActionSupport { private String name = "泰斯特"; public String demo2(){
//1.获取valueStack
//先获取ActionContext
ActionContext context = ActionContext.getContext();
context.put("contextMap", "hello context map");
//再使用ActionContext中的getValueStack方法获取
ValueStack vs = context.getValueStack();
/*
* 压栈操作
*/
Student s1 = new Student("test",18,"male");
vs.push(s1); Student s2 = new Student("test1",20,"female");
vs.push(s2); return SUCCESS;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }

b、ValueStack中的getRoot()方法:

c、CompoundRoot是什么:

d、栈操作:

2、取数据:用Struts2的标签(OGNL表达式)在JSP上

使用OGNL表达式来去,struts2的OGNL表达式必须写在struts2标签中。

2.1、使用s:property取数据

a、取contextMap中的数据,需使用#

 <body>
<%--1.获取ValueStack中的数据 :
当我们使用s:property不指定value属性时,默认获取的是栈顶元素(对象)
注意:获取的是一个对象。
只有不使用value属性时,才获取的是对象。
剩余的情况全是:
根据属性名称获取属性值!!!!!!!!
--%>
<s:property/>
<hr/>
<%--2.获取指定属性的值
当s:property标签的value属性没有使用#号时,是从ValueStack中获取数据
把value的取值当做property name,从栈顶逐个元素往下寻找,找和value取值一样的属性,
找到了,把值获取回来。只要找到了,就不再继续寻找。 获取valueStack中的数据,不用写#号。并且直接写属性名称即可。
--%>
<s:property value="name"/>
<hr/>
<%--3.获取指定位置指定属性的值
[1]表示的不是属性名称出现的索引位置。
而是指的集合中元素(对象)的索引位置。 当我们使用[n].propertyname方式获取值时,它就是把栈中下标为n的元素看成是栈顶元素,逐个往下寻找。
--%>
<s:property value="[1].name"/>
<hr/>
<%--4.ValueStack中的findValue方法 --%>
<% ActionContext ac = ActionContext.getContext();
ValueStack vs = ac.getValueStack();
Object obj = vs.findValue("name");
Object obj1 = vs.findValue("[2].name");
out.print(obj);
out.print("<hr/>");
out.print(obj1);
out.print("<hr/>");
Object obj2 = vs.findValue("#contextMap");
out.print("aaaa:"+obj2);
%>
<%-- <s:property value="#contextMap"/> --%>
<s:debug/>
</body>

b、取contextMap里面ValueStack中对象的属性:直接写属性名

1               <tr>
<td><s:property value="name"/></td>
<td><s:property value="age"/></td>
<td><s:property value="gender"/></td>
</tr>

OGNL的使用总结:

1.取中对象的属性不使用#

2.取contextMapkey的值,要使用#

2.2、ValueStack的findValue方法(我们在Jsp上调用的都是findValue)

十七、Struts2对EL的改变

1、Struts2中使用EL的问题:

前提:

我们应该知道,如果我们没有往值栈(根)中放入数据的话,那么我们的动作类默认是在值栈的栈顶。

问题:

我们放到请求域中的属性,使用EL表达式取出来了。但是放到应用域中的属性,使用EL表达式没取出来。

2、关于EL问题的分析:

分析:

我们知道EL表达式是从四大域对象中依次查找属性。搜索范围是由小到大。page Scope————>request Scope————>sessionScope————>application Scope

但是通过测试发现,搜索完request范围后就没有继续搜索,而是返回了ValueStack中栈顶对象name属性的值。

3、Struts2中EL查找顺序改变总结:

EL表达式: page Scope————>request Scope————>sessionScope————>application Scope

OGNL表达式:page Scope————>request Scope————>valueStack(根中)————>contextMap————>sessionScope————>application Scope

4、OGNL的特殊说明:

 public String demo3(){
//1.获取HttpServletRequest的对象
HttpServletRequest request = ServletActionContext.getRequest();
//2.往请求域中存放一个name
//request.setAttribute("name", "请求域中的name");
//3.获取HttpSession
HttpSession session = request.getSession();
session.setAttribute("name", "会话域中的name"); ActionContext context = ActionContext.getContext();
context.put("name", "大Map中的name"); return SUCCESS;
}

十八、OGNL配合通用标签的其他使用

1、iterator标签

 /**
* iterator标签的使用
* @author zhy
*
*/
public class Demo4Action extends ActionSupport { private List<Student> students; public String demo4(){
//1.获取HttpServletRequest的对象
//HttpServletRequest request = ServletActionContext.getRequest();
//就相当于从数据库中获取学生列表
students = new ArrayList<Student>();
students.add(new Student("test1",18,"male"));
students.add(new Student("test2",21,"female"));
students.add(new Student("test3",22,"male"));
//2.把查询出来的学生列表存入请求域中
//request.setAttribute("students", students); return SUCCESS;
} public List<Student> getStudents() {
return students;
} public void setStudents(List<Student> students) {
this.students = students;
}
}
         <s:iterator value="students">
<tr>
<td><s:property value="name"/></td>
<td><s:property value="age"/></td>
<td><s:property value="gender"/></td>
</tr>
</s:iterator>

2、Struts2中#,$,%符号的使用

2.1、#

a、取ActionContext中key时使用,例如<s:property value="#name" />

b、OGNL中创建Map对象时使用,例如:<s:radio list="#{'male':'男','female':'女'}" />

2.2、$

a、在JSP中使用EL表达式时使用,例如${name}

b、在xml配置文件中,编写OGNL表达式时使用,例如文件下载时,文件名编码。struts.xml——>${@java.net.URLEncoder.encode(filename,"UTF-8")}

2.3、%

在struts2中,有些标签的value属性取值就是一个OGNL表达式,例如<s:property value="OGNL Expression" />

还有一部分标签,value属性的取值就是普通字符串,例如<s:textfield value="username"/>,如果想把一个普通的字符串强制看成时OGNL,就需要使用%{}把字符串套起来。

例如<s:textfield value="%{username}"/>。当然在<s:property value="%{OGNL Expression}" />也可以使用,但不会这么用。

3、其他标签

3.1、if标签,elseif标签 else标签

 <%--1、s:if s:elseif s:else
作用:
进行条件判断。
属性:
test里面的内容是一个逻辑运算,返回的结果应该是一个布尔类型值。
可以使用常量运算,还可以是OGNL表达式的逻辑 运算 test的取值可以是OGNL表达式,但是只能在ValueStack中取值 --%>
<%--没有经过动作类
ActionContext ac = ActionContext.getContext();
ac.put("name", "test");
--%>
<s:if test="name == null">
用户名没有了
</s:if>
<s:elseif test="#name == 'test'">
是一个测试用户
</s:elseif>

3.2、url和a标签

 <%--2、s:url 和 s:a
s:url标签:
作用:是把指定路径存入contextMap中
属性:
action:直接写动作名称。不用再写${pageContext.request.contextPath}
namespace:指定动作所在的名称空间,如果该动作是在默认名称空间下可以不写
var:取值是一个普通字符串。把var的取值当做key,把action的取值当做value,存入contextMap中
s:param标签:
作用:是给s:url或者s:a添加请求参数
属性:
name:参数的名称
value:参数的值.它的取值是一个OGNL表达式.
s:a标签:
作用:和超链接标签是一样的。并且可以和s:url互换
--%>
<s:url action="action1" var="action1_url">
<s:param name="param1" value="'hello'"></s:param>
</s:url>
<a href="<s:property value="#action1_url"/>">let me see see</a> <br/>
<a href="${pageContext.request.contextPath}/action1.action">让我们看看</a>
<br/> <s:a action="action1" namespace="">
<s:param name="param1" value="'hello'"></s:param>
去action1 看看
</s:a>

3.3、date标签

 <%--3、s:date --%>
<font color="red">我们想要的输出结果是:2016-05-30 或者是 2016年05月30日</font><br/>
<%--s:date标签:
作用:格式化输出日期
属性:
name:取值是一个OGNL表达式。指定的是要转换的日期对象
format:指定转换的格式
var:取值是一个普通的字符串。把var的值当做key,把转换好的日期当成value,存入contextMap中
--%>
<s:date name="birthday" format="yyyy-MM-dd" var="sbirthday"/>
<%--
DateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
String date = format.format(birthday);
out.print(date);
--%> <s:property value="#sbirthday"/>

Java实战之01Struts2-05contextMAP、EL、OGNL的更多相关文章

  1. Java实战之04JavaWeb-04JSP、EL表达式、JSTL标签库

    一.jsp部分 只要是与页面显示相关的都是重点 1.jsp的脚本 <%java代码%>:被翻译到service方法内部,局部变量,局部的功能 <%=表达式或变量%>:翻译成se ...

  2. Tomcat6环境JBPM4.4报错:java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver

    Tomcat6环境JBPM4.4报错:java.lang.ClassNotFoundException: de.odysseus.el.util.SimpleResolver 报错信息:

  3. 「小程序JAVA实战」springboot的后台搭建(31)

    转自:https://idig8.com/2018/08/29/xiaochengxujavashizhanspringbootdehoutaidajian31/ 根据下面的图,我们来建立下对应的sp ...

  4. JAVA基础之JSP与EL技术、JSTL技术

    要牢记jsp四大作用域(pageContext域:当前jsp页面范围      request域:一次请求   session域:一次会话   application域:整个web应用)以及九大内置对 ...

  5. Java Web学习笔记之---EL和JSTL

    Java Web学习笔记之---EL和JSTL (一)EL (1)EL作用 Expression  Language(表达式语言),目的是代替JSP页面中复杂的代码 (2)EL表达式 ${变量名} ( ...

  6. Java实战:教你如何进行数据库分库分表

    摘要:本文通过实际案例,说明如何按日期来对订单数据进行水平分库和分表,实现数据的分布式查询和操作. 本文分享自华为云社区<数据库分库分表Java实战经验总结 丨[绽放吧!数据库]>,作者: ...

  7. Java实战之01Struts2-04拦截器、上传下载、OGNL表达式

    十二.Struts2中的拦截器 1.拦截器的重要性 Struts2中的很多功能都是由拦截器完成的.比如:servletConfig,staticParam,params,modelDriven等等. ...

  8. java实战之解析xml

    在java中解析xml有现成的包提供方法,常用的有四类:Dom,JDom,Sax以及Dom4j.其中前者是java中自带的,后三者需要大家从开源诸如sourceforge这样的网站下载jar包,然后在 ...

  9. Java实战之03Spring-02Spring的核心之IoC

    二.Spring的核心之IoC(Inversion of Control 控制反转) 1.IoC是什么? 回顾:连接池原理中的使用. 注意:我们在连接池原理中是使用构造函数注入的,当然还可以通过提供s ...

随机推荐

  1. tmux快捷键`

    Ctrl+b 激活控制台:此时以下按键生效 系统操作 ? 列出所有快捷键:按q返回 d 脱离当前会话:这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话 D 选择要脱离的 ...

  2. YUV格式总结

    1. YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL),是PAL和SECAM模拟彩色电视制式采用的颜色空间.在现代彩色电视系统中,通常采用三管彩色摄影机或彩色CCD摄影机进行取像,然后把取 ...

  3. POJ2250 - Compromise(LCS+打印路径)

    题目大意 给定两段文本,问公共单词有多少个 题解 裸LCS... 代码: #include<iostream> #include<string> using namespace ...

  4. iOS xcodebuild 打包app

    1.传统的app打包(没有使用cocopods) 在打包之前,先把证书和配置文件选好. step1:打开终端,cd 进入到工程目录中 step2:xcodebuild clean(如果buid文件存在 ...

  5. ORA-01653:表空间扩展失败的问题(开启表空间自动扩展)

    ----查询表空间使用情况---使用DBA权限登陆SELECT UPPER(F.TABLESPACE_NAME) "表空间名",D.TOT_GROOTTE_MB "表空间 ...

  6. MultiTouch camera controls source code

    http://www.jpct.net/wiki/index.php/MultiTouch_camera_controls MultiTouch camera controls This code w ...

  7. Entity Framework 教程(转)

    预备知识    2 LINQ技术    2 LINQ技术的基础 - C#3.0    2 自动属性    2 隐式类型    2 对象初始化器与集合初始化器    3 匿名类    3 扩展方法    ...

  8. Kivy A to Z -- 怎样从python代码中直接訪问Android的Service

    在Kivy中,通过pyjnius扩展能够间接调用Java代码,而pyjnius利用的是Java的反射机制.可是在Python对象和Java对象中转来转去总让人感觉到十分别扭.好在android提供了b ...

  9. jstl前台Jsp日期格式化

    1. 引入fmt标签 <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %&g ...

  10. TCP并发server,每个客户一个子进程

    今天笔者带来的是server型号第一,这是最经常使用的模型的最基本的一个–TCP并发server,每个客户一个子进程. 首先简单介绍:TCP并发server,每个客户一个子进程,并发server调用f ...